summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt21
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx37
-rw-r--r--Source/CPack/cpack.cxx8
-rw-r--r--Source/CTest/cmCTestBinPacker.cxx132
-rw-r--r--Source/CTest/cmCTestBinPacker.h10
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx105
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h32
-rw-r--r--Source/CTest/cmCTestProcessesLexerHelper.cxx55
-rw-r--r--Source/CTest/cmCTestResourceAllocator.cxx (renamed from Source/CTest/cmCTestHardwareAllocator.cxx)20
-rw-r--r--Source/CTest/cmCTestResourceAllocator.h (renamed from Source/CTest/cmCTestHardwareAllocator.h)10
-rw-r--r--Source/CTest/cmCTestResourceGroupsLexerHelper.cxx55
-rw-r--r--Source/CTest/cmCTestResourceGroupsLexerHelper.h (renamed from Source/CTest/cmCTestProcessesLexerHelper.h)12
-rw-r--r--Source/CTest/cmCTestResourceSpec.cxx (renamed from Source/CTest/cmCTestHardwareSpec.cxx)28
-rw-r--r--Source/CTest/cmCTestResourceSpec.h (renamed from Source/CTest/cmCTestHardwareSpec.h)10
-rw-r--r--Source/CTest/cmCTestRunTest.cxx36
-rw-r--r--Source/CTest/cmCTestRunTest.h40
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx6
-rw-r--r--Source/CTest/cmCTestTestCommand.h2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx28
-rw-r--r--Source/CTest/cmCTestTestHandler.h12
-rw-r--r--Source/Checks/Curses.cmake9
-rw-r--r--Source/Checks/cm_c11_thread_local.cmake10
-rw-r--r--Source/Checks/cm_cxx14_check.cmake10
-rw-r--r--Source/Checks/cm_cxx17_check.cmake10
-rw-r--r--Source/Checks/cm_cxx_features.cmake10
-rw-r--r--Source/Checks/cm_message_checks_compat.cmake13
-rw-r--r--Source/CursesDialog/CMakeLists.txt25
-rw-r--r--Source/CursesDialog/ccmake.cxx2
-rw-r--r--Source/CursesDialog/cmCursesBoolWidget.cxx15
-rw-r--r--Source/CursesDialog/cmCursesColor.cxx29
-rw-r--r--Source/CursesDialog/cmCursesColor.h24
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx24
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.h4
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx132
-rw-r--r--Source/CursesDialog/cmCursesMainForm.h19
-rw-r--r--Source/CursesDialog/cmCursesOptionsWidget.cxx10
-rw-r--r--Source/CursesDialog/cmCursesPathWidget.cxx8
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx10
-rw-r--r--Source/LexerParser/.gitattributes4
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.cxx (renamed from Source/LexerParser/cmCTestProcessesLexer.cxx)168
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.h (renamed from Source/LexerParser/cmCTestProcessesLexer.h)252
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.in.l (renamed from Source/LexerParser/cmCTestProcessesLexer.in.l)38
-rw-r--r--Source/QtDialog/CMakeLists.txt4
-rw-r--r--Source/cmCTest.cxx63
-rw-r--r--Source/cmCTest.h10
-rw-r--r--Source/cmCoreTryCompile.cxx208
-rw-r--r--Source/cmExportInstallFileGenerator.cxx15
-rw-r--r--Source/cmFindPackageCommand.cxx8
-rw-r--r--Source/cmForEachCommand.cxx145
-rw-r--r--Source/cmGeneratorExpression.cxx14
-rw-r--r--Source/cmGeneratorExpression.h3
-rw-r--r--Source/cmGeneratorTarget.cxx163
-rw-r--r--Source/cmGeneratorTarget.h33
-rw-r--r--Source/cmGlobalGenerator.cxx4
-rw-r--r--Source/cmGlobalGenerator.h3
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx5
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h3
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx36
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h8
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx12
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx29
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmGraphVizWriter.cxx723
-rw-r--r--Source/cmGraphVizWriter.h93
-rw-r--r--Source/cmInstallTargetGenerator.cxx8
-rw-r--r--Source/cmLinkItemGraphVisitor.cxx142
-rw-r--r--Source/cmLinkItemGraphVisitor.h75
-rw-r--r--Source/cmLocalGenerator.cxx6
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmMakefile.cxx2
-rw-r--r--Source/cmMessageCommand.cxx135
-rw-r--r--Source/cmProjectCommand.cxx5
-rw-r--r--Source/cmSourceFile.h5
-rw-r--r--Source/cmSourceGroupCommand.cxx14
-rw-r--r--Source/cmStateSnapshot.cxx4
-rw-r--r--Source/cmSystemTools.cxx9
-rw-r--r--Source/cmTarget.cxx4
-rw-r--r--Source/cmVariableWatch.cxx14
-rw-r--r--Source/cmVariableWatch.h4
-rw-r--r--Source/cmVariableWatchCommand.cxx65
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx19
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h1
-rw-r--r--Source/cmake.cxx19
-rw-r--r--Source/cmake.h32
-rw-r--r--Source/cmakemain.cxx1
-rw-r--r--Source/ctest.cxx9
-rw-r--r--Source/kwsys/Encoding.hxx.in2
-rw-r--r--Source/kwsys/EncodingCXX.cxx14
-rw-r--r--Source/kwsys/RegularExpression.hxx.in6
90 files changed, 2239 insertions, 1432 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 63e08de0f5..d050fb7f61 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -289,6 +289,8 @@ set(SRCS
cmGeneratorExpression.h
cmGeneratorTarget.cxx
cmGeneratorTarget.h
+ cmLinkItemGraphVisitor.cxx
+ cmLinkItemGraphVisitor.h
cmGetPipes.cxx
cmGetPipes.h
cmGlobalCommonGenerator.cxx
@@ -919,14 +921,14 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
- CTest/cmCTestHardwareAllocator.cxx
- CTest/cmCTestHardwareSpec.cxx
+ CTest/cmCTestResourceAllocator.cxx
+ CTest/cmCTestResourceSpec.cxx
CTest/cmCTestLaunch.cxx
CTest/cmCTestMemCheckCommand.cxx
CTest/cmCTestMemCheckHandler.cxx
CTest/cmCTestMultiProcessHandler.cxx
- CTest/cmCTestProcessesLexerHelper.cxx
CTest/cmCTestReadCustomFilesCommand.cxx
+ CTest/cmCTestResourceGroupsLexerHelper.cxx
CTest/cmCTestRunScriptCommand.cxx
CTest/cmCTestRunTest.cxx
CTest/cmCTestScriptHandler.cxx
@@ -958,9 +960,9 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestP4.cxx
CTest/cmCTestP4.h
- LexerParser/cmCTestProcessesLexer.cxx
- LexerParser/cmCTestProcessesLexer.h
- LexerParser/cmCTestProcessesLexer.in.l
+ LexerParser/cmCTestResourceGroupsLexer.cxx
+ LexerParser/cmCTestResourceGroupsLexer.h
+ LexerParser/cmCTestResourceGroupsLexer.in.l
)
# Build CTestLib
@@ -1177,7 +1179,7 @@ if(WIN32)
unset(CMake_RCVERSION_MONTH_DAY)
unset(CMake_RCVERSION_YEAR)
else()
- set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH},0)
endif()
set(CMake_RCVERSION_STR ${CMake_VERSION})
@@ -1193,6 +1195,11 @@ if(WIN32)
endforeach()
endif()
+if(CMake_JOB_POOL_LINK_BIN)
+ set_property(TARGET ${_tools} PROPERTY JOB_POOL_LINK "link-bin")
+ set_property(GLOBAL APPEND PROPERTY JOB_POOLS "link-bin=${CMake_JOB_POOL_LINK_BIN}")
+endif()
+
# Install tools
foreach(_tool ${_tools})
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f72da64cdb..41bde355a6 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,8 +1,8 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 16)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 3)
+set(CMake_VERSION_PATCH 20191112)
+#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
# Start with the full version number used in tags. It has no dev info.
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index adea8ecd15..f90a740ef7 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -129,14 +129,13 @@ int cmCPackNSISGenerator::PackageFiles()
this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
std::string installerIconCode;
if (this->IsSet("CPACK_NSIS_MUI_ICON")) {
- installerIconCode += "!define MUI_ICON \"";
- installerIconCode += this->GetOption("CPACK_NSIS_MUI_ICON");
- installerIconCode += "\"\n";
+ installerIconCode += cmStrCat(
+ "!define MUI_ICON \"", this->GetOption("CPACK_NSIS_MUI_ICON"), "\"\n");
}
if (this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
- installerIconCode += "!define MUI_UNICON \"";
- installerIconCode += this->GetOption("CPACK_NSIS_MUI_UNIICON");
- installerIconCode += "\"\n";
+ installerIconCode +=
+ cmStrCat("!define MUI_UNICON \"",
+ this->GetOption("CPACK_NSIS_MUI_UNIICON"), "\"\n");
}
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_ICON_CODE",
installerIconCode.c_str());
@@ -174,6 +173,32 @@ int cmCPackNSISGenerator::PackageFiles()
installerRunCode.c_str());
}
+ if (this->IsSet("CPACK_NSIS_WELCOME_TITLE")) {
+ std::string welcomeTitleCode =
+ cmStrCat("!define MUI_WELCOMEPAGE_TITLE \"",
+ this->GetOption("CPACK_NSIS_WELCOME_TITLE"), "\"");
+ this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE",
+ welcomeTitleCode.c_str());
+ }
+
+ if (this->IsSet("CPACK_NSIS_WELCOME_TITLE_3LINES")) {
+ this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE",
+ "!define MUI_WELCOMEPAGE_TITLE_3LINES");
+ }
+
+ if (this->IsSet("CPACK_NSIS_FINISH_TITLE")) {
+ std::string finishTitleCode =
+ cmStrCat("!define MUI_FINISHPAGE_TITLE \"",
+ this->GetOption("CPACK_NSIS_FINISH_TITLE"), "\"");
+ this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE",
+ finishTitleCode.c_str());
+ }
+
+ if (this->IsSet("CPACK_NSIS_FINISH_TITLE_3LINES")) {
+ this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_3LINES_CODE",
+ "!define MUI_FINISHPAGE_TITLE_3LINES");
+ }
+
// Setup all of the component sections
if (this->Components.empty()) {
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", "");
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 58956522f4..d7868f3465 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -314,7 +314,7 @@ int main(int argc, char const* const* argv)
else {
// get a default value (current working directory)
cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory();
- // use default value iff no value has been provided by the config file
+ // use default value if no value has been provided by the config file
if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {
globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
cpackProjectDirectory);
@@ -324,6 +324,12 @@ int main(int argc, char const* const* argv)
globalMF.AddDefinition(cd.first, cd.second);
}
+ // Force CPACK_PACKAGE_DIRECTORY as absolute path
+ cpackProjectDirectory = globalMF.GetDefinition("CPACK_PACKAGE_DIRECTORY");
+ cpackProjectDirectory =
+ cmSystemTools::CollapseFullPath(cpackProjectDirectory);
+ globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
+
const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
if (cpackModulesPath) {
globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath);
diff --git a/Source/CTest/cmCTestBinPacker.cxx b/Source/CTest/cmCTestBinPacker.cxx
index e9e3beee24..e21b14dd76 100644
--- a/Source/CTest/cmCTestBinPacker.cxx
+++ b/Source/CTest/cmCTestBinPacker.cxx
@@ -23,7 +23,7 @@ namespace {
/*
* The following algorithm is used to do two things:
*
- * 1) Determine if a test's hardware requirements can fit within the hardware
+ * 1) Determine if a test's resource requirements can fit within the resources
* present on the system, and
* 2) Do the actual allocation
*
@@ -34,46 +34,46 @@ namespace {
* more combinations can be tried.
*/
template <typename AllocationStrategy>
-static bool AllocateCTestHardware(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- const std::vector<std::string>& hardwareSorted, std::size_t currentIndex,
+static bool AllocateCTestResources(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ const std::vector<std::string>& resourcesSorted, std::size_t currentIndex,
std::vector<cmCTestBinPackerAllocation*>& allocations)
{
// Iterate through all large enough resources until we find a solution
- std::size_t hardwareIndex = 0;
- while (hardwareIndex < hardwareSorted.size()) {
- auto const& resource = hardware.at(hardwareSorted[hardwareIndex]);
+ std::size_t resourceIndex = 0;
+ while (resourceIndex < resourcesSorted.size()) {
+ auto const& resource = resources.at(resourcesSorted[resourceIndex]);
if (resource.Free() >=
static_cast<unsigned int>(allocations[currentIndex]->SlotsNeeded)) {
// Preemptively allocate the resource
- allocations[currentIndex]->Id = hardwareSorted[hardwareIndex];
+ allocations[currentIndex]->Id = resourcesSorted[resourceIndex];
if (currentIndex + 1 >= allocations.size()) {
// We have a solution
return true;
}
// Move the resource up the list until it is sorted again
- auto hardware2 = hardware;
- auto hardwareSorted2 = hardwareSorted;
- hardware2[hardwareSorted2[hardwareIndex]].Locked +=
+ auto resources2 = resources;
+ auto resourcesSorted2 = resourcesSorted;
+ resources2[resourcesSorted2[resourceIndex]].Locked +=
allocations[currentIndex]->SlotsNeeded;
- AllocationStrategy::IncrementalSort(hardware2, hardwareSorted2,
- hardwareIndex);
+ AllocationStrategy::IncrementalSort(resources2, resourcesSorted2,
+ resourceIndex);
// Recurse one level deeper
- if (AllocateCTestHardware<AllocationStrategy>(
- hardware2, hardwareSorted2, currentIndex + 1, allocations)) {
+ if (AllocateCTestResources<AllocationStrategy>(
+ resources2, resourcesSorted2, currentIndex + 1, allocations)) {
return true;
}
}
// No solution found here, deallocate the resource and try the next one
allocations[currentIndex]->Id.clear();
- auto freeSlots = hardware.at(hardwareSorted.at(hardwareIndex)).Free();
+ auto freeSlots = resources.at(resourcesSorted.at(resourceIndex)).Free();
do {
- ++hardwareIndex;
- } while (hardwareIndex < hardwareSorted.size() &&
- hardware.at(hardwareSorted.at(hardwareIndex)).Free() ==
+ ++resourceIndex;
+ } while (resourceIndex < resourcesSorted.size() &&
+ resources.at(resourcesSorted.at(resourceIndex)).Free() ==
freeSlots);
}
@@ -82,8 +82,8 @@ static bool AllocateCTestHardware(
}
template <typename AllocationStrategy>
-static bool AllocateCTestHardware(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
+static bool AllocateCTestResources(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
// Sort the resource requirements in descending order by slots needed
@@ -99,103 +99,105 @@ static bool AllocateCTestHardware(
});
// Sort the resources according to sort strategy
- std::vector<std::string> hardwareSorted;
- hardwareSorted.reserve(hardware.size());
- for (auto const& hw : hardware) {
- hardwareSorted.push_back(hw.first);
+ std::vector<std::string> resourcesSorted;
+ resourcesSorted.reserve(resources.size());
+ for (auto const& res : resources) {
+ resourcesSorted.push_back(res.first);
}
- AllocationStrategy::InitialSort(hardware, hardwareSorted);
+ AllocationStrategy::InitialSort(resources, resourcesSorted);
// Do the actual allocation
- return AllocateCTestHardware<AllocationStrategy>(
- hardware, hardwareSorted, std::size_t(0), allocationsPtr);
+ return AllocateCTestResources<AllocationStrategy>(
+ resources, resourcesSorted, std::size_t(0), allocationsPtr);
}
class RoundRobinAllocationStrategy
{
public:
static void InitialSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted);
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted);
static void IncrementalSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex);
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
};
void RoundRobinAllocationStrategy::InitialSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted)
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted)
{
std::stable_sort(
- hardwareSorted.rbegin(), hardwareSorted.rend(),
- [&hardware](const std::string& id1, const std::string& id2) {
- return hardware.at(id1).Free() < hardware.at(id2).Free();
+ resourcesSorted.rbegin(), resourcesSorted.rend(),
+ [&resources](const std::string& id1, const std::string& id2) {
+ return resources.at(id1).Free() < resources.at(id2).Free();
});
}
void RoundRobinAllocationStrategy::IncrementalSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex)
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
{
- auto tmp = hardwareSorted[lastAllocatedIndex];
+ auto tmp = resourcesSorted[lastAllocatedIndex];
std::size_t i = lastAllocatedIndex;
- while (i < hardwareSorted.size() - 1 &&
- hardware.at(hardwareSorted[i + 1]).Free() > hardware.at(tmp).Free()) {
- hardwareSorted[i] = hardwareSorted[i + 1];
+ while (i < resourcesSorted.size() - 1 &&
+ resources.at(resourcesSorted[i + 1]).Free() >
+ resources.at(tmp).Free()) {
+ resourcesSorted[i] = resourcesSorted[i + 1];
++i;
}
- hardwareSorted[i] = tmp;
+ resourcesSorted[i] = tmp;
}
class BlockAllocationStrategy
{
public:
static void InitialSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted);
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted);
static void IncrementalSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex);
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
};
void BlockAllocationStrategy::InitialSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
- std::vector<std::string>& hardwareSorted)
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted)
{
std::stable_sort(
- hardwareSorted.rbegin(), hardwareSorted.rend(),
- [&hardware](const std::string& id1, const std::string& id2) {
- return hardware.at(id1).Free() < hardware.at(id2).Free();
+ resourcesSorted.rbegin(), resourcesSorted.rend(),
+ [&resources](const std::string& id1, const std::string& id2) {
+ return resources.at(id1).Free() < resources.at(id2).Free();
});
}
void BlockAllocationStrategy::IncrementalSort(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>&,
- std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex)
+ const std::map<std::string, cmCTestResourceAllocator::Resource>&,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
{
- auto tmp = hardwareSorted[lastAllocatedIndex];
+ auto tmp = resourcesSorted[lastAllocatedIndex];
std::size_t i = lastAllocatedIndex;
while (i > 0) {
- hardwareSorted[i] = hardwareSorted[i - 1];
+ resourcesSorted[i] = resourcesSorted[i - 1];
--i;
}
- hardwareSorted[i] = tmp;
+ resourcesSorted[i] = tmp;
}
}
-bool cmAllocateCTestHardwareRoundRobin(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
+bool cmAllocateCTestResourcesRoundRobin(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
- return AllocateCTestHardware<RoundRobinAllocationStrategy>(hardware,
- allocations);
+ return AllocateCTestResources<RoundRobinAllocationStrategy>(resources,
+ allocations);
}
-bool cmAllocateCTestHardwareBlock(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
+bool cmAllocateCTestResourcesBlock(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
- return AllocateCTestHardware<BlockAllocationStrategy>(hardware, allocations);
+ return AllocateCTestResources<BlockAllocationStrategy>(resources,
+ allocations);
}
diff --git a/Source/CTest/cmCTestBinPacker.h b/Source/CTest/cmCTestBinPacker.h
index 54f03d72fb..ff02b8565c 100644
--- a/Source/CTest/cmCTestBinPacker.h
+++ b/Source/CTest/cmCTestBinPacker.h
@@ -8,7 +8,7 @@
#include <string>
#include <vector>
-#include "cmCTestHardwareAllocator.h"
+#include "cmCTestResourceAllocator.h"
struct cmCTestBinPackerAllocation
{
@@ -20,12 +20,12 @@ struct cmCTestBinPackerAllocation
bool operator!=(const cmCTestBinPackerAllocation& other) const;
};
-bool cmAllocateCTestHardwareRoundRobin(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
+bool cmAllocateCTestResourcesRoundRobin(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations);
-bool cmAllocateCTestHardwareBlock(
- const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
+bool cmAllocateCTestResourcesBlock(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations);
#endif
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 7e8d5482db..9ab3c2eff1 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -140,7 +140,7 @@ void cmCTestMultiProcessHandler::RunTests()
assert(this->Completed == this->Total);
assert(this->Tests.empty());
}
- assert(this->AllHardwareAvailable());
+ assert(this->AllResourcesAvailable());
this->MarkFinished();
this->UpdateCostData();
@@ -171,15 +171,15 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
this->RunningCount += GetProcessorsUsed(test);
cmCTestRunTest* testRun = new cmCTestRunTest(*this);
- if (this->CTest->GetRepeatUntilFail()) {
- testRun->SetRunUntilFailOn();
+ if (this->CTest->GetRerunMode() != cmCTest::Rerun::Never) {
+ testRun->SetRerunMode(this->CTest->GetRerunMode());
testRun->SetNumberOfRuns(this->CTest->GetTestRepeat());
}
testRun->SetIndex(test);
testRun->SetTestProperties(this->Properties[test]);
- if (this->TestHandler->UseHardwareSpec) {
- testRun->SetUseAllocatedHardware(true);
- testRun->SetAllocatedHardware(this->AllocatedHardware[test]);
+ if (this->TestHandler->UseResourceSpec) {
+ testRun->SetUseAllocatedResources(true);
+ testRun->SetAllocatedResources(this->AllocatedResources[test]);
}
// Find any failed dependencies for this test. We assume the more common
@@ -192,10 +192,10 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
// Always lock the resources we'll be using, even if we fail to set the
// working directory because FinishTestProcess() will try to unlock them
- this->AllocateResources(test);
+ this->LockResources(test);
- if (!this->TestsHaveSufficientHardware[test]) {
- testRun->StartFailure("Insufficient hardware");
+ if (!this->TestsHaveSufficientResources[test]) {
+ testRun->StartFailure("Insufficient resources");
this->FinishTestProcess(testRun, false);
return false;
}
@@ -218,26 +218,26 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
return false;
}
-bool cmCTestMultiProcessHandler::AllocateHardware(int index)
+bool cmCTestMultiProcessHandler::AllocateResources(int index)
{
- if (!this->TestHandler->UseHardwareSpec) {
+ if (!this->TestHandler->UseResourceSpec) {
return true;
}
std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
- if (!this->TryAllocateHardware(index, allocations)) {
+ if (!this->TryAllocateResources(index, allocations)) {
return false;
}
- auto& allocatedHardware = this->AllocatedHardware[index];
- allocatedHardware.resize(this->Properties[index]->Processes.size());
+ auto& allocatedResources = this->AllocatedResources[index];
+ allocatedResources.resize(this->Properties[index]->ResourceGroups.size());
for (auto const& it : allocations) {
for (auto const& alloc : it.second) {
- bool result = this->HardwareAllocator.AllocateResource(
+ bool result = this->ResourceAllocator.AllocateResource(
it.first, alloc.Id, alloc.SlotsNeeded);
(void)result;
assert(result);
- allocatedHardware[alloc.ProcessIndex][it.first].push_back(
+ allocatedResources[alloc.ProcessIndex][it.first].push_back(
{ alloc.Id, static_cast<unsigned int>(alloc.SlotsNeeded) });
}
}
@@ -245,14 +245,14 @@ bool cmCTestMultiProcessHandler::AllocateHardware(int index)
return true;
}
-bool cmCTestMultiProcessHandler::TryAllocateHardware(
+bool cmCTestMultiProcessHandler::TryAllocateResources(
int index,
std::map<std::string, std::vector<cmCTestBinPackerAllocation>>& allocations)
{
allocations.clear();
std::size_t processIndex = 0;
- for (auto const& process : this->Properties[index]->Processes) {
+ for (auto const& process : this->Properties[index]->ResourceGroups) {
for (auto const& requirement : process) {
for (int i = 0; i < requirement.UnitsNeeded; ++i) {
allocations[requirement.ResourceType].push_back(
@@ -262,13 +262,13 @@ bool cmCTestMultiProcessHandler::TryAllocateHardware(
++processIndex;
}
- auto const& availableHardware = this->HardwareAllocator.GetResources();
+ auto const& availableResources = this->ResourceAllocator.GetResources();
for (auto& it : allocations) {
- if (!availableHardware.count(it.first)) {
+ if (!availableResources.count(it.first)) {
return false;
}
- if (!cmAllocateCTestHardwareRoundRobin(availableHardware.at(it.first),
- it.second)) {
+ if (!cmAllocateCTestResourcesRoundRobin(availableResources.at(it.first),
+ it.second)) {
return false;
}
}
@@ -276,19 +276,19 @@ bool cmCTestMultiProcessHandler::TryAllocateHardware(
return true;
}
-void cmCTestMultiProcessHandler::DeallocateHardware(int index)
+void cmCTestMultiProcessHandler::DeallocateResources(int index)
{
- if (!this->TestHandler->UseHardwareSpec) {
+ if (!this->TestHandler->UseResourceSpec) {
return;
}
{
- auto& allocatedHardware = this->AllocatedHardware[index];
- for (auto const& processAlloc : allocatedHardware) {
+ auto& allocatedResources = this->AllocatedResources[index];
+ for (auto const& processAlloc : allocatedResources) {
for (auto const& it : processAlloc) {
auto resourceType = it.first;
for (auto const& it2 : it.second) {
- bool success = this->HardwareAllocator.DeallocateResource(
+ bool success = this->ResourceAllocator.DeallocateResource(
resourceType, it2.Id, it2.Slots);
(void)success;
assert(success);
@@ -296,12 +296,12 @@ void cmCTestMultiProcessHandler::DeallocateHardware(int index)
}
}
}
- this->AllocatedHardware.erase(index);
+ this->AllocatedResources.erase(index);
}
-bool cmCTestMultiProcessHandler::AllHardwareAvailable()
+bool cmCTestMultiProcessHandler::AllResourcesAvailable()
{
- for (auto const& it : this->HardwareAllocator.GetResources()) {
+ for (auto const& it : this->ResourceAllocator.GetResources()) {
for (auto const& it2 : it.second) {
if (it2.second.Locked != 0) {
return false;
@@ -312,13 +312,13 @@ bool cmCTestMultiProcessHandler::AllHardwareAvailable()
return true;
}
-void cmCTestMultiProcessHandler::CheckHardwareAvailable()
+void cmCTestMultiProcessHandler::CheckResourcesAvailable()
{
for (auto test : this->SortedTests) {
std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
- this->TestsHaveSufficientHardware[test] =
- !this->TestHandler->UseHardwareSpec ||
- this->TryAllocateHardware(test, allocations);
+ this->TestsHaveSufficientResources[test] =
+ !this->TestHandler->UseResourceSpec ||
+ this->TryAllocateResources(test, allocations);
}
}
@@ -346,7 +346,7 @@ void cmCTestMultiProcessHandler::SetStopTimePassed()
}
}
-void cmCTestMultiProcessHandler::AllocateResources(int index)
+void cmCTestMultiProcessHandler::LockResources(int index)
{
this->LockedResources.insert(
this->Properties[index]->LockedResources.begin(),
@@ -357,7 +357,7 @@ void cmCTestMultiProcessHandler::AllocateResources(int index)
}
}
-void cmCTestMultiProcessHandler::DeallocateResources(int index)
+void cmCTestMultiProcessHandler::UnlockResources(int index)
{
for (std::string const& i : this->Properties[index]->LockedResources) {
this->LockedResources.erase(i);
@@ -404,10 +404,10 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
}
}
- // Allocate hardware
- if (this->TestsHaveSufficientHardware[test] &&
- !this->AllocateHardware(test)) {
- this->DeallocateHardware(test);
+ // Allocate resources
+ if (this->TestsHaveSufficientResources[test] &&
+ !this->AllocateResources(test)) {
+ this->DeallocateResources(test);
return false;
}
@@ -417,7 +417,7 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
}
// This test was not able to start because it is waiting
// on depends to run
- this->DeallocateHardware(test);
+ this->DeallocateResources(test);
return false;
}
@@ -602,8 +602,8 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
this->TestFinishMap[test] = true;
this->TestRunningMap[test] = false;
this->WriteCheckpoint(test);
- this->DeallocateHardware(test);
this->DeallocateResources(test);
+ this->UnlockResources(test);
this->RunningCount -= GetProcessorsUsed(test);
for (auto p : properties->Affinity) {
@@ -912,14 +912,14 @@ static Json::Value DumpTimeoutAfterMatch(
return timeoutAfterMatch;
}
-static Json::Value DumpProcessesToJsonArray(
+static Json::Value DumpResourceGroupsToJsonArray(
const std::vector<
std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
- processes)
+ resourceGroups)
{
- Json::Value jsonProcesses = Json::arrayValue;
- for (auto const& it : processes) {
- Json::Value jsonProcess = Json::objectValue;
+ Json::Value jsonResourceGroups = Json::arrayValue;
+ for (auto const& it : resourceGroups) {
+ Json::Value jsonResourceGroup = Json::objectValue;
Json::Value requirements = Json::arrayValue;
for (auto const& it2 : it) {
Json::Value res = Json::objectValue;
@@ -928,10 +928,10 @@ static Json::Value DumpProcessesToJsonArray(
res["slots"] = it2.SlotsNeeded;
requirements.append(res);
}
- jsonProcess["requirements"] = requirements;
- jsonProcesses.append(jsonProcess);
+ jsonResourceGroup["requirements"] = requirements;
+ jsonResourceGroups.append(jsonResourceGroup);
}
- return jsonProcesses;
+ return jsonResourceGroups;
}
static Json::Value DumpCTestProperty(std::string const& name,
@@ -1005,9 +1005,10 @@ static Json::Value DumpCTestProperties(
"PASS_REGULAR_EXPRESSION",
DumpRegExToJsonArray(testProperties.RequiredRegularExpressions)));
}
- if (!testProperties.Processes.empty()) {
+ if (!testProperties.ResourceGroups.empty()) {
properties.append(DumpCTestProperty(
- "PROCESSES", DumpProcessesToJsonArray(testProperties.Processes)));
+ "RESOURCE_GROUPS",
+ DumpResourceGroupsToJsonArray(testProperties.ResourceGroups)));
}
if (testProperties.WantAffinity) {
properties.append(
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index da716f0bab..1db4bfdd1b 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -14,13 +14,13 @@
#include "cm_uv.h"
-#include "cmCTestHardwareAllocator.h"
+#include "cmCTestResourceAllocator.h"
#include "cmCTestTestHandler.h"
#include "cmUVHandlePtr.h"
class cmCTest;
struct cmCTestBinPackerAllocation;
-class cmCTestHardwareSpec;
+class cmCTestResourceSpec;
class cmCTestRunTest;
/** \class cmCTestMultiProcessHandler
@@ -47,7 +47,7 @@ public:
: public std::map<int, cmCTestTestHandler::cmCTestTestProperties*>
{
};
- struct HardwareAllocation
+ struct ResourceAllocation
{
std::string Id;
unsigned int Slots;
@@ -87,12 +87,12 @@ public:
void SetQuiet(bool b) { this->Quiet = b; }
- void InitHardwareAllocator(const cmCTestHardwareSpec& spec)
+ void InitResourceAllocator(const cmCTestResourceSpec& spec)
{
- this->HardwareAllocator.InitializeFromHardwareSpec(spec);
+ this->ResourceAllocator.InitializeFromResourceSpec(spec);
}
- void CheckHardwareAvailable();
+ void CheckResourcesAvailable();
protected:
// Start the next test or tests as many as are allowed by
@@ -134,16 +134,16 @@ protected:
bool CheckStopTimePassed();
void SetStopTimePassed();
- void AllocateResources(int index);
- void DeallocateResources(int index);
+ void LockResources(int index);
+ void UnlockResources(int index);
- bool AllocateHardware(int index);
- bool TryAllocateHardware(
+ bool AllocateResources(int index);
+ bool TryAllocateResources(
int index,
std::map<std::string, std::vector<cmCTestBinPackerAllocation>>&
allocations);
- void DeallocateHardware(int index);
- bool AllHardwareAvailable();
+ void DeallocateResources(int index);
+ bool AllResourcesAvailable();
// map from test number to set of depend tests
TestMap Tests;
@@ -166,10 +166,10 @@ protected:
std::vector<std::string> LastTestsFailed;
std::set<std::string> LockedResources;
std::map<int,
- std::vector<std::map<std::string, std::vector<HardwareAllocation>>>>
- AllocatedHardware;
- std::map<int, bool> TestsHaveSufficientHardware;
- cmCTestHardwareAllocator HardwareAllocator;
+ std::vector<std::map<std::string, std::vector<ResourceAllocation>>>>
+ AllocatedResources;
+ std::map<int, bool> TestsHaveSufficientResources;
+ cmCTestResourceAllocator ResourceAllocator;
std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
size_t ParallelLevel; // max number of process that can be run at once
unsigned long TestLoad;
diff --git a/Source/CTest/cmCTestProcessesLexerHelper.cxx b/Source/CTest/cmCTestProcessesLexerHelper.cxx
deleted file mode 100644
index 797164bcf1..0000000000
--- a/Source/CTest/cmCTestProcessesLexerHelper.cxx
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCTestProcessesLexerHelper.h"
-
-#include "cmCTestProcessesLexer.h"
-#include "cmCTestTestHandler.h"
-
-cmCTestProcessesLexerHelper::cmCTestProcessesLexerHelper(
- std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
- output)
- : Output(output)
-{
-}
-
-bool cmCTestProcessesLexerHelper::ParseString(const std::string& value)
-{
- yyscan_t lexer;
- cmCTestProcesses_yylex_init_extra(this, &lexer);
-
- auto state = cmCTestProcesses_yy_scan_string(value.c_str(), lexer);
- int retval = cmCTestProcesses_yylex(lexer);
- cmCTestProcesses_yy_delete_buffer(state, lexer);
-
- cmCTestProcesses_yylex_destroy(lexer);
- return retval == 0;
-}
-
-void cmCTestProcessesLexerHelper::SetProcessCount(unsigned int count)
-{
- this->ProcessCount = count;
-}
-
-void cmCTestProcessesLexerHelper::SetResourceType(const std::string& type)
-{
- this->ResourceType = type;
-}
-
-void cmCTestProcessesLexerHelper::SetNeededSlots(int count)
-{
- this->NeededSlots = count;
-}
-
-void cmCTestProcessesLexerHelper::WriteRequirement()
-{
- this->Process.push_back({ this->ResourceType, this->NeededSlots, 1 });
-}
-
-void cmCTestProcessesLexerHelper::WriteProcess()
-{
- for (unsigned int i = 0; i < this->ProcessCount; ++i) {
- this->Output.push_back(this->Process);
- }
- this->Process.clear();
- this->ProcessCount = 1;
-}
diff --git a/Source/CTest/cmCTestHardwareAllocator.cxx b/Source/CTest/cmCTestResourceAllocator.cxx
index 2d1833d488..9d468a7f07 100644
--- a/Source/CTest/cmCTestHardwareAllocator.cxx
+++ b/Source/CTest/cmCTestResourceAllocator.cxx
@@ -1,15 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCTestHardwareAllocator.h"
+#include "cmCTestResourceAllocator.h"
#include <utility>
#include <vector>
-#include "cmCTestHardwareSpec.h"
+#include "cmCTestResourceSpec.h"
-void cmCTestHardwareAllocator::InitializeFromHardwareSpec(
- const cmCTestHardwareSpec& spec)
+void cmCTestResourceAllocator::InitializeFromResourceSpec(
+ const cmCTestResourceSpec& spec)
{
this->Resources.clear();
@@ -23,13 +23,13 @@ void cmCTestHardwareAllocator::InitializeFromHardwareSpec(
}
const std::map<std::string,
- std::map<std::string, cmCTestHardwareAllocator::Resource>>&
-cmCTestHardwareAllocator::GetResources() const
+ std::map<std::string, cmCTestResourceAllocator::Resource>>&
+cmCTestResourceAllocator::GetResources() const
{
return this->Resources;
}
-bool cmCTestHardwareAllocator::AllocateResource(const std::string& name,
+bool cmCTestResourceAllocator::AllocateResource(const std::string& name,
const std::string& id,
unsigned int slots)
{
@@ -51,7 +51,7 @@ bool cmCTestHardwareAllocator::AllocateResource(const std::string& name,
return true;
}
-bool cmCTestHardwareAllocator::DeallocateResource(const std::string& name,
+bool cmCTestResourceAllocator::DeallocateResource(const std::string& name,
const std::string& id,
unsigned int slots)
{
@@ -73,13 +73,13 @@ bool cmCTestHardwareAllocator::DeallocateResource(const std::string& name,
return true;
}
-bool cmCTestHardwareAllocator::Resource::operator==(
+bool cmCTestResourceAllocator::Resource::operator==(
const Resource& other) const
{
return this->Total == other.Total && this->Locked == other.Locked;
}
-bool cmCTestHardwareAllocator::Resource::operator!=(
+bool cmCTestResourceAllocator::Resource::operator!=(
const Resource& other) const
{
return !(*this == other);
diff --git a/Source/CTest/cmCTestHardwareAllocator.h b/Source/CTest/cmCTestResourceAllocator.h
index 441f84d777..9f0b9c95a3 100644
--- a/Source/CTest/cmCTestHardwareAllocator.h
+++ b/Source/CTest/cmCTestResourceAllocator.h
@@ -1,14 +1,14 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCTestHardwareAllocator_h
-#define cmCTestHardwareAllocator_h
+#ifndef cmCTestResourceAllocator_h
+#define cmCTestResourceAllocator_h
#include <map>
#include <string>
-class cmCTestHardwareSpec;
+class cmCTestResourceSpec;
-class cmCTestHardwareAllocator
+class cmCTestResourceAllocator
{
public:
struct Resource
@@ -22,7 +22,7 @@ public:
bool operator!=(const Resource& other) const;
};
- void InitializeFromHardwareSpec(const cmCTestHardwareSpec& spec);
+ void InitializeFromResourceSpec(const cmCTestResourceSpec& spec);
const std::map<std::string, std::map<std::string, Resource>>& GetResources()
const;
diff --git a/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
new file mode 100644
index 0000000000..072af42f03
--- /dev/null
+++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
@@ -0,0 +1,55 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestResourceGroupsLexerHelper.h"
+
+#include "cmCTestResourceGroupsLexer.h"
+#include "cmCTestTestHandler.h"
+
+cmCTestResourceGroupsLexerHelper::cmCTestResourceGroupsLexerHelper(
+ std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ output)
+ : Output(output)
+{
+}
+
+bool cmCTestResourceGroupsLexerHelper::ParseString(const std::string& value)
+{
+ yyscan_t lexer;
+ cmCTestResourceGroups_yylex_init_extra(this, &lexer);
+
+ auto state = cmCTestResourceGroups_yy_scan_string(value.c_str(), lexer);
+ int retval = cmCTestResourceGroups_yylex(lexer);
+ cmCTestResourceGroups_yy_delete_buffer(state, lexer);
+
+ cmCTestResourceGroups_yylex_destroy(lexer);
+ return retval == 0;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetProcessCount(unsigned int count)
+{
+ this->ProcessCount = count;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetResourceType(const std::string& type)
+{
+ this->ResourceType = type;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetNeededSlots(int count)
+{
+ this->NeededSlots = count;
+}
+
+void cmCTestResourceGroupsLexerHelper::WriteRequirement()
+{
+ this->Process.push_back({ this->ResourceType, this->NeededSlots, 1 });
+}
+
+void cmCTestResourceGroupsLexerHelper::WriteProcess()
+{
+ for (unsigned int i = 0; i < this->ProcessCount; ++i) {
+ this->Output.push_back(this->Process);
+ }
+ this->Process.clear();
+ this->ProcessCount = 1;
+}
diff --git a/Source/CTest/cmCTestProcessesLexerHelper.h b/Source/CTest/cmCTestResourceGroupsLexerHelper.h
index 6c9289fb5c..2cb6cb1c58 100644
--- a/Source/CTest/cmCTestProcessesLexerHelper.h
+++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.h
@@ -1,25 +1,25 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCTestProcessesLexerHelper_h
-#define cmCTestProcessesLexerHelper_h
+#ifndef cmCTestResourceGroupsLexerHelper_h
+#define cmCTestResourceGroupsLexerHelper_h
#include <string>
#include <vector>
#include "cmCTestTestHandler.h"
-class cmCTestProcessesLexerHelper
+class cmCTestResourceGroupsLexerHelper
{
public:
struct ParserType
{
};
- cmCTestProcessesLexerHelper(
+ cmCTestResourceGroupsLexerHelper(
std::vector<
std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
output);
- ~cmCTestProcessesLexerHelper() = default;
+ ~cmCTestResourceGroupsLexerHelper() = default;
bool ParseString(const std::string& value);
@@ -39,6 +39,6 @@ private:
std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement> Process;
};
-#define YY_EXTRA_TYPE cmCTestProcessesLexerHelper*
+#define YY_EXTRA_TYPE cmCTestResourceGroupsLexerHelper*
#endif
diff --git a/Source/CTest/cmCTestHardwareSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx
index 137398aa83..b4a2b30c9c 100644
--- a/Source/CTest/cmCTestHardwareSpec.cxx
+++ b/Source/CTest/cmCTestResourceSpec.cxx
@@ -1,6 +1,6 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCTestHardwareSpec.h"
+#include "cmCTestResourceSpec.h"
#include <map>
#include <string>
@@ -16,7 +16,7 @@
static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
-bool cmCTestHardwareSpec::ReadFromJSONFile(const std::string& filename)
+bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename)
{
cmsys::ifstream fin(filename.c_str());
if (!fin) {
@@ -50,7 +50,7 @@ bool cmCTestHardwareSpec::ReadFromJSONFile(const std::string& filename)
if (!localSocket.isObject()) {
return false;
}
- std::map<std::string, std::vector<cmCTestHardwareSpec::Resource>> resources;
+ std::map<std::string, std::vector<cmCTestResourceSpec::Resource>> resources;
cmsys::RegularExpressionMatch match;
for (auto const& key : localSocket.getMemberNames()) {
if (IdentifierRegex.find(key.c_str(), match)) {
@@ -59,7 +59,7 @@ bool cmCTestHardwareSpec::ReadFromJSONFile(const std::string& filename)
if (value.isArray()) {
for (auto const& item : value) {
if (item.isObject()) {
- cmCTestHardwareSpec::Resource resource;
+ cmCTestResourceSpec::Resource resource;
if (!item.isMember("id")) {
return false;
@@ -98,36 +98,36 @@ bool cmCTestHardwareSpec::ReadFromJSONFile(const std::string& filename)
return true;
}
-bool cmCTestHardwareSpec::operator==(const cmCTestHardwareSpec& other) const
+bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const
{
return this->LocalSocket == other.LocalSocket;
}
-bool cmCTestHardwareSpec::operator!=(const cmCTestHardwareSpec& other) const
+bool cmCTestResourceSpec::operator!=(const cmCTestResourceSpec& other) const
{
return !(*this == other);
}
-bool cmCTestHardwareSpec::Socket::operator==(
- const cmCTestHardwareSpec::Socket& other) const
+bool cmCTestResourceSpec::Socket::operator==(
+ const cmCTestResourceSpec::Socket& other) const
{
return this->Resources == other.Resources;
}
-bool cmCTestHardwareSpec::Socket::operator!=(
- const cmCTestHardwareSpec::Socket& other) const
+bool cmCTestResourceSpec::Socket::operator!=(
+ const cmCTestResourceSpec::Socket& other) const
{
return !(*this == other);
}
-bool cmCTestHardwareSpec::Resource::operator==(
- const cmCTestHardwareSpec::Resource& other) const
+bool cmCTestResourceSpec::Resource::operator==(
+ const cmCTestResourceSpec::Resource& other) const
{
return this->Id == other.Id && this->Capacity == other.Capacity;
}
-bool cmCTestHardwareSpec::Resource::operator!=(
- const cmCTestHardwareSpec::Resource& other) const
+bool cmCTestResourceSpec::Resource::operator!=(
+ const cmCTestResourceSpec::Resource& other) const
{
return !(*this == other);
}
diff --git a/Source/CTest/cmCTestHardwareSpec.h b/Source/CTest/cmCTestResourceSpec.h
index a0b4cae596..4646db84cd 100644
--- a/Source/CTest/cmCTestHardwareSpec.h
+++ b/Source/CTest/cmCTestResourceSpec.h
@@ -1,13 +1,13 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCTestHardwareSpec_h
-#define cmCTestHardwareSpec_h
+#ifndef cmCTestResourceSpec_h
+#define cmCTestResourceSpec_h
#include <map>
#include <string>
#include <vector>
-class cmCTestHardwareSpec
+class cmCTestResourceSpec
{
public:
class Resource
@@ -33,8 +33,8 @@ public:
bool ReadFromJSONFile(const std::string& filename);
- bool operator==(const cmCTestHardwareSpec& other) const;
- bool operator!=(const cmCTestHardwareSpec& other) const;
+ bool operator==(const cmCTestResourceSpec& other) const;
+ bool operator!=(const cmCTestResourceSpec& other) const;
};
#endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 7f7f736799..317f0b4086 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -34,9 +34,6 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler)
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
this->TestResult.Properties = nullptr;
- this->NumberOfRunsLeft = 1; // default to 1 run of the test
- this->RunUntilFail = false; // default to run the test once
- this->RunAgain = false; // default to not having to run again
}
void cmCTestRunTest::CheckOutput(std::string const& line)
@@ -343,10 +340,14 @@ bool cmCTestRunTest::NeedsToRerun()
return false;
}
// if number of runs left is not 0, and we are running until
- // we find a failed test, then return true so the test can be
+ // we find a failed (or passed) test, then return true so the test can be
// restarted
- if (this->RunUntilFail &&
- this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
+ if ((this->RerunMode == cmCTest::Rerun::UntilFail &&
+ this->TestResult.Status == cmCTestTestHandler::COMPLETED) ||
+ (this->RerunMode == cmCTest::Rerun::UntilPass &&
+ this->TestResult.Status != cmCTestTestHandler::COMPLETED) ||
+ (this->RerunMode == cmCTest::Rerun::AfterTimeout &&
+ this->TestResult.Status == cmCTestTestHandler::TIMEOUT)) {
this->RunAgain = true;
return true;
}
@@ -690,25 +691,25 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
cmSystemTools::AppendEnv(*environment);
}
- if (this->UseAllocatedHardware) {
- this->SetupHardwareEnvironment();
+ if (this->UseAllocatedResources) {
+ this->SetupResourcesEnvironment();
} else {
- cmSystemTools::UnsetEnv("CTEST_PROCESS_COUNT");
+ cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT");
}
return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
affinity);
}
-void cmCTestRunTest::SetupHardwareEnvironment()
+void cmCTestRunTest::SetupResourcesEnvironment()
{
- std::string processCount = "CTEST_PROCESS_COUNT=";
- processCount += std::to_string(this->AllocatedHardware.size());
+ std::string processCount = "CTEST_RESOURCE_GROUP_COUNT=";
+ processCount += std::to_string(this->AllocatedResources.size());
cmSystemTools::PutEnv(processCount);
std::size_t i = 0;
- for (auto const& process : this->AllocatedHardware) {
- std::string prefix = "CTEST_PROCESS_";
+ for (auto const& process : this->AllocatedResources) {
+ std::string prefix = "CTEST_RESOURCE_GROUP_";
prefix += std::to_string(i);
std::string resourceList = prefix + '=';
prefix += '_';
@@ -746,7 +747,12 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
// then it will never print out the completed / total, same would
// got for run until pass. Trick is when this is called we don't
// yet know if we are passing or failing.
- if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) {
+ bool const progressOnLast =
+ (this->RerunMode != cmCTest::Rerun::UntilPass &&
+ this->RerunMode != cmCTest::Rerun::AfterTimeout);
+ if ((progressOnLast && this->NumberOfRunsLeft == 1) ||
+ (!progressOnLast && this->NumberOfRunsLeft == this->NumberOfRunsTotal) ||
+ this->CTest->GetTestProgressOutput()) {
outputStream << std::setw(getNumWidth(total)) << completed << "/";
outputStream << std::setw(getNumWidth(total)) << total << " ";
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 085a6b8f84..d5e83d9e4d 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -13,13 +13,12 @@
#include <stddef.h>
+#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmProcess.h"
-class cmCTest;
-
/** \class cmRunTest
* \brief represents a single test to be run
*
@@ -30,8 +29,13 @@ class cmCTestRunTest
public:
explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler);
- void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; }
- void SetRunUntilFailOn() { this->RunUntilFail = true; }
+ void SetNumberOfRuns(int n)
+ {
+ this->NumberOfRunsLeft = n;
+ this->NumberOfRunsTotal = n;
+ }
+
+ void SetRerunMode(cmCTest::Rerun r) { this->RerunMode = r; }
void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop)
{
this->TestProperties = prop;
@@ -84,14 +88,17 @@ public:
bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; }
- void SetUseAllocatedHardware(bool use) { this->UseAllocatedHardware = use; }
- void SetAllocatedHardware(
+ void SetUseAllocatedResources(bool use)
+ {
+ this->UseAllocatedResources = use;
+ }
+ void SetAllocatedResources(
const std::vector<
std::map<std::string,
- std::vector<cmCTestMultiProcessHandler::HardwareAllocation>>>&
- hardware)
+ std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>>&
+ resources)
{
- this->AllocatedHardware = hardware;
+ this->AllocatedResources = resources;
}
private:
@@ -105,7 +112,7 @@ private:
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
- void SetupHardwareEnvironment();
+ void SetupResourcesEnvironment();
// Returns "completed/total Test #Index: "
std::string GetTestPrefix(size_t completed, size_t total) const;
@@ -125,13 +132,14 @@ private:
std::string StartTime;
std::string ActualCommand;
std::vector<std::string> Arguments;
- bool UseAllocatedHardware = false;
+ bool UseAllocatedResources = false;
std::vector<std::map<
- std::string, std::vector<cmCTestMultiProcessHandler::HardwareAllocation>>>
- AllocatedHardware;
- bool RunUntilFail;
- int NumberOfRunsLeft;
- bool RunAgain;
+ std::string, std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>>
+ AllocatedResources;
+ cmCTest::Rerun RerunMode = cmCTest::Rerun::Never;
+ int NumberOfRunsLeft = 1; // default to 1 run of the test
+ int NumberOfRunsTotal = 1; // default to 1 run of the test
+ bool RunAgain = false; // default to not having to run again
size_t TotalNumberOfTests;
};
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 5496353012..9784214053 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -32,7 +32,7 @@ void cmCTestTestCommand::BindArguments()
this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom);
this->Bind("STOP_TIME"_s, this->StopTime);
this->Bind("TEST_LOAD"_s, this->TestLoad);
- this->Bind("HARDWARE_SPEC_FILE"_s, this->HardwareSpecFile);
+ this->Bind("RESOURCE_SPEC_FILE"_s, this->ResourceSpecFile);
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
@@ -88,8 +88,8 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
if (!this->ScheduleRandom.empty()) {
handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
}
- if (!this->HardwareSpecFile.empty()) {
- handler->SetOption("HardwareSpecFile", this->HardwareSpecFile.c_str());
+ if (!this->ResourceSpecFile.empty()) {
+ handler->SetOption("ResourceSpecFile", this->ResourceSpecFile.c_str());
}
if (!this->StopTime.empty()) {
this->CTest->SetStopTime(this->StopTime);
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index dc15279ba7..4019694b2e 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -58,7 +58,7 @@ protected:
std::string ScheduleRandom;
std::string StopTime;
std::string TestLoad;
- std::string HardwareSpecFile;
+ std::string ResourceSpecFile;
};
#endif
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 2be62ae4e1..8e3ac22639 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -29,7 +29,7 @@
#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
-#include "cmCTestProcessesLexerHelper.h"
+#include "cmCTestResourceGroupsLexerHelper.h"
#include "cmDuration.h"
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
@@ -289,7 +289,7 @@ cmCTestTestHandler::cmCTestTestHandler()
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
- this->UseHardwareSpec = false;
+ this->UseResourceSpec = false;
this->CustomMaximumPassedTestOutputSize = 1 * 1024;
this->CustomMaximumFailedTestOutputSize = 300 * 1024;
@@ -510,12 +510,12 @@ bool cmCTestTestHandler::ProcessOptions()
}
this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed")));
- val = this->GetOption("HardwareSpecFile");
+ val = this->GetOption("ResourceSpecFile");
if (val) {
- this->UseHardwareSpec = true;
- if (!this->HardwareSpec.ReadFromJSONFile(val)) {
+ this->UseResourceSpec = true;
+ if (!this->ResourceSpec.ReadFromJSONFile(val)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Could not read hardware spec file: " << val << std::endl);
+ "Could not read resource spec file: " << val << std::endl);
return false;
}
}
@@ -1237,8 +1237,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
} else {
parallel->SetTestLoad(this->CTest->GetTestLoad());
}
- if (this->UseHardwareSpec) {
- parallel->InitHardwareAllocator(this->HardwareSpec);
+ if (this->UseResourceSpec) {
+ parallel->InitResourceAllocator(this->ResourceSpec);
}
*this->LogFile
@@ -1283,7 +1283,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
parallel->SetPassFailVectors(&passed, &failed);
this->TestResults.clear();
parallel->SetTestResults(&this->TestResults);
- parallel->CheckHardwareAvailable();
+ parallel->CheckResourcesAvailable();
if (this->CTest->ShouldPrintLabels()) {
parallel->PrintLabels();
@@ -1626,11 +1626,11 @@ std::string cmCTestTestHandler::FindExecutable(
return fullPath;
}
-bool cmCTestTestHandler::ParseProcessesProperty(
+bool cmCTestTestHandler::ParseResourceGroupsProperty(
const std::string& val,
- std::vector<std::vector<cmCTestTestResourceRequirement>>& processes)
+ std::vector<std::vector<cmCTestTestResourceRequirement>>& resourceGroups)
{
- cmCTestProcessesLexerHelper lexer(processes);
+ cmCTestResourceGroupsLexerHelper lexer(resourceGroups);
return lexer.ParseString(val);
}
@@ -2203,8 +2203,8 @@ bool cmCTestTestHandler::SetTestsProperties(
if (key == "PROCESSOR_AFFINITY") {
rt.WantAffinity = cmIsOn(val);
}
- if (key == "PROCESSES") {
- if (!ParseProcessesProperty(val, rt.Processes)) {
+ if (key == "RESOURCE_GROUPS") {
+ if (!ParseResourceGroupsProperty(val, rt.ResourceGroups)) {
return false;
}
}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 525215c267..eab75d0eb8 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -19,7 +19,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmCTestGenericHandler.h"
-#include "cmCTestHardwareSpec.h"
+#include "cmCTestResourceSpec.h"
#include "cmDuration.h"
#include "cmListFileCache.h"
@@ -158,7 +158,7 @@ public:
std::set<std::string> FixturesCleanup;
std::set<std::string> FixturesRequired;
std::set<std::string> RequireSuccessDepends;
- std::vector<std::vector<cmCTestTestResourceRequirement>> Processes;
+ std::vector<std::vector<cmCTestTestResourceRequirement>> ResourceGroups;
// Private test generator properties used to track backtraces
cmListFileBacktrace Backtrace;
};
@@ -202,9 +202,9 @@ public:
std::vector<std::string>& extraPaths,
std::vector<std::string>& failed);
- static bool ParseProcessesProperty(
+ static bool ParseResourceGroupsProperty(
const std::string& val,
- std::vector<std::vector<cmCTestTestResourceRequirement>>& processes);
+ std::vector<std::vector<cmCTestTestResourceRequirement>>& resourceGroups);
using ListOfTests = std::vector<cmCTestTestProperties>;
@@ -336,8 +336,8 @@ private:
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
- bool UseHardwareSpec;
- cmCTestHardwareSpec HardwareSpec;
+ bool UseResourceSpec;
+ cmCTestResourceSpec ResourceSpec;
void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
cmsys::RegularExpression DartStuff1;
diff --git a/Source/Checks/Curses.cmake b/Source/Checks/Curses.cmake
index 2942b666ae..d35dd2a6e1 100644
--- a/Source/Checks/Curses.cmake
+++ b/Source/Checks/Curses.cmake
@@ -1,4 +1,7 @@
-message(STATUS "Checking for curses support")
+include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
+cm_message_checks_compat(
+ "Checking for curses support" __checkStart __checkPass __checkFail)
+message(${__checkStart})
# Try compiling a simple project using curses.
# Pass in any cache entries that the user may have set.
@@ -31,11 +34,11 @@ set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}")
unset(CMakeCheckCurses_COMPILED CACHE)
if(CMakeCheckCurses_COMPILED)
- message(STATUS "Checking for curses support - Success")
+ message(${__checkPass} "Success")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
else()
- message(STATUS "Checking for curses support - Failed")
+ message(${__checkFail} "Failed")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
endif()
diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake
index 6b8d10b2bd..2263be3bad 100644
--- a/Source/Checks/cm_c11_thread_local.cmake
+++ b/Source/Checks/cm_c11_thread_local.cmake
@@ -1,7 +1,11 @@
set(CMake_C11_THREAD_LOCAL_BROKEN 0)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION)
if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS)
- message(STATUS "Checking if compiler supports C11 _Thread_local")
+ include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
+ cm_message_checks_compat(
+ "Checking if compiler supports C11 _Thread_local"
+ __checkStart __checkPass __checkFail)
+ message(${__checkStart})
try_compile(CMake_C11_THREAD_LOCAL_WORKS
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c
@@ -12,14 +16,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION)
set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0)
endif()
if(CMake_C11_THREAD_LOCAL_WORKS)
- message(STATUS "Checking if compiler supports C11 _Thread_local - yes")
+ message(${__checkPass} "yes")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if compiler supports C11 _Thread_local passed with the following output:\n"
"${OUTPUT}\n"
"\n"
)
else()
- message(STATUS "Checking if compiler supports C11 _Thread_local - no")
+ message(${__checkFail} "no")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler supports C11 _Thread_local failed with the following output:\n"
"${OUTPUT}\n"
diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake
index 38606b9c90..8e9c2c70a6 100644
--- a/Source/Checks/cm_cxx14_check.cmake
+++ b/Source/Checks/cm_cxx14_check.cmake
@@ -4,7 +4,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
set(CMake_CXX14_WORKS 0)
endif()
if(NOT DEFINED CMake_CXX14_WORKS)
- message(STATUS "Checking if compiler supports needed C++14 constructs")
+ include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
+ cm_message_checks_compat(
+ "Checking if compiler supports needed C++14 constructs"
+ __checkStart __checkPass __checkFail)
+ message(${__checkStart})
try_compile(CMake_CXX14_WORKS
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_check.cpp
@@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
set_property(CACHE CMake_CXX14_WORKS PROPERTY VALUE 0)
endif()
if(CMake_CXX14_WORKS)
- message(STATUS "Checking if compiler supports needed C++14 constructs - yes")
+ message(${__checkPass} "yes")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if compiler supports needed C++14 constructs passed with the following output:\n"
"${OUTPUT}\n"
"\n"
)
else()
- message(STATUS "Checking if compiler supports needed C++14 constructs - no")
+ message(${__checkFail} "no")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler supports needed C++14 constructs failed with the following output:\n"
"${OUTPUT}\n"
diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake
index 4da2fd7cac..9e1d9c3eae 100644
--- a/Source/Checks/cm_cxx17_check.cmake
+++ b/Source/Checks/cm_cxx17_check.cmake
@@ -4,7 +4,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
set(CMake_CXX17_WORKS 0)
endif()
if(NOT DEFINED CMake_CXX17_WORKS)
- message(STATUS "Checking if compiler supports needed C++17 constructs")
+ include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
+ cm_message_checks_compat(
+ "Checking if compiler supports needed C++17 constructs"
+ __checkStart __checkPass __checkFail)
+ message(${__checkStart})
try_compile(CMake_CXX17_WORKS
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_LIST_DIR}/cm_cxx17_check.cpp
@@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
set_property(CACHE CMake_CXX17_WORKS PROPERTY VALUE 0)
endif()
if(CMake_CXX17_WORKS)
- message(STATUS "Checking if compiler supports needed C++17 constructs - yes")
+ message(${__checkPass} "yes")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if compiler supports needed C++17 constructs passed with the following output:\n"
"${OUTPUT}\n"
"\n"
)
else()
- message(STATUS "Checking if compiler supports needed C++17 constructs - no")
+ message(${__checkFail} "no")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler supports needed C++17 constructs failed with the following output:\n"
"${OUTPUT}\n"
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index fb68ed78c9..de8a77af55 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -1,8 +1,12 @@
+include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
function(cm_check_cxx_feature name)
string(TOUPPER ${name} FEATURE)
if(NOT DEFINED CMake_HAVE_CXX_${FEATURE})
- message(STATUS "Checking if compiler supports C++ ${name}")
+ cm_message_checks_compat(
+ "Checking if compiler supports C++ ${name}"
+ __checkStart __checkPass __checkFail)
+ message(${__checkStart})
if(CMAKE_CXX_STANDARD)
set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD})
else()
@@ -31,14 +35,14 @@ function(cm_check_cxx_feature name)
set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
endif()
if(CMake_HAVE_CXX_${FEATURE})
- message(STATUS "Checking if compiler supports C++ ${name} - yes")
+ message(${__checkPass} "yes")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if compiler supports C++ ${name} passed with the following output:\n"
"${OUTPUT}\n"
"\n"
)
else()
- message(STATUS "Checking if compiler supports C++ ${name} - no")
+ message(${__checkFail} "no")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if compiler supports C++ ${name} failed with the following output:\n"
"${OUTPUT}\n"
diff --git a/Source/Checks/cm_message_checks_compat.cmake b/Source/Checks/cm_message_checks_compat.cmake
new file mode 100644
index 0000000000..024c397a8b
--- /dev/null
+++ b/Source/Checks/cm_message_checks_compat.cmake
@@ -0,0 +1,13 @@
+# Supporting using the CHECK_... message modes if available
+# and fall back to the older behavior if not
+macro(cm_message_checks_compat description startVar passVar failVar)
+ if(CMAKE_VERSION VERSION_GREATER 3.16.2019)
+ set(${startVar} CHECK_START "${description}")
+ set(${passVar} CHECK_PASS)
+ set(${failVar} CHECK_FAIL)
+ else()
+ set(${startVar} STATUS "${description}")
+ set(${passVar} STATUS "${description} - ")
+ set(${failVar} STATUS "${description} - ")
+ endif()
+endmacro()
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index 7009717511..c24ee76216 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -5,6 +5,7 @@ add_executable(ccmake
ccmake.cxx
cmCursesBoolWidget.cxx
cmCursesCacheEntryComposite.cxx
+ cmCursesColor.cxx
cmCursesDummyWidget.cxx
cmCursesFilePathWidget.cxx
cmCursesForm.cxx
@@ -17,21 +18,45 @@ add_executable(ccmake
cmCursesWidget.cxx
)
target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH})
+set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_PATH})
target_link_libraries(ccmake CMakeLib)
if(CMAKE_USE_SYSTEM_FORM)
find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses)
if(CURSES_FORM_INCLUDE_DIR)
target_include_directories(ccmake PRIVATE ${CURSES_FORM_INCLUDE_DIR})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_FORM_INCLUDE_DIR})
endif()
target_link_libraries(ccmake
${CURSES_FORM_LIBRARY}
${CURSES_LIBRARY}
)
+ set(CMAKE_REQUIRED_LIBRARIES
+ ${CURSES_FORM_LIBRARY}
+ ${CURSES_LIBRARY}
+ )
if(CURSES_EXTRA_LIBRARY)
target_link_libraries(ccmake ${CURSES_EXTRA_LIBRARY})
+ list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_EXTRA_LIBRARY})
endif()
else()
target_link_libraries(ccmake cmForm)
+ get_target_property(cmFormIncludeDirs cmForm INTERFACE_INCLUDE_DIRECTORIES)
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${cmFormIncludeDirs})
+ get_target_property(cmFormLibraries cmForm INTERFACE_LINK_LIBRARIES)
+ set(CMAKE_REQUIRED_LIBRARIES ${cmFormLibraries})
+endif()
+
+include(CheckSymbolExists)
+check_symbol_exists(use_default_colors
+ "form.h"
+ HAVE_CURSES_USE_DEFAULT_COLORS)
+if(HAVE_CURSES_USE_DEFAULT_COLORS)
+ set_source_files_properties(cmCursesColor.cxx
+ PROPERTIES COMPILE_DEFINITIONS HAVE_CURSES_USE_DEFAULT_COLORS)
+endif()
+
+if(CMake_JOB_POOL_LINK_BIN)
+ set_property(TARGET ccmake PROPERTY JOB_POOL_LINK "link-bin")
endif()
CMake_OPTIONAL_COMPONENT(ccmake)
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 9e9dfbd195..7732105085 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -9,6 +9,7 @@
#include "cmsys/Encoding.hxx"
+#include "cmCursesColor.h"
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
@@ -126,6 +127,7 @@ int main(int argc, char const* const* argv)
noecho(); /* Echo off */
cbreak(); /* nl- or cr not needed */
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
+ cmCursesColor::InitColors();
signal(SIGWINCH, onsig);
diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx
index 97b0811288..c4dbed8350 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.cxx
+++ b/Source/CursesDialog/cmCursesBoolWidget.cxx
@@ -4,6 +4,7 @@
#include <string>
+#include "cmCursesColor.h"
#include "cmCursesWidget.h"
#include "cmStateTypes.h"
@@ -12,8 +13,10 @@ cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, int left,
: cmCursesWidget(width, height, left, top)
{
this->Type = cmStateEnums::BOOL;
- set_field_fore(this->Field, A_NORMAL);
- set_field_back(this->Field, A_STANDOUT);
+ if (!cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ }
field_opts_off(this->Field, O_STATIC);
this->SetValueAsBool(false);
}
@@ -42,8 +45,16 @@ void cmCursesBoolWidget::SetValueAsBool(bool value)
{
if (value) {
this->SetValue("ON");
+ if (cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOn));
+ set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOn));
+ }
} else {
this->SetValue("OFF");
+ if (cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOff));
+ set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOff));
+ }
}
}
diff --git a/Source/CursesDialog/cmCursesColor.cxx b/Source/CursesDialog/cmCursesColor.cxx
new file mode 100644
index 0000000000..641d48ccec
--- /dev/null
+++ b/Source/CursesDialog/cmCursesColor.cxx
@@ -0,0 +1,29 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCursesColor.h"
+
+#include "cmCursesStandardIncludes.h"
+
+bool cmCursesColor::HasColors()
+{
+#ifdef HAVE_CURSES_USE_DEFAULT_COLORS
+ return has_colors();
+#else
+ return false;
+#endif
+}
+
+void cmCursesColor::InitColors()
+{
+#ifdef HAVE_CURSES_USE_DEFAULT_COLORS
+ if (HasColors()) {
+ start_color();
+ use_default_colors();
+ init_pair(cmCursesColor::BoolOff, COLOR_RED, -1);
+ init_pair(cmCursesColor::BoolOn, COLOR_GREEN, -1);
+ init_pair(cmCursesColor::String, COLOR_BLUE, -1);
+ init_pair(cmCursesColor::Path, COLOR_YELLOW, -1);
+ init_pair(cmCursesColor::Options, COLOR_MAGENTA, -1);
+ }
+#endif
+}
diff --git a/Source/CursesDialog/cmCursesColor.h b/Source/CursesDialog/cmCursesColor.h
new file mode 100644
index 0000000000..78ca52cbb1
--- /dev/null
+++ b/Source/CursesDialog/cmCursesColor.h
@@ -0,0 +1,24 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCursesColor_h
+#define cmCursesColor_h
+
+class cmCursesColor
+{
+public:
+ enum Color
+ {
+ // Default color is pair 0
+ BoolOff = 1,
+ BoolOn,
+ String,
+ Path,
+ Options
+ };
+
+ static bool HasColors();
+
+ static void InitColors();
+};
+
+#endif // cmCursesColor_h
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index e2d8d06b49..a69fdee894 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -8,6 +8,7 @@
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
+#include "cmStringAlgorithms.h"
#include "cmVersion.h"
inline int ctrl(int z)
@@ -19,11 +20,7 @@ cmCursesLongMessageForm::cmCursesLongMessageForm(
std::vector<std::string> const& messages, const char* title)
{
// Append all messages into on big string
- for (std::string const& message : messages) {
- this->Messages += message;
- // Add one blank line after each message
- this->Messages += "\n\n";
- }
+ this->Messages = cmJoin(messages, "\n");
this->Title = title;
this->Fields[0] = nullptr;
this->Fields[1] = nullptr;
@@ -48,7 +45,7 @@ void cmCursesLongMessageForm::UpdateStatusBar()
size = cmCursesMainForm::MAX_WIDTH - 1;
}
strncpy(bar, this->Title.c_str(), size);
- for (size_t i = size - 1; i < cmCursesMainForm::MAX_WIDTH; i++) {
+ for (size_t i = size; i < cmCursesMainForm::MAX_WIDTH; i++) {
bar[i] = ' ';
}
int width;
@@ -89,7 +86,7 @@ void cmCursesLongMessageForm::PrintKeys()
return;
}
char firstLine[512];
- sprintf(firstLine, "Press [e] to exit help");
+ sprintf(firstLine, "Press [e] to exit screen");
char fmt_s[] = "%s";
curses_move(y - 2, 0);
@@ -139,7 +136,6 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
form_driver(this->Form, REQ_BEG_FIELD);
this->UpdateStatusBar();
- this->PrintKeys();
touchwin(stdscr);
refresh();
}
@@ -153,6 +149,7 @@ void cmCursesLongMessageForm::HandleInput()
char debugMessage[128];
for (;;) {
+ this->PrintKeys();
int key = getch();
sprintf(debugMessage, "Message widget handling input, key: %d", key);
@@ -173,7 +170,16 @@ void cmCursesLongMessageForm::HandleInput()
}
this->UpdateStatusBar();
- this->PrintKeys();
+ touchwin(stdscr);
+ wrefresh(stdscr);
+ }
+}
+
+void cmCursesLongMessageForm::ScrollDown()
+{
+ if (this->Form) {
+ form_driver(this->Form, REQ_END_FIELD);
+ this->UpdateStatusBar();
touchwin(stdscr);
wrefresh(stdscr);
}
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h
index 42f9c710b7..dde5bfffaf 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.h
+++ b/Source/CursesDialog/cmCursesLongMessageForm.h
@@ -26,6 +26,10 @@ public:
void HandleInput() override;
// Description:
+ // Scroll down to the end of the content
+ void ScrollDown();
+
+ // Description:
// Display form. Use a window of size width x height, starting
// at top, left.
void Render(int left, int top, int width, int height) override;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 6b71e8a10a..ffc9528966 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -34,6 +34,7 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
: Args(std::move(args))
, InitialWidth(initWidth)
{
+ this->HasNonStatusOutputs = false;
this->NumberOfPages = 0;
this->AdvancedMode = false;
this->NumberOfVisibleEntries = 0;
@@ -321,25 +322,25 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
} else {
if (this->OkToGenerate) {
sprintf(firstLine,
- "Press [c] to configure Press [g] to generate and exit");
+ " [l] Show log output [c] Configure"
+ " [g] Generate ");
} else {
sprintf(firstLine,
- "Press [c] to configure ");
+ " [l] Show log output [c] Configure"
+ " ");
}
{
const char* toggleKeyInstruction =
- "Press [t] to toggle advanced mode (Currently %s)";
+ " [t] Toggle advanced mode (currently %s)";
sprintf(thirdLine, toggleKeyInstruction,
- this->AdvancedMode ? "On" : "Off");
+ this->AdvancedMode ? "on" : "off");
}
sprintf(secondLine,
- "Press [h] for help "
- "Press [q] to quit without generating");
+ " [h] Help [q] Quit without generating");
}
curses_move(y - 4, 0);
- char fmt[512] =
- "Press [enter] to edit option Press [d] to delete an entry";
+ char fmt[512] = "Keys: [enter] Edit an entry [d] Delete an entry";
if (process) {
memset(fmt, ' ', 57);
}
@@ -446,6 +447,15 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
bar[width] = '\0';
+ // Highlight the current label
+ // Fields are grouped by 3, the first one being the label
+ // so start at 0 and move up by 3 avoiding the last null entry
+ using size_type = decltype(this->Fields)::size_type;
+ for (size_type index = 0; index < this->Fields.size() - 1; index += 3) {
+ bool currentLabel = index == static_cast<size_type>(findex - 2);
+ set_field_fore(this->Fields[index], currentLabel ? A_STANDOUT : A_NORMAL);
+ }
+
// Display CMake version info on the next line
// We want to display this on the right
char version[cmCursesMainForm::MAX_WIDTH];
@@ -469,18 +479,21 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog)
{
- char tmp[1024];
- const char* cmsg = tmp;
if (prog >= 0) {
- sprintf(tmp, "%s %i%%", msg.c_str(), static_cast<int>(100 * prog));
+ constexpr int progressBarWidth = 40;
+ int progressBarCompleted = static_cast<int>(progressBarWidth * prog);
+ int percentCompleted = static_cast<int>(100 * prog);
+ this->LastProgress = (percentCompleted < 100 ? " " : "");
+ this->LastProgress += (percentCompleted < 10 ? " " : "");
+ this->LastProgress += std::to_string(percentCompleted) + "% [";
+ this->LastProgress.append(progressBarCompleted, '#');
+ this->LastProgress.append(progressBarWidth - progressBarCompleted, ' ');
+ this->LastProgress += "] " + msg + "...";
} else {
- cmsg = msg.c_str();
+ this->Outputs.emplace_back(msg);
}
- this->UpdateStatusBar(cmsg);
- this->PrintKeys(1);
- curses_move(1, 1);
- touchwin(stdscr);
- refresh();
+
+ this->DisplayOutputs();
}
int cmCursesMainForm::Configure(int noconfigure)
@@ -489,15 +502,15 @@ int cmCursesMainForm::Configure(int noconfigure)
int yi;
getmaxyx(stdscr, yi, xi);
- curses_move(1, 1);
- this->UpdateStatusBar("Configuring, please wait...");
- this->PrintKeys(1);
- touchwin(stdscr);
- refresh();
- this->CMakeInstance->SetProgressCallback(
- [this](const std::string& msg, float prog) {
- this->UpdateProgress(msg, prog);
- });
+ this->ResetOutputs();
+
+ if (noconfigure == 0) {
+ this->UpdateProgress("Configuring", 0);
+ this->CMakeInstance->SetProgressCallback(
+ [this](const std::string& msg, float prog) {
+ this->UpdateProgress(msg, prog);
+ });
+ }
// always save the current gui values to disk
this->FillCacheManagerFromUI();
@@ -505,9 +518,6 @@ int cmCursesMainForm::Configure(int noconfigure)
this->CMakeInstance->GetHomeOutputDirectory());
this->LoadCache(nullptr);
- // Get rid of previous errors
- this->Errors = std::vector<std::string>();
-
// run the generate process
this->OkToGenerate = true;
int retVal;
@@ -524,7 +534,7 @@ int cmCursesMainForm::Configure(int noconfigure)
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
- if (retVal != 0 || !this->Errors.empty()) {
+ if (retVal != 0 || this->HasNonStatusOutputs) {
// see if there was an error
if (cmSystemTools::GetErrorOccuredFlag()) {
this->OkToGenerate = false;
@@ -532,15 +542,17 @@ int cmCursesMainForm::Configure(int noconfigure)
int xx;
int yy;
getmaxyx(stdscr, yy, xx);
+ const char* title = "Configure produced the following output";
+ if (cmSystemTools::GetErrorOccuredFlag()) {
+ title = "Configure failed with the following output";
+ }
cmCursesLongMessageForm* msgs =
- new cmCursesLongMessageForm(this->Errors,
- cmSystemTools::GetErrorOccuredFlag()
- ? "Errors occurred during the last pass."
- : "CMake produced the following output.");
+ new cmCursesLongMessageForm(this->Outputs, title);
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
CurrentForm = msgs;
msgs->Render(1, 1, xx, yy);
+ msgs->ScrollDown();
msgs->HandleInput();
// If they typed the wrong source directory, we report
// an error and exit
@@ -563,26 +575,21 @@ int cmCursesMainForm::Generate()
int yi;
getmaxyx(stdscr, yi, xi);
- curses_move(1, 1);
- this->UpdateStatusBar("Generating, please wait...");
- this->PrintKeys(1);
- touchwin(stdscr);
- refresh();
+ this->ResetOutputs();
+
+ this->UpdateProgress("Generating", 0);
this->CMakeInstance->SetProgressCallback(
[this](const std::string& msg, float prog) {
this->UpdateProgress(msg, prog);
});
- // Get rid of previous errors
- this->Errors = std::vector<std::string>();
-
// run the generate process
int retVal = this->CMakeInstance->Generate();
this->CMakeInstance->SetProgressCallback(nullptr);
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
- if (retVal != 0 || !this->Errors.empty()) {
+ if (retVal != 0 || this->HasNonStatusOutputs) {
// see if there was an error
if (cmSystemTools::GetErrorOccuredFlag()) {
this->OkToGenerate = false;
@@ -592,14 +599,15 @@ int cmCursesMainForm::Generate()
int xx;
int yy;
getmaxyx(stdscr, yy, xx);
- const char* title = "Messages during last pass.";
+ const char* title = "Generate produced the following output";
if (cmSystemTools::GetErrorOccuredFlag()) {
- title = "Errors occurred during the last pass.";
+ title = "Generate failed with the following output";
}
cmCursesLongMessageForm* msgs =
- new cmCursesLongMessageForm(this->Errors, title);
+ new cmCursesLongMessageForm(this->Outputs, title);
CurrentForm = msgs;
msgs->Render(1, 1, xx, yy);
+ msgs->ScrollDown();
msgs->HandleInput();
// If they typed the wrong source directory, we report
// an error and exit
@@ -619,7 +627,9 @@ int cmCursesMainForm::Generate()
void cmCursesMainForm::AddError(const std::string& message,
const char* /*unused*/)
{
- this->Errors.emplace_back(message);
+ this->Outputs.emplace_back(message);
+ this->HasNonStatusOutputs = true;
+ this->DisplayOutputs();
}
void cmCursesMainForm::RemoveEntry(const char* value)
@@ -849,7 +859,7 @@ void cmCursesMainForm::HandleInput()
}
cmCursesLongMessageForm* msgs =
- new cmCursesLongMessageForm(this->HelpMessage, "Help.");
+ new cmCursesLongMessageForm(this->HelpMessage, "Help");
CurrentForm = msgs;
msgs->Render(1, 1, x, y);
msgs->HandleInput();
@@ -861,7 +871,7 @@ void cmCursesMainForm::HandleInput()
else if (key == 'l') {
getmaxyx(stdscr, y, x);
cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
- this->Errors, "Errors occurred during the last pass.");
+ this->Outputs, "CMake produced the following output");
CurrentForm = msgs;
msgs->Render(1, 1, x, y);
msgs->HandleInput();
@@ -1024,6 +1034,28 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr)
}
}
+void cmCursesMainForm::ResetOutputs()
+{
+ this->LogForm.reset();
+ this->Outputs.clear();
+ this->HasNonStatusOutputs = false;
+ this->LastProgress.clear();
+}
+
+void cmCursesMainForm::DisplayOutputs()
+{
+ int xi;
+ int yi;
+ getmaxyx(stdscr, yi, xi);
+
+ auto newLogForm =
+ new cmCursesLongMessageForm(this->Outputs, this->LastProgress.c_str());
+ CurrentForm = newLogForm;
+ this->LogForm.reset(newLogForm);
+ this->LogForm->Render(1, 1, xi, yi);
+ this->LogForm->ScrollDown();
+}
+
const char* cmCursesMainForm::s_ConstHelpMessage =
"CMake is used to configure and generate build files for software projects. "
"The basic steps for configuring a project with ccmake are as follows:\n\n"
@@ -1080,7 +1112,7 @@ const char* cmCursesMainForm::s_ConstHelpMessage =
" c : process the configuration files with the current options\n"
" g : generate build files and exit, only available when there are no "
"new options and no errors have been detected during last configuration.\n"
- " l : shows last errors\n"
+ " l : shows cmake output\n"
" d : delete an option\n"
" t : toggles advanced mode. In normal mode, only the most important "
"options are shown. In advanced mode, all options are shown. We recommend "
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index b8769b7cf4..598fbdfba3 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -16,6 +16,7 @@
#include "cmStateTypes.h"
class cmake;
+class cmCursesLongMessageForm;
/** \class cmCursesMainForm
* \brief The main page of ccmake
@@ -122,10 +123,24 @@ protected:
// Jump to the cache entry whose name matches the string.
void JumpToCacheEntry(const char* str);
+ // Clear and reset the output log and state
+ void ResetOutputs();
+
+ // Display the current progress and output
+ void DisplayOutputs();
+
// Copies of cache entries stored in the user interface
std::vector<cmCursesCacheEntryComposite> Entries;
- // Errors produced during last run of cmake
- std::vector<std::string> Errors;
+
+ // The form used to display logs during processing
+ std::unique_ptr<cmCursesLongMessageForm> LogForm;
+ // Output produced by the last pass
+ std::vector<std::string> Outputs;
+ // Did the last pass produced outputs of interest (errors, warnings, ...)
+ bool HasNonStatusOutputs;
+ // Last progress bar
+ std::string LastProgress;
+
// Command line arguments to be passed to cmake each time
// it is run
std::vector<std::string> Args;
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx
index eb773ad0fb..a15241faed 100644
--- a/Source/CursesDialog/cmCursesOptionsWidget.cxx
+++ b/Source/CursesDialog/cmCursesOptionsWidget.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesOptionsWidget.h"
+#include "cmCursesColor.h"
#include "cmCursesWidget.h"
#include "cmStateTypes.h"
@@ -15,8 +16,13 @@ cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left,
// there is no option type, and string type causes ccmake to cast
// the widget into a string widget at some point. BOOL is safe for
// now.
- set_field_fore(this->Field, A_NORMAL);
- set_field_back(this->Field, A_STANDOUT);
+ if (cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Options));
+ set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Options));
+ } else {
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ }
field_opts_off(this->Field, O_STATIC);
}
diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx
index bb3808e89c..8ed42dee75 100644
--- a/Source/CursesDialog/cmCursesPathWidget.cxx
+++ b/Source/CursesDialog/cmCursesPathWidget.cxx
@@ -4,6 +4,7 @@
#include <vector>
+#include "cmCursesColor.h"
#include "cmCursesMainForm.h"
#include "cmCursesStringWidget.h"
#include "cmStateTypes.h"
@@ -16,6 +17,13 @@ cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left,
this->Type = cmStateEnums::PATH;
this->Cycle = false;
this->CurrentIndex = 0;
+ if (cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Path));
+ set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Path));
+ } else {
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ }
}
void cmCursesPathWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW* w)
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index 6296af20ba..c62947836c 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -4,6 +4,7 @@
#include <cstdio>
+#include "cmCursesColor.h"
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
@@ -21,8 +22,13 @@ cmCursesStringWidget::cmCursesStringWidget(int width, int height, int left,
{
this->InEdit = false;
this->Type = cmStateEnums::STRING;
- set_field_fore(this->Field, A_NORMAL);
- set_field_back(this->Field, A_STANDOUT);
+ if (cmCursesColor::HasColors()) {
+ set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::String));
+ set_field_back(this->Field, COLOR_PAIR(cmCursesColor::String));
+ } else {
+ set_field_fore(this->Field, A_NORMAL);
+ set_field_back(this->Field, A_STANDOUT);
+ }
field_opts_off(this->Field, O_STATIC);
}
diff --git a/Source/LexerParser/.gitattributes b/Source/LexerParser/.gitattributes
index e5a1d8b113..bf70249788 100644
--- a/Source/LexerParser/.gitattributes
+++ b/Source/LexerParser/.gitattributes
@@ -2,8 +2,8 @@
/cmCommandArgumentLexer.h generated
/cmCommandArgumentParser.cxx generated
/cmCommandArgumentParserTokens.h generated
-/cmCTestProcessesLexer.cxx generated
-/cmCTestProcessesLexer.h generated
+/cmCTestResourceGroupsLexer.cxx generated
+/cmCTestResourceGroupsLexer.h generated
/cmDependsJavaLexer.cxx generated
/cmDependsJavaLexer.h generated
/cmDependsJavaParser.cxx generated
diff --git a/Source/LexerParser/cmCTestProcessesLexer.cxx b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
index 2a5dab35b9..de07c4693a 100644
--- a/Source/LexerParser/cmCTestProcessesLexer.cxx
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
@@ -14,213 +14,213 @@
#endif
#ifdef yy_create_buffer
-#define cmCTestProcesses_yy_create_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
#else
-#define yy_create_buffer cmCTestProcesses_yy_create_buffer
+#define yy_create_buffer cmCTestResourceGroups_yy_create_buffer
#endif
#ifdef yy_delete_buffer
-#define cmCTestProcesses_yy_delete_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
#else
-#define yy_delete_buffer cmCTestProcesses_yy_delete_buffer
+#define yy_delete_buffer cmCTestResourceGroups_yy_delete_buffer
#endif
#ifdef yy_scan_buffer
-#define cmCTestProcesses_yy_scan_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
#else
-#define yy_scan_buffer cmCTestProcesses_yy_scan_buffer
+#define yy_scan_buffer cmCTestResourceGroups_yy_scan_buffer
#endif
#ifdef yy_scan_string
-#define cmCTestProcesses_yy_scan_string_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
#else
-#define yy_scan_string cmCTestProcesses_yy_scan_string
+#define yy_scan_string cmCTestResourceGroups_yy_scan_string
#endif
#ifdef yy_scan_bytes
-#define cmCTestProcesses_yy_scan_bytes_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
#else
-#define yy_scan_bytes cmCTestProcesses_yy_scan_bytes
+#define yy_scan_bytes cmCTestResourceGroups_yy_scan_bytes
#endif
#ifdef yy_init_buffer
-#define cmCTestProcesses_yy_init_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
#else
-#define yy_init_buffer cmCTestProcesses_yy_init_buffer
+#define yy_init_buffer cmCTestResourceGroups_yy_init_buffer
#endif
#ifdef yy_flush_buffer
-#define cmCTestProcesses_yy_flush_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
#else
-#define yy_flush_buffer cmCTestProcesses_yy_flush_buffer
+#define yy_flush_buffer cmCTestResourceGroups_yy_flush_buffer
#endif
#ifdef yy_load_buffer_state
-#define cmCTestProcesses_yy_load_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
#else
-#define yy_load_buffer_state cmCTestProcesses_yy_load_buffer_state
+#define yy_load_buffer_state cmCTestResourceGroups_yy_load_buffer_state
#endif
#ifdef yy_switch_to_buffer
-#define cmCTestProcesses_yy_switch_to_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
#else
-#define yy_switch_to_buffer cmCTestProcesses_yy_switch_to_buffer
+#define yy_switch_to_buffer cmCTestResourceGroups_yy_switch_to_buffer
#endif
#ifdef yypush_buffer_state
-#define cmCTestProcesses_yypush_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
#else
-#define yypush_buffer_state cmCTestProcesses_yypush_buffer_state
+#define yypush_buffer_state cmCTestResourceGroups_yypush_buffer_state
#endif
#ifdef yypop_buffer_state
-#define cmCTestProcesses_yypop_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
#else
-#define yypop_buffer_state cmCTestProcesses_yypop_buffer_state
+#define yypop_buffer_state cmCTestResourceGroups_yypop_buffer_state
#endif
#ifdef yyensure_buffer_stack
-#define cmCTestProcesses_yyensure_buffer_stack_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
#else
-#define yyensure_buffer_stack cmCTestProcesses_yyensure_buffer_stack
+#define yyensure_buffer_stack cmCTestResourceGroups_yyensure_buffer_stack
#endif
#ifdef yylex
-#define cmCTestProcesses_yylex_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_ALREADY_DEFINED
#else
-#define yylex cmCTestProcesses_yylex
+#define yylex cmCTestResourceGroups_yylex
#endif
#ifdef yyrestart
-#define cmCTestProcesses_yyrestart_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
#else
-#define yyrestart cmCTestProcesses_yyrestart
+#define yyrestart cmCTestResourceGroups_yyrestart
#endif
#ifdef yylex_init
-#define cmCTestProcesses_yylex_init_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
#else
-#define yylex_init cmCTestProcesses_yylex_init
+#define yylex_init cmCTestResourceGroups_yylex_init
#endif
#ifdef yylex_init_extra
-#define cmCTestProcesses_yylex_init_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
#else
-#define yylex_init_extra cmCTestProcesses_yylex_init_extra
+#define yylex_init_extra cmCTestResourceGroups_yylex_init_extra
#endif
#ifdef yylex_destroy
-#define cmCTestProcesses_yylex_destroy_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
#else
-#define yylex_destroy cmCTestProcesses_yylex_destroy
+#define yylex_destroy cmCTestResourceGroups_yylex_destroy
#endif
#ifdef yyget_debug
-#define cmCTestProcesses_yyget_debug_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
#else
-#define yyget_debug cmCTestProcesses_yyget_debug
+#define yyget_debug cmCTestResourceGroups_yyget_debug
#endif
#ifdef yyset_debug
-#define cmCTestProcesses_yyset_debug_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
#else
-#define yyset_debug cmCTestProcesses_yyset_debug
+#define yyset_debug cmCTestResourceGroups_yyset_debug
#endif
#ifdef yyget_extra
-#define cmCTestProcesses_yyget_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
#else
-#define yyget_extra cmCTestProcesses_yyget_extra
+#define yyget_extra cmCTestResourceGroups_yyget_extra
#endif
#ifdef yyset_extra
-#define cmCTestProcesses_yyset_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
#else
-#define yyset_extra cmCTestProcesses_yyset_extra
+#define yyset_extra cmCTestResourceGroups_yyset_extra
#endif
#ifdef yyget_in
-#define cmCTestProcesses_yyget_in_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
#else
-#define yyget_in cmCTestProcesses_yyget_in
+#define yyget_in cmCTestResourceGroups_yyget_in
#endif
#ifdef yyset_in
-#define cmCTestProcesses_yyset_in_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
#else
-#define yyset_in cmCTestProcesses_yyset_in
+#define yyset_in cmCTestResourceGroups_yyset_in
#endif
#ifdef yyget_out
-#define cmCTestProcesses_yyget_out_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
#else
-#define yyget_out cmCTestProcesses_yyget_out
+#define yyget_out cmCTestResourceGroups_yyget_out
#endif
#ifdef yyset_out
-#define cmCTestProcesses_yyset_out_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
#else
-#define yyset_out cmCTestProcesses_yyset_out
+#define yyset_out cmCTestResourceGroups_yyset_out
#endif
#ifdef yyget_leng
-#define cmCTestProcesses_yyget_leng_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
#else
-#define yyget_leng cmCTestProcesses_yyget_leng
+#define yyget_leng cmCTestResourceGroups_yyget_leng
#endif
#ifdef yyget_text
-#define cmCTestProcesses_yyget_text_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
#else
-#define yyget_text cmCTestProcesses_yyget_text
+#define yyget_text cmCTestResourceGroups_yyget_text
#endif
#ifdef yyget_lineno
-#define cmCTestProcesses_yyget_lineno_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
#else
-#define yyget_lineno cmCTestProcesses_yyget_lineno
+#define yyget_lineno cmCTestResourceGroups_yyget_lineno
#endif
#ifdef yyset_lineno
-#define cmCTestProcesses_yyset_lineno_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
#else
-#define yyset_lineno cmCTestProcesses_yyset_lineno
+#define yyset_lineno cmCTestResourceGroups_yyset_lineno
#endif
#ifdef yyget_column
-#define cmCTestProcesses_yyget_column_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
#else
-#define yyget_column cmCTestProcesses_yyget_column
+#define yyget_column cmCTestResourceGroups_yyget_column
#endif
#ifdef yyset_column
-#define cmCTestProcesses_yyset_column_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
#else
-#define yyset_column cmCTestProcesses_yyset_column
+#define yyset_column cmCTestResourceGroups_yyset_column
#endif
#ifdef yywrap
-#define cmCTestProcesses_yywrap_ALREADY_DEFINED
+#define cmCTestResourceGroups_yywrap_ALREADY_DEFINED
#else
-#define yywrap cmCTestProcesses_yywrap
+#define yywrap cmCTestResourceGroups_yywrap
#endif
#ifdef yyalloc
-#define cmCTestProcesses_yyalloc_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
#else
-#define yyalloc cmCTestProcesses_yyalloc
+#define yyalloc cmCTestResourceGroups_yyalloc
#endif
#ifdef yyrealloc
-#define cmCTestProcesses_yyrealloc_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
#else
-#define yyrealloc cmCTestProcesses_yyrealloc
+#define yyrealloc cmCTestResourceGroups_yyrealloc
#endif
#ifdef yyfree
-#define cmCTestProcesses_yyfree_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyfree_ALREADY_DEFINED
#else
-#define yyfree cmCTestProcesses_yyfree
+#define yyfree cmCTestResourceGroups_yyfree
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
@@ -526,7 +526,7 @@ void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
-#define cmCTestProcesses_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define cmCTestResourceGroups_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
typedef flex_uint8_t YY_CHAR;
@@ -648,12 +648,12 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestProcessesLexer.h -ocmCTestProcessesLexer.cxx cmCTestProcessesLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestResourceGroupsLexer.h -ocmCTestResourceGroupsLexer.cxx cmCTestResourceGroupsLexer.in.l
-Modify cmCTestProcessesLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmCTestProcessesLexer.h cmCTestProcessesLexer.cxx
- - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestProcessesLexer.h cmCTestProcessesLexer.cxx
- - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestProcessesLexer.cxx
+Modify cmCTestResourceGroupsLexer.cxx:
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestResourceGroupsLexer.cxx
*/
@@ -661,7 +661,7 @@ Modify cmCTestProcessesLexer.cxx:
#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
-#include "cmCTestProcessesLexerHelper.h"
+#include "cmCTestResourceGroupsLexerHelper.h"
#include <string>
@@ -670,8 +670,8 @@ Modify cmCTestProcessesLexer.cxx:
/*--------------------------------------------------------------------------*/
#define INITIAL 0
-#define PROCESSES_START 1
-#define PROCESSES_END 2
+#define RESOURCE_GROUPS_START 1
+#define RESOURCE_GROUPS_END 2
#define RESOURCE_START 3
#define RESOURCE_COUNT 4
#define RESOURCE_END 5
@@ -990,7 +990,7 @@ YY_RULE_SETUP
case 2:
YY_RULE_SETUP
{
- BEGIN(PROCESSES_END);
+ BEGIN(RESOURCE_GROUPS_END);
std::size_t len = yyleng;
yyextra->SetProcessCount(std::stoll(yytext, &len, 10));
}
@@ -1013,18 +1013,18 @@ YY_RULE_SETUP
case 5:
YY_RULE_SETUP
{
- BEGIN(PROCESSES_START);
+ BEGIN(RESOURCE_GROUPS_START);
}
YY_BREAK
case 6:
YY_RULE_SETUP
{
- BEGIN(PROCESSES_START);
+ BEGIN(RESOURCE_GROUPS_START);
yyextra->WriteProcess();
}
YY_BREAK
case YY_STATE_EOF(RESOURCE_START):
-case YY_STATE_EOF(PROCESSES_END):
+case YY_STATE_EOF(RESOURCE_GROUPS_END):
case YY_STATE_EOF(RESOURCE_END):
{
yyextra->WriteProcess();
@@ -1032,7 +1032,7 @@ case YY_STATE_EOF(RESOURCE_END):
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(PROCESSES_START):
+case YY_STATE_EOF(RESOURCE_GROUPS_START):
{
return 0;
}
diff --git a/Source/LexerParser/cmCTestProcessesLexer.h b/Source/LexerParser/cmCTestResourceGroupsLexer.h
index b6437b44ae..e323a50899 100644
--- a/Source/LexerParser/cmCTestProcessesLexer.h
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.h
@@ -1,6 +1,6 @@
-#ifndef cmCTestProcesses_yyHEADER_H
-#define cmCTestProcesses_yyHEADER_H 1
-#define cmCTestProcesses_yyIN_HEADER 1
+#ifndef cmCTestResourceGroups_yyHEADER_H
+#define cmCTestResourceGroups_yyHEADER_H 1
+#define cmCTestResourceGroups_yyIN_HEADER 1
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -16,213 +16,213 @@
#endif
#ifdef yy_create_buffer
-#define cmCTestProcesses_yy_create_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
#else
-#define yy_create_buffer cmCTestProcesses_yy_create_buffer
+#define yy_create_buffer cmCTestResourceGroups_yy_create_buffer
#endif
#ifdef yy_delete_buffer
-#define cmCTestProcesses_yy_delete_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
#else
-#define yy_delete_buffer cmCTestProcesses_yy_delete_buffer
+#define yy_delete_buffer cmCTestResourceGroups_yy_delete_buffer
#endif
#ifdef yy_scan_buffer
-#define cmCTestProcesses_yy_scan_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
#else
-#define yy_scan_buffer cmCTestProcesses_yy_scan_buffer
+#define yy_scan_buffer cmCTestResourceGroups_yy_scan_buffer
#endif
#ifdef yy_scan_string
-#define cmCTestProcesses_yy_scan_string_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
#else
-#define yy_scan_string cmCTestProcesses_yy_scan_string
+#define yy_scan_string cmCTestResourceGroups_yy_scan_string
#endif
#ifdef yy_scan_bytes
-#define cmCTestProcesses_yy_scan_bytes_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
#else
-#define yy_scan_bytes cmCTestProcesses_yy_scan_bytes
+#define yy_scan_bytes cmCTestResourceGroups_yy_scan_bytes
#endif
#ifdef yy_init_buffer
-#define cmCTestProcesses_yy_init_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
#else
-#define yy_init_buffer cmCTestProcesses_yy_init_buffer
+#define yy_init_buffer cmCTestResourceGroups_yy_init_buffer
#endif
#ifdef yy_flush_buffer
-#define cmCTestProcesses_yy_flush_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
#else
-#define yy_flush_buffer cmCTestProcesses_yy_flush_buffer
+#define yy_flush_buffer cmCTestResourceGroups_yy_flush_buffer
#endif
#ifdef yy_load_buffer_state
-#define cmCTestProcesses_yy_load_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
#else
-#define yy_load_buffer_state cmCTestProcesses_yy_load_buffer_state
+#define yy_load_buffer_state cmCTestResourceGroups_yy_load_buffer_state
#endif
#ifdef yy_switch_to_buffer
-#define cmCTestProcesses_yy_switch_to_buffer_ALREADY_DEFINED
+#define cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
#else
-#define yy_switch_to_buffer cmCTestProcesses_yy_switch_to_buffer
+#define yy_switch_to_buffer cmCTestResourceGroups_yy_switch_to_buffer
#endif
#ifdef yypush_buffer_state
-#define cmCTestProcesses_yypush_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
#else
-#define yypush_buffer_state cmCTestProcesses_yypush_buffer_state
+#define yypush_buffer_state cmCTestResourceGroups_yypush_buffer_state
#endif
#ifdef yypop_buffer_state
-#define cmCTestProcesses_yypop_buffer_state_ALREADY_DEFINED
+#define cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
#else
-#define yypop_buffer_state cmCTestProcesses_yypop_buffer_state
+#define yypop_buffer_state cmCTestResourceGroups_yypop_buffer_state
#endif
#ifdef yyensure_buffer_stack
-#define cmCTestProcesses_yyensure_buffer_stack_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
#else
-#define yyensure_buffer_stack cmCTestProcesses_yyensure_buffer_stack
+#define yyensure_buffer_stack cmCTestResourceGroups_yyensure_buffer_stack
#endif
#ifdef yylex
-#define cmCTestProcesses_yylex_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_ALREADY_DEFINED
#else
-#define yylex cmCTestProcesses_yylex
+#define yylex cmCTestResourceGroups_yylex
#endif
#ifdef yyrestart
-#define cmCTestProcesses_yyrestart_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
#else
-#define yyrestart cmCTestProcesses_yyrestart
+#define yyrestart cmCTestResourceGroups_yyrestart
#endif
#ifdef yylex_init
-#define cmCTestProcesses_yylex_init_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
#else
-#define yylex_init cmCTestProcesses_yylex_init
+#define yylex_init cmCTestResourceGroups_yylex_init
#endif
#ifdef yylex_init_extra
-#define cmCTestProcesses_yylex_init_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
#else
-#define yylex_init_extra cmCTestProcesses_yylex_init_extra
+#define yylex_init_extra cmCTestResourceGroups_yylex_init_extra
#endif
#ifdef yylex_destroy
-#define cmCTestProcesses_yylex_destroy_ALREADY_DEFINED
+#define cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
#else
-#define yylex_destroy cmCTestProcesses_yylex_destroy
+#define yylex_destroy cmCTestResourceGroups_yylex_destroy
#endif
#ifdef yyget_debug
-#define cmCTestProcesses_yyget_debug_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
#else
-#define yyget_debug cmCTestProcesses_yyget_debug
+#define yyget_debug cmCTestResourceGroups_yyget_debug
#endif
#ifdef yyset_debug
-#define cmCTestProcesses_yyset_debug_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
#else
-#define yyset_debug cmCTestProcesses_yyset_debug
+#define yyset_debug cmCTestResourceGroups_yyset_debug
#endif
#ifdef yyget_extra
-#define cmCTestProcesses_yyget_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
#else
-#define yyget_extra cmCTestProcesses_yyget_extra
+#define yyget_extra cmCTestResourceGroups_yyget_extra
#endif
#ifdef yyset_extra
-#define cmCTestProcesses_yyset_extra_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
#else
-#define yyset_extra cmCTestProcesses_yyset_extra
+#define yyset_extra cmCTestResourceGroups_yyset_extra
#endif
#ifdef yyget_in
-#define cmCTestProcesses_yyget_in_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
#else
-#define yyget_in cmCTestProcesses_yyget_in
+#define yyget_in cmCTestResourceGroups_yyget_in
#endif
#ifdef yyset_in
-#define cmCTestProcesses_yyset_in_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
#else
-#define yyset_in cmCTestProcesses_yyset_in
+#define yyset_in cmCTestResourceGroups_yyset_in
#endif
#ifdef yyget_out
-#define cmCTestProcesses_yyget_out_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
#else
-#define yyget_out cmCTestProcesses_yyget_out
+#define yyget_out cmCTestResourceGroups_yyget_out
#endif
#ifdef yyset_out
-#define cmCTestProcesses_yyset_out_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
#else
-#define yyset_out cmCTestProcesses_yyset_out
+#define yyset_out cmCTestResourceGroups_yyset_out
#endif
#ifdef yyget_leng
-#define cmCTestProcesses_yyget_leng_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
#else
-#define yyget_leng cmCTestProcesses_yyget_leng
+#define yyget_leng cmCTestResourceGroups_yyget_leng
#endif
#ifdef yyget_text
-#define cmCTestProcesses_yyget_text_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
#else
-#define yyget_text cmCTestProcesses_yyget_text
+#define yyget_text cmCTestResourceGroups_yyget_text
#endif
#ifdef yyget_lineno
-#define cmCTestProcesses_yyget_lineno_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
#else
-#define yyget_lineno cmCTestProcesses_yyget_lineno
+#define yyget_lineno cmCTestResourceGroups_yyget_lineno
#endif
#ifdef yyset_lineno
-#define cmCTestProcesses_yyset_lineno_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
#else
-#define yyset_lineno cmCTestProcesses_yyset_lineno
+#define yyset_lineno cmCTestResourceGroups_yyset_lineno
#endif
#ifdef yyget_column
-#define cmCTestProcesses_yyget_column_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
#else
-#define yyget_column cmCTestProcesses_yyget_column
+#define yyget_column cmCTestResourceGroups_yyget_column
#endif
#ifdef yyset_column
-#define cmCTestProcesses_yyset_column_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
#else
-#define yyset_column cmCTestProcesses_yyset_column
+#define yyset_column cmCTestResourceGroups_yyset_column
#endif
#ifdef yywrap
-#define cmCTestProcesses_yywrap_ALREADY_DEFINED
+#define cmCTestResourceGroups_yywrap_ALREADY_DEFINED
#else
-#define yywrap cmCTestProcesses_yywrap
+#define yywrap cmCTestResourceGroups_yywrap
#endif
#ifdef yyalloc
-#define cmCTestProcesses_yyalloc_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
#else
-#define yyalloc cmCTestProcesses_yyalloc
+#define yyalloc cmCTestResourceGroups_yyalloc
#endif
#ifdef yyrealloc
-#define cmCTestProcesses_yyrealloc_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
#else
-#define yyrealloc cmCTestProcesses_yyrealloc
+#define yyrealloc cmCTestResourceGroups_yyrealloc
#endif
#ifdef yyfree
-#define cmCTestProcesses_yyfree_ALREADY_DEFINED
+#define cmCTestResourceGroups_yyfree_ALREADY_DEFINED
#else
-#define yyfree cmCTestProcesses_yyfree
+#define yyfree cmCTestResourceGroups_yyfree
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
@@ -423,15 +423,15 @@ void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
-#define cmCTestProcesses_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define cmCTestResourceGroups_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
-#define PROCESSES_START 1
-#define PROCESSES_END 2
+#define RESOURCE_GROUPS_START 1
+#define RESOURCE_GROUPS_END 2
#define RESOURCE_START 3
#define RESOURCE_COUNT 4
#define RESOURCE_END 5
@@ -543,150 +543,150 @@ extern int yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#ifndef cmCTestProcesses_yy_create_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
#undef yy_create_buffer
#endif
-#ifndef cmCTestProcesses_yy_delete_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
#undef yy_delete_buffer
#endif
-#ifndef cmCTestProcesses_yy_scan_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
#undef yy_scan_buffer
#endif
-#ifndef cmCTestProcesses_yy_scan_string_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
#undef yy_scan_string
#endif
-#ifndef cmCTestProcesses_yy_scan_bytes_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
#undef yy_scan_bytes
#endif
-#ifndef cmCTestProcesses_yy_init_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
#undef yy_init_buffer
#endif
-#ifndef cmCTestProcesses_yy_flush_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
#undef yy_flush_buffer
#endif
-#ifndef cmCTestProcesses_yy_load_buffer_state_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
#undef yy_load_buffer_state
#endif
-#ifndef cmCTestProcesses_yy_switch_to_buffer_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
#undef yy_switch_to_buffer
#endif
-#ifndef cmCTestProcesses_yypush_buffer_state_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
#undef yypush_buffer_state
#endif
-#ifndef cmCTestProcesses_yypop_buffer_state_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
#undef yypop_buffer_state
#endif
-#ifndef cmCTestProcesses_yyensure_buffer_stack_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
#undef yyensure_buffer_stack
#endif
-#ifndef cmCTestProcesses_yylex_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yylex_ALREADY_DEFINED
#undef yylex
#endif
-#ifndef cmCTestProcesses_yyrestart_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
#undef yyrestart
#endif
-#ifndef cmCTestProcesses_yylex_init_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
#undef yylex_init
#endif
-#ifndef cmCTestProcesses_yylex_init_extra_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
#undef yylex_init_extra
#endif
-#ifndef cmCTestProcesses_yylex_destroy_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
#undef yylex_destroy
#endif
-#ifndef cmCTestProcesses_yyget_debug_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
#undef yyget_debug
#endif
-#ifndef cmCTestProcesses_yyset_debug_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
#undef yyset_debug
#endif
-#ifndef cmCTestProcesses_yyget_extra_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
#undef yyget_extra
#endif
-#ifndef cmCTestProcesses_yyset_extra_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
#undef yyset_extra
#endif
-#ifndef cmCTestProcesses_yyget_in_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
#undef yyget_in
#endif
-#ifndef cmCTestProcesses_yyset_in_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
#undef yyset_in
#endif
-#ifndef cmCTestProcesses_yyget_out_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
#undef yyget_out
#endif
-#ifndef cmCTestProcesses_yyset_out_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
#undef yyset_out
#endif
-#ifndef cmCTestProcesses_yyget_leng_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
#undef yyget_leng
#endif
-#ifndef cmCTestProcesses_yyget_text_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
#undef yyget_text
#endif
-#ifndef cmCTestProcesses_yyget_lineno_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
#undef yyget_lineno
#endif
-#ifndef cmCTestProcesses_yyset_lineno_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
#undef yyset_lineno
#endif
-#ifndef cmCTestProcesses_yyget_column_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
#undef yyget_column
#endif
-#ifndef cmCTestProcesses_yyset_column_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
#undef yyset_column
#endif
-#ifndef cmCTestProcesses_yywrap_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yywrap_ALREADY_DEFINED
#undef yywrap
#endif
-#ifndef cmCTestProcesses_yyget_lval_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_lval_ALREADY_DEFINED
#undef yyget_lval
#endif
-#ifndef cmCTestProcesses_yyset_lval_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_lval_ALREADY_DEFINED
#undef yyset_lval
#endif
-#ifndef cmCTestProcesses_yyget_lloc_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyget_lloc_ALREADY_DEFINED
#undef yyget_lloc
#endif
-#ifndef cmCTestProcesses_yyset_lloc_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyset_lloc_ALREADY_DEFINED
#undef yyset_lloc
#endif
-#ifndef cmCTestProcesses_yyalloc_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
#undef yyalloc
#endif
-#ifndef cmCTestProcesses_yyrealloc_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
#undef yyrealloc
#endif
-#ifndef cmCTestProcesses_yyfree_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyfree_ALREADY_DEFINED
#undef yyfree
#endif
-#ifndef cmCTestProcesses_yytext_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yytext_ALREADY_DEFINED
#undef yytext
#endif
-#ifndef cmCTestProcesses_yyleng_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyleng_ALREADY_DEFINED
#undef yyleng
#endif
-#ifndef cmCTestProcesses_yyin_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyin_ALREADY_DEFINED
#undef yyin
#endif
-#ifndef cmCTestProcesses_yyout_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyout_ALREADY_DEFINED
#undef yyout
#endif
-#ifndef cmCTestProcesses_yy_flex_debug_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yy_flex_debug_ALREADY_DEFINED
#undef yy_flex_debug
#endif
-#ifndef cmCTestProcesses_yylineno_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yylineno_ALREADY_DEFINED
#undef yylineno
#endif
-#ifndef cmCTestProcesses_yytables_fload_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yytables_fload_ALREADY_DEFINED
#undef yytables_fload
#endif
-#ifndef cmCTestProcesses_yytables_destroy_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yytables_destroy_ALREADY_DEFINED
#undef yytables_destroy
#endif
-#ifndef cmCTestProcesses_yyTABLES_NAME_ALREADY_DEFINED
+#ifndef cmCTestResourceGroups_yyTABLES_NAME_ALREADY_DEFINED
#undef yyTABLES_NAME
#endif
-#undef cmCTestProcesses_yyIN_HEADER
-#endif /* cmCTestProcesses_yyHEADER_H */
+#undef cmCTestResourceGroups_yyIN_HEADER
+#endif /* cmCTestResourceGroups_yyHEADER_H */
diff --git a/Source/LexerParser/cmCTestProcessesLexer.in.l b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
index ef494d5d06..2aabea48db 100644
--- a/Source/LexerParser/cmCTestProcessesLexer.in.l
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
@@ -7,12 +7,12 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestProcessesLexer.h -ocmCTestProcessesLexer.cxx cmCTestProcessesLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestResourceGroupsLexer.h -ocmCTestResourceGroupsLexer.cxx cmCTestResourceGroupsLexer.in.l
-Modify cmCTestProcessesLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmCTestProcessesLexer.h cmCTestProcessesLexer.cxx
- - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestProcessesLexer.h cmCTestProcessesLexer.cxx
- - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestProcessesLexer.cxx
+Modify cmCTestResourceGroupsLexer.cxx:
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestResourceGroupsLexer.cxx
*/
@@ -20,7 +20,7 @@ Modify cmCTestProcessesLexer.cxx:
#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
-#include "cmCTestProcessesLexerHelper.h"
+#include "cmCTestResourceGroupsLexerHelper.h"
#include <string>
@@ -29,15 +29,15 @@ Modify cmCTestProcessesLexer.cxx:
/*--------------------------------------------------------------------------*/
%}
-%option prefix="cmCTestProcesses_yy"
+%option prefix="cmCTestResourceGroups_yy"
%option reentrant
%option noyywrap
%option nodefault
%pointer
-%s PROCESSES_START
-%s PROCESSES_END
+%s RESOURCE_GROUPS_START
+%s RESOURCE_GROUPS_END
%s RESOURCE_START
%s RESOURCE_COUNT
%s RESOURCE_END
@@ -47,13 +47,13 @@ IDENTIFIER [a-z_][a-z0-9_]*
%%
-<INITIAL,PROCESSES_START,RESOURCE_START>{IDENTIFIER}: {
+<INITIAL,RESOURCE_GROUPS_START,RESOURCE_START>{IDENTIFIER}: {
BEGIN(RESOURCE_COUNT);
yyextra->SetResourceType(std::string(yytext, yyleng - 1));
}
-<INITIAL,PROCESSES_START>{NUMBER} {
- BEGIN(PROCESSES_END);
+<INITIAL,RESOURCE_GROUPS_START>{NUMBER} {
+ BEGIN(RESOURCE_GROUPS_END);
std::size_t len = yyleng;
yyextra->SetProcessCount(std::stoll(yytext, &len, 10));
}
@@ -65,25 +65,25 @@ IDENTIFIER [a-z_][a-z0-9_]*
yyextra->WriteRequirement();
}
-<PROCESSES_END,RESOURCE_END>,+ {
+<RESOURCE_GROUPS_END,RESOURCE_END>,+ {
BEGIN(RESOURCE_START);
}
-<INITIAL,PROCESSES_START,RESOURCE_START>;+ {
- BEGIN(PROCESSES_START);
+<INITIAL,RESOURCE_GROUPS_START,RESOURCE_START>;+ {
+ BEGIN(RESOURCE_GROUPS_START);
}
-<PROCESSES_END,RESOURCE_END>;+ {
- BEGIN(PROCESSES_START);
+<RESOURCE_GROUPS_END,RESOURCE_END>;+ {
+ BEGIN(RESOURCE_GROUPS_START);
yyextra->WriteProcess();
}
-<RESOURCE_START,PROCESSES_END,RESOURCE_END><<EOF>> {
+<RESOURCE_START,RESOURCE_GROUPS_END,RESOURCE_END><<EOF>> {
yyextra->WriteProcess();
return 0;
}
-<INITIAL,PROCESSES_START><<EOF>> {
+<INITIAL,RESOURCE_GROUPS_START><<EOF>> {
return 0;
}
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index cb89d19fd9..98dd0e212b 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -178,6 +178,10 @@ if(WIN32)
target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
endif()
+if(CMake_JOB_POOL_LINK_BIN)
+ set_property(TARGET cmake-gui PROPERTY JOB_POOL_LINK "link-bin")
+endif()
+
# cmake-gui has not been updated for `include-what-you-use`.
# Block the tool until this is done.
set_target_properties(cmake-gui PROPERTIES
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 10b7646664..34e9479ce8 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -84,7 +84,7 @@ struct cmCTest::Private
};
int RepeatTests = 1; // default to run each test once
- bool RepeatUntilFail = false;
+ cmCTest::Rerun RerunMode = cmCTest::Rerun::Never;
std::string ConfigType;
std::string ScheduleType;
std::chrono::system_clock::time_point StopTime;
@@ -1839,11 +1839,16 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
this->SetParallelLevel(plevel);
this->Impl->ParallelLevelSetInCli = true;
}
+
if (this->CheckArgument(arg, "--repeat-until-fail")) {
if (i >= args.size() - 1) {
errormsg = "'--repeat-until-fail' requires an argument";
return false;
}
+ if (this->Impl->RerunMode != cmCTest::Rerun::Never) {
+ errormsg = "At most one '--repeat-*' option may be used.";
+ return false;
+ }
i++;
long repeat = 1;
if (!cmStrToLong(args[i], &repeat)) {
@@ -1853,7 +1858,51 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
this->Impl->RepeatTests = static_cast<int>(repeat);
if (repeat > 1) {
- this->Impl->RepeatUntilFail = true;
+ this->Impl->RerunMode = cmCTest::Rerun::UntilFail;
+ }
+ }
+
+ if (this->CheckArgument(arg, "--repeat-until-pass")) {
+ if (i >= args.size() - 1) {
+ errormsg = "'--repeat-until-pass' requires an argument";
+ return false;
+ }
+ if (this->Impl->RerunMode != cmCTest::Rerun::Never) {
+ errormsg = "At most one '--repeat-*' option may be used.";
+ return false;
+ }
+ i++;
+ long repeat = 1;
+ if (!cmStrToLong(args[i], &repeat)) {
+ errormsg =
+ "'--repeat-until-pass' given non-integer value '" + args[i] + "'";
+ return false;
+ }
+ this->Impl->RepeatTests = static_cast<int>(repeat);
+ if (repeat > 1) {
+ this->Impl->RerunMode = cmCTest::Rerun::UntilPass;
+ }
+ }
+
+ if (this->CheckArgument(arg, "--repeat-after-timeout")) {
+ if (i >= args.size() - 1) {
+ errormsg = "'--repeat-after-timeout' requires an argument";
+ return false;
+ }
+ if (this->Impl->RerunMode != cmCTest::Rerun::Never) {
+ errormsg = "At most one '--repeat-*' option may be used.";
+ return false;
+ }
+ i++;
+ long repeat = 1;
+ if (!cmStrToLong(args[i], &repeat)) {
+ errormsg =
+ "'--repeat-after-timeout' given non-integer value '" + args[i] + "'";
+ return false;
+ }
+ this->Impl->RepeatTests = static_cast<int>(repeat);
+ if (repeat > 1) {
+ this->Impl->RerunMode = cmCTest::Rerun::AfterTimeout;
}
}
@@ -2090,12 +2139,12 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
"ExcludeFixtureCleanupRegularExpression", args[i].c_str());
}
- if (this->CheckArgument(arg, "--hardware-spec-file") &&
+ if (this->CheckArgument(arg, "--resource-spec-file") &&
i < args.size() - 1) {
i++;
- this->GetTestHandler()->SetPersistentOption("HardwareSpecFile",
+ this->GetTestHandler()->SetPersistentOption("ResourceSpecFile",
args[i].c_str());
- this->GetMemCheckHandler()->SetPersistentOption("HardwareSpecFile",
+ this->GetMemCheckHandler()->SetPersistentOption("ResourceSpecFile",
args[i].c_str());
}
@@ -2852,9 +2901,9 @@ int cmCTest::GetTestRepeat() const
return this->Impl->RepeatTests;
}
-bool cmCTest::GetRepeatUntilFail() const
+cmCTest::Rerun cmCTest::GetRerunMode() const
{
- return this->Impl->RepeatUntilFail;
+ return this->Impl->RerunMode;
}
void cmCTest::SetBuildID(const std::string& id)
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 82a6f4cbd3..bef0f8d368 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -433,8 +433,14 @@ public:
/** Return the number of times a test should be run */
int GetTestRepeat() const;
- /** Return true if test should run until fail */
- bool GetRepeatUntilFail() const;
+ enum class Rerun
+ {
+ Never,
+ UntilFail,
+ UntilPass,
+ AfterTimeout,
+ };
+ Rerun GetRerunMode() const;
void GenerateSubprojectsOutput(cmXMLWriter& xml);
std::vector<std::string> GetLabelsForSubprojects();
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 910cc9d5e8..5711cae493 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -136,13 +136,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
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;
std::vector<std::string> targets;
std::vector<std::string> linkOptions;
@@ -154,12 +160,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
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;
@@ -176,12 +188,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingCopyFileError,
DoingCStandard,
DoingCxxStandard,
+ DoingObjCStandard,
+ DoingObjCxxStandard,
DoingCudaStandard,
DoingCStandardRequired,
DoingCxxStandardRequired,
+ DoingObjCStandardRequired,
+ DoingObjCxxStandardRequired,
DoingCudaStandardRequired,
DoingCExtensions,
DoingCxxExtensions,
+ DoingObjCExtensions,
+ DoingObjCxxExtensions,
DoingCudaExtensions,
DoingSources,
DoingCMakeInternal
@@ -212,6 +230,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -221,6 +245,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -230,6 +260,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -285,6 +321,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -294,6 +336,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -303,6 +351,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} 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;
@@ -754,16 +808,20 @@ 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();
bool warnCMP0067 = false;
bool honorStandard = true;
- if (!didCStandard && !didCxxStandard && !didCudaStandard &&
- !didCStandardRequired && !didCxxStandardRequired &&
- !didCudaStandardRequired && !didCExtensions && !didCxxExtensions &&
- !didCudaExtensions) {
+ if (!didCStandard && !didCxxStandard && !didObjCStandard &&
+ !didObjCxxStandard && !didCudaStandard && !didCStandardRequired &&
+ !didCxxStandardRequired && !didObjCStandardRequired &&
+ !didObjCxxStandardRequired && !didCudaStandardRequired &&
+ !didCExtensions && !didCxxExtensions && !didObjCExtensions &&
+ !didObjCxxExtensions && !didCudaExtensions) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -786,45 +844,42 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
if (honorStandard || warnCMP0067) {
- if (testC) {
- if (!didCStandard) {
- cStandard = this->LookupStdVar("CMAKE_C_STANDARD", warnCMP0067);
- }
- if (!didCStandardRequired) {
- cStandardRequired =
- this->LookupStdVar("CMAKE_C_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCExtensions) {
- cExtensions = this->LookupStdVar("CMAKE_C_EXTENSIONS", warnCMP0067);
- }
- }
- if (testCxx) {
- if (!didCxxStandard) {
- cxxStandard = this->LookupStdVar("CMAKE_CXX_STANDARD", warnCMP0067);
- }
- if (!didCxxStandardRequired) {
- cxxStandardRequired =
- this->LookupStdVar("CMAKE_CXX_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCxxExtensions) {
- cxxExtensions =
- this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067);
- }
- }
- if (testCuda) {
- if (!didCudaStandard) {
- cudaStandard =
- this->LookupStdVar("CMAKE_CUDA_STANDARD", warnCMP0067);
- }
- if (!didCudaStandardRequired) {
- cudaStandardRequired =
- this->LookupStdVar("CMAKE_CUDA_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCudaExtensions) {
- cudaExtensions =
- this->LookupStdVar("CMAKE_CUDA_EXTENSIONS", warnCMP0067);
- }
- }
+
+ 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");
}
if (!this->WarnCMP0067.empty()) {
@@ -841,44 +896,37 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- if (testC) {
- if (!cStandard.empty()) {
- writeProperty(fout, targetName, "C_STANDARD", cStandard);
- }
- if (!cStandardRequired.empty()) {
- writeProperty(fout, targetName, "C_STANDARD_REQUIRED",
- cStandardRequired);
- }
- if (!cExtensions.empty()) {
- writeProperty(fout, targetName, "C_EXTENSIONS", cExtensions);
- }
- }
-
- if (testCxx) {
- if (!cxxStandard.empty()) {
- writeProperty(fout, targetName, "CXX_STANDARD", cxxStandard);
- }
- if (!cxxStandardRequired.empty()) {
- writeProperty(fout, targetName, "CXX_STANDARD_REQUIRED",
- cxxStandardRequired);
- }
- if (!cxxExtensions.empty()) {
- writeProperty(fout, targetName, "CXX_EXTENSIONS", cxxExtensions);
- }
- }
-
- if (testCuda) {
- if (!cudaStandard.empty()) {
- writeProperty(fout, targetName, "CUDA_STANDARD", cudaStandard);
- }
- if (!cudaStandardRequired.empty()) {
- writeProperty(fout, targetName, "CUDA_STANDARD_REQUIRED",
- cudaStandardRequired);
- }
- if (!cudaExtensions.empty()) {
- writeProperty(fout, targetName, "CUDA_EXTENSIONS", cudaExtensions);
+ 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");
if (!linkOptions.empty()) {
std::vector<std::string> options;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 6d29c9994f..987ec9ea7b 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -258,15 +258,7 @@ void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os)
void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
{
- std::string::size_type pos = 0;
- std::string::size_type lastPos = pos;
-
- while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) !=
- std::string::npos) {
- std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
- input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}");
- lastPos = endPos;
- }
+ cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}");
}
bool cmExportInstallFileGenerator::GenerateImportFileConfig(
@@ -525,13 +517,14 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
}
std::string cmExportInstallFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& /*config*/)
+ cmGeneratorTarget* target, const std::string& config)
{
std::string install_name_dir;
cmMakefile* mf = target->Target->GetMakefile();
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
- install_name_dir = target->GetInstallNameDirForInstallTree();
+ install_name_dir =
+ target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}");
}
return install_name_dir;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index ea936cfd95..2b11b62a21 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -201,7 +201,13 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
// Check if System Package Registry should be disabled
- if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) {
+ // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has
+ // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
+ if (const char* def = this->Makefile->GetDefinition(
+ "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) {
+ this->NoSystemRegistry = !cmIsOn(def);
+ } else if (this->Makefile->IsOn(
+ "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) {
this->NoSystemRegistry = true;
}
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 44392baa75..91cd4efd47 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -2,7 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmForEachCommand.h"
-#include <cstdio>
+#include <algorithm>
+#include <cstddef>
+// NOTE The declaration of `std::abs` has moved to `cmath` since C++17
+// See https://en.cppreference.com/w/cpp/numeric/math/abs
+// ALERT But IWYU used to lint `#include`s do not "understand"
+// conditional compilation (i.e. `#if __cplusplus >= 201703L`)
#include <cstdlib>
#include <utility>
@@ -21,8 +26,6 @@
#include "cmSystemTools.h"
namespace {
-bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile);
-
class cmForEachFunctionBlocker : public cmFunctionBlocker
{
public:
@@ -60,7 +63,8 @@ bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
{
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
- return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
+ return expandedArguments.empty() ||
+ expandedArguments.front() == this->Args.front();
}
bool cmForEachFunctionBlocker::Replay(
@@ -70,13 +74,13 @@ bool cmForEachFunctionBlocker::Replay(
// at end of for each execute recorded commands
// store the old value
std::string oldDef;
- if (mf.GetDefinition(this->Args[0])) {
- oldDef = mf.GetDefinition(this->Args[0]);
+ if (mf.GetDefinition(this->Args.front())) {
+ oldDef = mf.GetDefinition(this->Args.front());
}
for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
// set the variable to the loop value
- mf.AddDefinition(this->Args[0], arg);
+ mf.AddDefinition(this->Args.front(), arg);
// Invoke all the functions that were collected in the block.
for (cmListFileFunction const& func : functions) {
cmExecutionStatus status(mf);
@@ -84,12 +88,12 @@ bool cmForEachFunctionBlocker::Replay(
if (status.GetReturnInvoked()) {
inStatus.SetReturnInvoked();
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
+ mf.AddDefinition(this->Args.front(), oldDef);
return true;
}
if (status.GetBreakInvoked()) {
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
+ mf.AddDefinition(this->Args.front(), oldDef);
return true;
}
if (status.GetContinueInvoked()) {
@@ -102,11 +106,48 @@ bool cmForEachFunctionBlocker::Replay(
}
// restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef);
+ mf.AddDefinition(this->Args.front(), oldDef);
return true;
}
+
+bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile)
+{
+ auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile);
+ fb->Args.push_back(args.front());
+
+ enum Doing
+ {
+ DoingNone,
+ DoingLists,
+ DoingItems
+ };
+ Doing doing = DoingNone;
+ for (std::string const& arg : cmMakeRange(args).advance(2)) {
+ if (arg == "LISTS") {
+ doing = DoingLists;
+ } else if (arg == "ITEMS") {
+ doing = DoingItems;
+ } else if (doing == DoingLists) {
+ auto const& value = makefile.GetSafeDefinition(arg);
+ if (!value.empty()) {
+ cmExpandList(value, fb->Args, true);
+ }
+ } else if (doing == DoingItems) {
+ fb->Args.push_back(arg);
+ } else {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("Unknown argument:\n", " ", arg, "\n"));
+ return true;
+ }
+ }
+
+ makefile.AddFunctionBlocker(std::move(fb));
+
+ return true;
}
+} // anonymous namespace
+
bool cmForEachCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -126,16 +167,16 @@ bool cmForEachCommand(std::vector<std::string> const& args,
int stop = 0;
int step = 0;
if (args.size() == 3) {
- stop = atoi(args[2].c_str());
+ stop = std::stoi(args[2]);
}
if (args.size() == 4) {
- start = atoi(args[2].c_str());
- stop = atoi(args[3].c_str());
+ start = std::stoi(args[2]);
+ stop = std::stoi(args[3]);
}
if (args.size() == 5) {
- start = atoi(args[2].c_str());
- stop = atoi(args[3].c_str());
- step = atoi(args[4].c_str());
+ start = std::stoi(args[2]);
+ stop = std::stoi(args[3]);
+ step = std::stoi(args[4]);
}
if (step == 0) {
if (start > stop) {
@@ -151,21 +192,24 @@ bool cmForEachCommand(std::vector<std::string> const& args,
", stop ", stop, ", step ", step));
return false;
}
- std::vector<std::string> range;
- char buffer[100];
- range.push_back(args[0]);
- int cc;
- for (cc = start;; cc += step) {
- if ((step > 0 && cc > stop) || (step < 0 && cc < stop)) {
- break;
- }
- sprintf(buffer, "%d", cc);
- range.emplace_back(buffer);
- if (cc == stop) {
- break;
- }
- }
- fb->Args = range;
+
+ // Calculate expected iterations count and reserve enough space
+ // in the `fb->Args` vector. The first item is the iteration variable
+ // name...
+ const std::size_t iter_cnt = 2u +
+ int(start < stop) * (stop - start) / std::abs(step) +
+ int(start > stop) * (start - stop) / std::abs(step);
+ fb->Args.resize(iter_cnt);
+ fb->Args.front() = args.front();
+ auto cc = start;
+ auto generator = [&cc, step]() -> std::string {
+ auto result = std::to_string(cc);
+ cc += step;
+ return result;
+ };
+ // Fill the `range` vector w/ generated string values
+ // (starting from 2nd position)
+ std::generate(++fb->Args.begin(), fb->Args.end(), generator);
} else {
fb->Args = args;
}
@@ -176,42 +220,3 @@ bool cmForEachCommand(std::vector<std::string> const& args,
return true;
}
-
-namespace {
-bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile)
-{
- auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile);
- fb->Args.push_back(args[0]);
-
- enum Doing
- {
- DoingNone,
- DoingLists,
- DoingItems
- };
- Doing doing = DoingNone;
- for (unsigned int i = 2; i < args.size(); ++i) {
- if (doing == DoingItems) {
- fb->Args.push_back(args[i]);
- } else if (args[i] == "LISTS") {
- doing = DoingLists;
- } else if (args[i] == "ITEMS") {
- doing = DoingItems;
- } else if (doing == DoingLists) {
- const char* value = makefile.GetDefinition(args[i]);
- if (value && *value) {
- cmExpandList(value, fb->Args, true);
- }
- } else {
- makefile.IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Unknown argument:\n", " ", args[i], "\n"));
- return true;
- }
- }
-
- makefile.AddFunctionBlocker(std::move(fb));
-
- return true;
-}
-}
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index b7f7d1d9b6..de43d3e732 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -385,6 +385,20 @@ bool cmGeneratorExpression::IsValidTargetName(const std::string& input)
return targetNameValidator.find(input);
}
+void cmGeneratorExpression::ReplaceInstallPrefix(
+ std::string& input, const std::string& replacement)
+{
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+
+ while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) !=
+ std::string::npos) {
+ std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
+ input.replace(pos, endPos - pos, replacement);
+ lastPos = endPos;
+ }
+}
+
void cmCompiledGeneratorExpression::GetMaxLanguageStandard(
const cmGeneratorTarget* tgt, std::map<std::string, std::string>& mapping)
{
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 4bd1c9f88a..cd35e1e25d 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -87,6 +87,9 @@ public:
return input != nullptr && input[0] == '$' && input[1] == '<';
}
+ static void ReplaceInstallPrefix(std::string& input,
+ const std::string& replacement);
+
private:
cmListFileBacktrace Backtrace;
};
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 949d9d9128..cb9f49e7af 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -10,11 +10,11 @@
#include <cstdlib>
#include <cstring>
#include <iterator>
-#include <memory>
#include <sstream>
#include <unordered_set>
#include <utility>
+#include <cm/memory>
#include <cm/string_view>
#include <queue>
@@ -162,7 +162,8 @@ private:
cmListFileBacktrace Backtrace;
};
-cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry(
+std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
+CreateTargetPropertyEntry(
const std::string& propertyValue,
cmListFileBacktrace backtrace = cmListFileBacktrace(),
bool evaluateForBuildsystem = false)
@@ -172,15 +173,18 @@ cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry(
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(propertyValue);
cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
- return new TargetPropertyEntryGenex(std::move(cge));
+ return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
+ cm::make_unique<TargetPropertyEntryGenex>(std::move(cge)));
}
- return new TargetPropertyEntryString(propertyValue, std::move(backtrace));
+ return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
+ cm::make_unique<TargetPropertyEntryString>(propertyValue,
+ std::move(backtrace)));
}
void CreatePropertyGeneratorExpressions(
cmStringRange entries, cmBacktraceRange backtraces,
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
+ std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
bool evaluateForBuildsystem = false)
{
auto btIt = backtraces.begin();
@@ -219,13 +223,13 @@ struct EvaluatedTargetPropertyEntry
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
- cmGeneratorTarget::TargetPropertyEntry* entry)
+ cmGeneratorTarget::TargetPropertyEntry& entry)
{
- EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace());
- cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config,
- thisTarget, dagChecker, lang),
+ EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
+ cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
+ thisTarget, dagChecker, lang),
ee.Values);
- if (entry->GetHadContextSensitiveCondition()) {
+ if (entry.GetHadContextSensitiveCondition()) {
ee.ContextDependent = true;
}
return ee;
@@ -234,13 +238,14 @@ EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in)
+ std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
+ in)
{
std::vector<EvaluatedTargetPropertyEntry> out;
out.reserve(in.size());
- for (cmGeneratorTarget::TargetPropertyEntry* entry : in) {
+ for (auto& entry : in) {
out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang,
- dagChecker, entry));
+ dagChecker, *entry));
}
return out;
}
@@ -304,23 +309,12 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
this->PolicyMap = t->GetPolicyMap();
}
-cmGeneratorTarget::~cmGeneratorTarget()
-{
- cmDeleteAll(this->IncludeDirectoriesEntries);
- cmDeleteAll(this->CompileOptionsEntries);
- cmDeleteAll(this->CompileFeaturesEntries);
- cmDeleteAll(this->CompileDefinitionsEntries);
- cmDeleteAll(this->LinkOptionsEntries);
- cmDeleteAll(this->LinkDirectoriesEntries);
- cmDeleteAll(this->PrecompileHeadersEntries);
- cmDeleteAll(this->SourceEntries);
- cmDeleteAll(this->LinkInformation);
-}
+cmGeneratorTarget::~cmGeneratorTarget() = default;
const char* cmGeneratorTarget::GetSourcesProperty() const
{
std::vector<std::string> values;
- for (TargetPropertyEntry* se : this->SourceEntries) {
+ for (auto& se : this->SourceEntries) {
values.push_back(se->GetInput());
}
static std::string value;
@@ -1670,6 +1664,19 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
}
}
+std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
+{
+ std::set<std::string> languages;
+ std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
+ for (AllConfigSource const& si : sources) {
+ std::string const& lang = si.Source->GetOrDetermineLanguage();
+ if (!lang.empty()) {
+ languages.emplace(lang);
+ }
+ }
+ return languages;
+}
+
std::string cmGeneratorTarget::GetCompilePDBName(
const std::string& config) const
{
@@ -2112,7 +2119,9 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
// If building directly for installation then the build tree install_name
// is the same as the install tree.
if (this->MacOSXUseInstallNameDir()) {
- return this->GetInstallNameDirForInstallTree();
+ std::string installPrefix =
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ return this->GetInstallNameDirForInstallTree(config, installPrefix);
}
// Use the build tree directory for the target.
@@ -2130,7 +2139,8 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
return "";
}
-std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
+std::string cmGeneratorTarget::GetInstallNameDirForInstallTree(
+ const std::string& config, const std::string& installPrefix) const
{
if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
std::string dir;
@@ -2138,7 +2148,13 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
if (install_name_dir && *install_name_dir) {
- dir = cmStrCat(install_name_dir, '/');
+ dir = install_name_dir;
+ cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix);
+ dir =
+ cmGeneratorExpression::Evaluate(dir, this->LocalGenerator, config);
+ if (!dir.empty()) {
+ dir = cmStrCat(dir, '/');
+ }
}
}
if (!install_name_dir) {
@@ -3275,10 +3291,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
CM_FALLTHROUGH;
}
case cmPolicies::OLD: {
- std::unique_ptr<TargetPropertyEntry> entry(
- CreateTargetPropertyEntry(configProp));
+ std::unique_ptr<TargetPropertyEntry> entry =
+ CreateTargetPropertyEntry(configProp);
entries.emplace_back(EvaluateTargetPropertyEntry(
- this, config, language, &dagChecker, entry.get()));
+ this, config, language, &dagChecker, *entry));
} break;
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
@@ -3334,9 +3350,11 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
const std::string& language) const
{
- if (language != "C" && language != "CXX") {
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
return std::string();
}
+
if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
return std::string();
}
@@ -3367,8 +3385,15 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
filename = generatorTarget->ObjectDirectory;
}
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".h" },
+ { "CXX", ".hxx" },
+ { "OBJC", ".objc.h" },
+ { "OBJCXX", ".objcxx.hxx" }
+ };
+
filename = cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(),
- ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx"));
+ ".dir/cmake_pch", languageToExtension.at(language));
const std::string filename_tmp = cmStrCat(filename, ".tmp");
if (!pchReuseFrom) {
@@ -3418,7 +3443,8 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
std::string cmGeneratorTarget::GetPchSource(const std::string& config,
const std::string& language) const
{
- if (language != "C" && language != "CXX") {
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
return std::string();
}
const auto inserted =
@@ -3444,9 +3470,20 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
// For GCC the source extension will be tranformed into .h[xx].gch
if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
- filename += ((language == "C") ? ".h.c" : ".hxx.cxx");
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".h.c" },
+ { "CXX", ".hxx.cxx" },
+ { "OBJC", ".objc.h.m" },
+ { "OBJCXX", ".objcxx.hxx.mm" }
+ };
+
+ filename += languageToExtension.at(language);
} else {
- filename += ((language == "C") ? ".c" : ".cxx");
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".c" }, { "CXX", ".cxx" }, { "OBJC", ".m" }, { "OBJCXX", ".mm" }
+ };
+
+ filename += languageToExtension.at(language);
}
const std::string filename_tmp = cmStrCat(filename, ".tmp");
@@ -3464,7 +3501,8 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
const std::string& language)
{
- if (language != "C" && language != "CXX") {
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
return std::string();
}
const auto inserted =
@@ -3743,10 +3781,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
std::vector<std::string> options = cmExpandedList(linkOptions);
for (const auto& option : options) {
- std::unique_ptr<TargetPropertyEntry> entry(
- CreateTargetPropertyEntry(option));
- entries.emplace_back(EvaluateTargetPropertyEntry(
- this, config, language, &dagChecker, entry.get()));
+ std::unique_ptr<TargetPropertyEntry> entry =
+ CreateTargetPropertyEntry(option);
+ entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language,
+ &dagChecker, *entry));
}
}
processOptions(this, entries, result, uniqueOptions, false,
@@ -3897,10 +3935,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
std::vector<std::string> depends = cmExpandedList(linkDepends);
for (const auto& depend : depends) {
- std::unique_ptr<TargetPropertyEntry> entry(
- CreateTargetPropertyEntry(depend));
- entries.emplace_back(EvaluateTargetPropertyEntry(
- this, config, language, &dagChecker, entry.get()));
+ std::unique_ptr<TargetPropertyEntry> entry =
+ CreateTargetPropertyEntry(depend);
+ entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language,
+ &dagChecker, *entry));
}
}
AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
@@ -4684,9 +4722,9 @@ std::string intersect(const std::set<std::string>& s1,
}
void cmGeneratorTarget::CheckPropertyCompatibility(
- cmComputeLinkInformation* info, const std::string& config) const
+ cmComputeLinkInformation& info, const std::string& config) const
{
- const cmComputeLinkInformation::ItemVector& deps = info->GetItems();
+ const cmComputeLinkInformation::ItemVector& deps = info.GetItems();
std::set<std::string> emittedBools;
static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
@@ -5031,10 +5069,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
}
std::string interfaceProperty = "INTERFACE_" + p;
- std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter(
- p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter(
- tgt->GetLocalGenerator(), config, tgt)
- : nullptr);
+ std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter;
+ if (p == "POSITION_INDEPENDENT_CODE") {
+ genexInterpreter = cm::make_unique<cmGeneratorExpressionInterpreter>(
+ tgt->GetLocalGenerator(), config, tgt);
+ }
for (cmGeneratorTarget const* theTarget : deps) {
// An error should be reported if one dependency
@@ -5181,22 +5220,19 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
auto i = this->LinkInformation.find(key);
if (i == this->LinkInformation.end()) {
// Compute information for this configuration.
- cmComputeLinkInformation* info =
- new cmComputeLinkInformation(this, config);
- if (!info || !info->Compute()) {
- delete info;
- info = nullptr;
+ auto info = cm::make_unique<cmComputeLinkInformation>(this, config);
+ if (info && !info->Compute()) {
+ info.reset();
}
// Store the information for this configuration.
- cmTargetLinkInformationMap::value_type entry(key, info);
- i = this->LinkInformation.insert(entry).first;
+ i = this->LinkInformation.emplace(key, std::move(info)).first;
- if (info) {
- this->CheckPropertyCompatibility(info, config);
+ if (i->second) {
+ this->CheckPropertyCompatibility(*i->second, config);
}
}
- return i->second;
+ return i->second.get();
}
void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const
@@ -6343,8 +6379,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const
this->GetType() != cmStateEnums::EXECUTABLE) {
return false;
}
- std::set<std::string> languages;
- this->GetLanguages(languages, "");
+ std::set<std::string> languages = this->GetAllConfigCompileLanguages();
// Consider an explicit linker language property, but *not* the
// computed linker language that may depend on linked targets.
const char* linkLang = this->GetProperty("LINKER_LANGUAGE");
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 1f824b1163..f70b969d0b 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -7,6 +7,7 @@
#include <cstddef>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <unordered_map>
@@ -123,7 +124,7 @@ public:
struct AllConfigSource
{
- cmSourceFile const* Source;
+ cmSourceFile* Source;
cmGeneratorTarget::SourceKind Kind;
std::vector<size_t> Configs;
};
@@ -132,6 +133,10 @@ public:
per-source configurations assigned. */
std::vector<AllConfigSource> const& GetAllConfigSources() const;
+ /** Get all languages used to compile sources in any configuration.
+ This excludes the languages of objects from object libraries. */
+ std::set<std::string> GetAllConfigCompileLanguages() const;
+
void GetObjectSources(std::vector<cmSourceFile const*>&,
const std::string& config) const;
const std::string& GetObjectName(cmSourceFile const* file);
@@ -272,7 +277,8 @@ public:
/** Return the install name directory for the target in the
* install tree. For example: "\@rpath/" or "\@loader_path/". */
- std::string GetInstallNameDirForInstallTree() const;
+ std::string GetInstallNameDirForInstallTree(
+ const std::string& config, const std::string& installPrefix) const;
cmListFileBacktrace GetBacktrace() const;
@@ -811,10 +817,10 @@ private:
mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap;
using cmTargetLinkInformationMap =
- std::map<std::string, cmComputeLinkInformation*>;
+ std::map<std::string, std::unique_ptr<cmComputeLinkInformation>>;
mutable cmTargetLinkInformationMap LinkInformation;
- void CheckPropertyCompatibility(cmComputeLinkInformation* info,
+ void CheckPropertyCompatibility(cmComputeLinkInformation& info,
const std::string& config) const;
struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
@@ -877,14 +883,17 @@ private:
bool MaybeHaveInterfaceProperty(std::string const& prop,
cmGeneratorExpressionContext* context) const;
- std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
- std::vector<TargetPropertyEntry*> CompileOptionsEntries;
- std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
- std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
- std::vector<TargetPropertyEntry*> LinkOptionsEntries;
- std::vector<TargetPropertyEntry*> LinkDirectoriesEntries;
- std::vector<TargetPropertyEntry*> PrecompileHeadersEntries;
- std::vector<TargetPropertyEntry*> SourceEntries;
+ using TargetPropertyEntryVector =
+ std::vector<std::unique_ptr<TargetPropertyEntry>>;
+
+ TargetPropertyEntryVector IncludeDirectoriesEntries;
+ TargetPropertyEntryVector CompileOptionsEntries;
+ TargetPropertyEntryVector CompileFeaturesEntries;
+ TargetPropertyEntryVector CompileDefinitionsEntries;
+ TargetPropertyEntryVector LinkOptionsEntries;
+ TargetPropertyEntryVector LinkDirectoriesEntries;
+ TargetPropertyEntryVector PrecompileHeadersEntries;
+ TargetPropertyEntryVector SourceEntries;
mutable std::set<std::string> LinkImplicitNullProperties;
mutable std::map<std::string, std::string> PchHeaders;
mutable std::map<std::string, std::string> PchSources;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 96656a5997..2efafc64ba 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -165,7 +165,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
return false;
}
-bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
+bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool,
cmMakefile* mf)
{
if (ts.empty()) {
@@ -650,7 +650,7 @@ void cmGlobalGenerator::EnableLanguage(
// Tell the generator about the toolset, if any.
std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET");
- if (!this->SetGeneratorToolset(toolset, mf)) {
+ if (!this->SetGeneratorToolset(toolset, false, mf)) {
cmSystemTools::SetFatalErrorOccured();
return;
}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index f25ff7b77e..0e8735775e 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -128,7 +128,8 @@ public:
/** Set the generator-specific toolset name. Returns true if toolset
is supported and false otherwise. */
- virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ virtual bool SetGeneratorToolset(std::string const& ts, bool build,
+ cmMakefile* mf);
/**
* Create LocalGenerators and process the CMakeLists files. This does not
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 5a708abbcb..7afcd496e7 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -64,8 +64,11 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
}
bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
- cmMakefile* mf)
+ bool build, cmMakefile* mf)
{
+ if (build) {
+ return true;
+ }
std::string tsp; /* toolset path */
this->GetToolset(mf, tsp, ts);
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index ccfe073820..7cd8c794ce 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -58,7 +58,8 @@ public:
static bool SupportsPlatform() { return true; }
// Toolset / Platform Support
- bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+ bool SetGeneratorToolset(std::string const& ts, bool build,
+ cmMakefile* mf) override;
bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
/**
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 09a49e1e9d..5b83e2fe99 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -26,6 +26,16 @@
static const char vs10generatorName[] = "Visual Studio 10 2010";
static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;
+static void ConvertToWindowsSlashes(std::string& s)
+{
+ // first convert all of the slashes
+ for (auto& ch : s) {
+ if (ch == '/') {
+ ch = '\\';
+ }
+ }
+}
+
// Map generator name without year to name with year.
static const char* cmVS10GenName(const std::string& name, std::string& genName)
{
@@ -193,7 +203,7 @@ static void cmCudaToolVersion(std::string& s)
}
bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
- std::string const& ts, cmMakefile* mf)
+ std::string const& ts, bool build, cmMakefile* mf)
{
if (this->SystemIsWindowsCE && ts.empty() &&
this->DefaultPlatformToolset.empty()) {
@@ -208,7 +218,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
return false;
}
- if (!this->FindVCTargetsPath(mf)) {
+ if (build) {
+ return true;
+ }
+
+ if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) {
return false;
}
@@ -349,6 +363,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
}
+ if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR",
+ vcTargetsDir);
+ }
+
return true;
}
@@ -442,6 +461,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
this->GeneratorToolsetVersion = value;
return true;
}
+ if (key == "VCTargetsPath") {
+ this->CustomVCTargetsPath = value;
+ ConvertToWindowsSlashes(this->CustomVCTargetsPath);
+ return true;
+ }
return false;
}
@@ -603,6 +627,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage(
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
+const char* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const
+{
+ if (this->CustomVCTargetsPath.empty()) {
+ return nullptr;
+ }
+ return this->CustomVCTargetsPath.c_str();
+}
+
const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
{
std::string const& toolset = this->GetPlatformToolsetString();
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 9adcf08ae2..8a760476d0 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -20,7 +20,8 @@ public:
bool SetSystemName(std::string const& s, cmMakefile* mf) override;
bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
- bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+ bool SetGeneratorToolset(std::string const& ts, bool build,
+ cmMakefile* mf) override;
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
@@ -45,6 +46,9 @@ public:
bool IsNsightTegra() const;
std::string GetNsightTegraVersion() const;
+ /** The vctargets path for the target platform. */
+ const char* GetCustomVCTargetsPath() const;
+
/** The toolset name for the target platform. */
const char* GetPlatformToolset() const;
std::string const& GetPlatformToolsetString() const;
@@ -155,6 +159,7 @@ protected:
std::string GeneratorToolset;
std::string GeneratorToolsetVersion;
std::string GeneratorToolsetHostArchitecture;
+ std::string GeneratorToolsetCustomVCTargetsDir;
std::string GeneratorToolsetCuda;
std::string GeneratorToolsetCudaCustomDir;
std::string DefaultPlatformToolset;
@@ -206,6 +211,7 @@ private:
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ std::string CustomVCTargetsPath;
std::string VCTargetsPath;
bool FindVCTargetsPath(cmMakefile* mf);
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index ed0cba7ddf..54124070d7 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -799,19 +799,9 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
cmGeneratorTarget const* gt)
{
- // check to see if this is a fortran build
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- }
-
// If there's only one source language, Fortran has to be used
// in order for the sources to compile.
- std::set<std::string> languages;
- gt->GetLanguages(languages, "");
+ std::set<std::string> languages = gt->GetAllConfigCompileLanguages();
// Consider an explicit linker language property, but *not* the
// computed linker language that may depend on linked targets.
// This allows the project to control the language choice in
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 67f1a46103..998ffa6918 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -267,7 +267,7 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
}
bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
- cmMakefile* mf)
+ bool build, cmMakefile* mf)
{
if (ts.find_first_of(",=") != std::string::npos) {
std::ostringstream e;
@@ -283,6 +283,9 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
return false;
}
this->GeneratorToolset = ts;
+ if (build) {
+ return true;
+ }
if (!this->GeneratorToolset.empty()) {
mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
}
@@ -776,7 +779,7 @@ public:
"Xcode does not support per-config per-source " << property << ":\n"
" " << expression << "\n"
"specified for source:\n"
- " " << this->SourceFile->GetFullPath() << "\n";
+ " " << this->SourceFile->ResolveFullPath() << "\n";
/* clang-format on */
this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
@@ -850,7 +853,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
cmXCodeObject* buildFile =
- this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
+ this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
@@ -896,7 +899,8 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
std::string listfile =
cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
"/CMakeLists.txt");
- cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(listfile);
+ cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
if (!cmContains(sources, srcCMakeLists)) {
sources.push_back(srcCMakeLists);
}
@@ -1029,7 +1033,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference(
{
std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- return this->CreateXCodeFileReferenceFromPath(sf->GetFullPath(), target,
+ return this->CreateXCodeFileReferenceFromPath(sf->ResolveFullPath(), target,
lang, sf);
}
@@ -1064,7 +1068,7 @@ struct cmSourceFilePathCompare
{
bool operator()(cmSourceFile* l, cmSourceFile* r)
{
- return l->GetFullPath() < r->GetFullPath();
+ return l->ResolveFullPath() < r->ResolveFullPath();
}
};
@@ -1139,7 +1143,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
// 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);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
classes.push_back(sf);
}
@@ -2855,15 +2860,17 @@ bool cmGlobalXCodeGenerator::CreateGroups(
std::string listfile =
cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(),
"/CMakeLists.txt");
- cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile);
- addSourceToGroup(sf->GetFullPath());
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
}
// 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);
- addSourceToGroup(sf->GetFullPath());
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
}
}
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index af905d00c4..f60ea728d8 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -103,7 +103,8 @@ public:
bool ShouldStripResourcePath(cmMakefile*) const override;
- bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+ bool SetGeneratorToolset(std::string const& ts, bool build,
+ cmMakefile* mf) override;
void AppendFlag(std::string& flags, std::string const& flag) const;
protected:
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index e0d545d86d..7759c5f9d3 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -2,174 +2,190 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGraphVizWriter.h"
-#include <cstddef>
+#include <cctype>
#include <iostream>
#include <memory>
-#include <sstream>
+#include <set>
#include <utility>
+#include <cm/memory>
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmake.h"
namespace {
-enum LinkLibraryScopeType
-{
- LLT_SCOPE_PUBLIC,
- LLT_SCOPE_PRIVATE,
- LLT_SCOPE_INTERFACE
-};
-const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed";
-const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted";
+char const* const GRAPHVIZ_EDGE_STYLE_PUBLIC = "solid";
+char const* const GRAPHVIZ_EDGE_STYLE_INTERFACE = "dashed";
+char const* const GRAPHVIZ_EDGE_STYLE_PRIVATE = "dotted";
-std::string getLinkLibraryStyle(const LinkLibraryScopeType& type)
-{
- std::string style;
- switch (type) {
- case LLT_SCOPE_PRIVATE:
- style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]";
- break;
- case LLT_SCOPE_INTERFACE:
- style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]";
- break;
- default:
- break;
- }
- return style;
-}
+char const* const GRAPHVIZ_NODE_SHAPE_EXECUTABLE = "egg"; // egg-xecutable
+
+// Normal libraries.
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC = "octagon";
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED = "doubleoctagon";
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE = "tripleoctagon";
-const char* getShapeForTarget(const cmGeneratorTarget* target)
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE = "pentagon";
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT = "hexagon";
+char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN = "septagon";
+
+char const* const GRAPHVIZ_NODE_SHAPE_UTILITY = "box";
+
+const char* getShapeForTarget(const cmLinkItem& item)
{
- if (!target) {
- return "ellipse";
+ if (item.Target == nullptr) {
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN;
}
- switch (target->GetType()) {
+ switch (item.Target->GetType()) {
case cmStateEnums::EXECUTABLE:
- return "house";
+ return GRAPHVIZ_NODE_SHAPE_EXECUTABLE;
case cmStateEnums::STATIC_LIBRARY:
- return "diamond";
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC;
case cmStateEnums::SHARED_LIBRARY:
- return "polygon";
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED;
case cmStateEnums::MODULE_LIBRARY:
- return "octagon";
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE;
+ case cmStateEnums::OBJECT_LIBRARY:
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT;
+ case cmStateEnums::UTILITY:
+ return GRAPHVIZ_NODE_SHAPE_UTILITY;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE;
+ case cmStateEnums::UNKNOWN_LIBRARY:
default:
- break;
+ return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN;
}
+}
+}
- return "box";
+cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName,
+ const cmGlobalGenerator* globalGenerator)
+ : FileName(fileName)
+ , GlobalFileStream(fileName)
+ , GraphName(globalGenerator->GetSafeGlobalSetting("CMAKE_PROJECT_NAME"))
+ , GraphHeader("node [\n fontsize = \"12\"\n];")
+ , GraphNodePrefix("node")
+ , GlobalGenerator(globalGenerator)
+ , NextNodeId(0)
+ , GenerateForExecutables(true)
+ , GenerateForStaticLibs(true)
+ , GenerateForSharedLibs(true)
+ , GenerateForModuleLibs(true)
+ , GenerateForInterfaceLibs(true)
+ , GenerateForObjectLibs(true)
+ , GenerateForUnknownLibs(true)
+ , GenerateForCustomTargets(false)
+ , GenerateForExternals(true)
+ , GeneratePerTarget(true)
+ , GenerateDependers(true)
+{
}
-std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
- cmTarget* Target, const cmGlobalGenerator* globalGenerator)
+cmGraphVizWriter::~cmGraphVizWriter()
{
- char sep = ';';
- std::map<std::string, LinkLibraryScopeType> tokens;
- size_t start = 0;
- size_t end = 0;
+ this->WriteFooter(this->GlobalFileStream);
- const char* pInterfaceLinkLibraries =
- Target->GetProperty("INTERFACE_LINK_LIBRARIES");
- const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES");
+ for (auto& fileStream : this->PerTargetFileStreams) {
+ this->WriteFooter(*fileStream.second);
+ }
- if (!pInterfaceLinkLibraries && !pLinkLibraries) {
- return tokens; // target is not linked against any other libraries
+ for (auto& fileStream : this->TargetDependersFileStreams) {
+ this->WriteFooter(*fileStream.second);
}
+}
- // make sure we don't touch a null-ptr
- auto interfaceLinkLibraries =
- std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : "");
- auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : "");
+void cmGraphVizWriter::VisitGraph(std::string const&)
+{
+ this->WriteHeader(GlobalFileStream, this->GraphName);
+ this->WriteLegend(GlobalFileStream);
+}
- // first extract interfaceLinkLibraries
- while (start < interfaceLinkLibraries.length()) {
+void cmGraphVizWriter::OnItem(cmLinkItem const& item)
+{
+ if (this->ItemExcluded(item)) {
+ return;
+ }
- if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) {
- end = interfaceLinkLibraries.length();
- }
+ NodeNames[item.AsStr()] = cmStrCat(GraphNodePrefix, NextNodeId);
+ ++NextNodeId;
- std::string element = interfaceLinkLibraries.substr(start, end - start);
- if (globalGenerator->IsAlias(element)) {
- const auto tgt = globalGenerator->FindTarget(element);
- if (tgt) {
- element = tgt->GetName();
- }
- }
+ this->WriteNode(this->GlobalFileStream, item);
- if (std::string::npos == element.find("$<LINK_ONLY:", 0)) {
- // we assume first, that this library is an interface library.
- // if we find it again in the linklibraries property, we promote it to an
- // public library.
- tokens[element] = LLT_SCOPE_INTERFACE;
- } else {
- // this is an private linked static library.
- // we take care of this case in the second iterator.
- }
- start = end + 1;
+ if (this->GeneratePerTarget) {
+ this->CreateTargetFile(this->PerTargetFileStreams, item);
}
- // second extract linkLibraries
- start = 0;
- while (start < linkLibraries.length()) {
-
- if ((end = linkLibraries.find(sep, start)) == std::string::npos) {
- end = linkLibraries.length();
- }
+ if (this->GenerateDependers) {
+ this->CreateTargetFile(this->TargetDependersFileStreams, item,
+ ".dependers");
+ }
+}
- std::string element = linkLibraries.substr(start, end - start);
- if (globalGenerator->IsAlias(element)) {
- const auto tgt = globalGenerator->FindTarget(element);
- if (tgt) {
- element = tgt->GetName();
- }
- }
+void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap,
+ cmLinkItem const& item,
+ std::string const& fileNameSuffix)
+{
+ auto const pathSafeItemName = PathSafeString(item.AsStr());
+ auto const perTargetFileName =
+ cmStrCat(this->FileName, '.', pathSafeItemName, fileNameSuffix);
+ auto perTargetFileStream =
+ cm::make_unique<cmGeneratedFileStream>(perTargetFileName);
- if (tokens.find(element) == tokens.end()) {
- // this library is not found in interfaceLinkLibraries but in
- // linkLibraries.
- // this results in a private linked library.
- tokens[element] = LLT_SCOPE_PRIVATE;
- } else if (LLT_SCOPE_INTERFACE == tokens[element]) {
- // this library is found in interfaceLinkLibraries and linkLibraries.
- // this results in a public linked library.
- tokens[element] = LLT_SCOPE_PUBLIC;
- } else {
- // private and public linked libraries should not be changed anymore.
- }
+ this->WriteHeader(*perTargetFileStream, item.AsStr());
+ this->WriteNode(*perTargetFileStream, item);
- start = end + 1;
- }
+ fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream));
+}
- return tokens;
+void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee,
+ DependencyType dt)
+{
+ this->VisitLink(depender, dependee, true, GetEdgeStyle(dt));
}
+
+void cmGraphVizWriter::OnIndirectLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee)
+{
+ this->VisitLink(depender, dependee, false);
}
-cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator)
- : GraphType("digraph")
- , GraphName("GG")
- , GraphHeader("node [\n fontsize = \"12\"\n];")
- , GraphNodePrefix("node")
- , GlobalGenerator(globalGenerator)
- , LocalGenerators(globalGenerator->GetLocalGenerators())
- , GenerateForExecutables(true)
- , GenerateForStaticLibs(true)
- , GenerateForSharedLibs(true)
- , GenerateForModuleLibs(true)
- , GenerateForInterface(true)
- , GenerateForExternals(true)
- , GeneratePerTarget(true)
- , GenerateDependers(true)
- , HaveTargetsAndLibs(false)
+void cmGraphVizWriter::VisitLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee, bool isDirectLink,
+ std::string const& scopeType)
{
+ if (this->ItemExcluded(depender) || this->ItemExcluded(dependee)) {
+ return;
+ }
+
+ if (!isDirectLink) {
+ return;
+ }
+
+ this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType);
+
+ if (this->GeneratePerTarget) {
+ auto fileStream = PerTargetFileStreams[depender.AsStr()].get();
+ this->WriteNode(*fileStream, dependee);
+ this->WriteConnection(*fileStream, depender, dependee, scopeType);
+ }
+
+ if (this->GenerateDependers) {
+ auto fileStream = TargetDependersFileStreams[dependee.AsStr()].get();
+ this->WriteNode(*fileStream, depender);
+ this->WriteConnection(*fileStream, depender, dependee, scopeType);
+ }
}
void cmGraphVizWriter::ReadSettings(
@@ -208,7 +224,6 @@ void cmGraphVizWriter::ReadSettings(
} \
} while (false)
- __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE");
__set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
__set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
__set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
@@ -225,7 +240,10 @@ void cmGraphVizWriter::ReadSettings(
__set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
__set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
__set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
- __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE");
+ __set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS");
+ __set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS");
+ __set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS");
+ __set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS");
__set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
__set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
__set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");
@@ -248,329 +266,170 @@ void cmGraphVizWriter::ReadSettings(
}
}
-// Iterate over all targets and write for each one a graph which shows
-// which other targets depend on it.
-void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName)
+void cmGraphVizWriter::Write()
{
- if (!this->GenerateDependers) {
- return;
- }
-
- this->CollectTargetsAndLibs();
-
- for (auto const& ptr : this->TargetPtrs) {
- if (ptr.second == nullptr) {
- continue;
- }
-
- if (!this->GenerateForTargetType(ptr.second->GetType())) {
- continue;
- }
-
- std::string currentFilename =
- cmStrCat(fileName, '.', ptr.first, ".dependers");
-
- cmGeneratedFileStream str(currentFilename);
- if (!str) {
- return;
+ auto gg = this->GlobalGenerator;
+
+ this->VisitGraph(gg->GetName());
+
+ // We want to traverse in a determined order, such that the output is always
+ // the same for a given project (this makes tests reproducible, etc.)
+ std::set<cmGeneratorTarget const*, cmGeneratorTarget::StrictTargetComparison>
+ sortedGeneratorTargets;
+
+ for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ for (cmGeneratorTarget const* gt : lg->GetGeneratorTargets()) {
+ // Reserved targets have inconsistent names across platforms (e.g. 'all'
+ // vs. 'ALL_BUILD'), which can disrupt the traversal ordering.
+ // We don't need or want them anyway.
+ if (!cmGlobalGenerator::IsReservedTarget(gt->GetName())) {
+ sortedGeneratorTargets.insert(gt);
+ }
}
-
- std::set<std::string> insertedConnections;
- std::set<std::string> insertedNodes;
-
- std::cout << "Writing " << currentFilename << "..." << std::endl;
- this->WriteHeader(str);
-
- this->WriteDependerConnections(ptr.first, insertedNodes,
- insertedConnections, str);
-
- this->WriteFooter(str);
- }
-}
-
-// Iterate over all targets and write for each one a graph which shows
-// on which targets it depends.
-void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName)
-{
- if (!this->GeneratePerTarget) {
- return;
}
- this->CollectTargetsAndLibs();
-
- for (auto const& ptr : this->TargetPtrs) {
- if (ptr.second == nullptr) {
- continue;
- }
-
- if (!this->GenerateForTargetType(ptr.second->GetType())) {
- continue;
- }
-
- std::set<std::string> insertedConnections;
- std::set<std::string> insertedNodes;
-
- std::string currentFilename = cmStrCat(fileName, '.', ptr.first);
- cmGeneratedFileStream str(currentFilename);
- if (!str) {
- return;
- }
-
- std::cout << "Writing " << currentFilename << "..." << std::endl;
- this->WriteHeader(str);
-
- this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
- this->WriteFooter(str);
+ for (auto const gt : sortedGeneratorTargets) {
+ auto item = cmLinkItem(gt, gt->GetBacktrace());
+ this->VisitItem(item);
}
}
-void cmGraphVizWriter::WriteGlobalFile(const std::string& fileName)
+void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs,
+ const std::string& name)
{
- this->CollectTargetsAndLibs();
-
- cmGeneratedFileStream str(fileName);
- if (!str) {
- return;
- }
- this->WriteHeader(str);
-
- std::cout << "Writing " << fileName << "..." << std::endl;
-
- std::set<std::string> insertedConnections;
- std::set<std::string> insertedNodes;
-
- for (auto const& ptr : this->TargetPtrs) {
- if (ptr.second == nullptr) {
- continue;
- }
-
- if (!this->GenerateForTargetType(ptr.second->GetType())) {
- continue;
- }
-
- this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
- }
- this->WriteFooter(str);
+ auto const escapedGraphName = EscapeForDotFile(name);
+ fs << "digraph \"" << escapedGraphName << "\" {" << std::endl;
+ fs << this->GraphHeader << std::endl;
}
-void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const
+void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& fs)
{
- str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl;
- str << this->GraphHeader << std::endl;
+ fs << "}" << std::endl;
}
-void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const
+void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs)
{
- str << "}" << std::endl;
+ // Note that the subgraph name must start with "cluster", as done here, to
+ // make Graphviz layout engines do the right thing and keep the nodes
+ // together.
+ fs << "subgraph clusterLegend {" << std::endl;
+ fs << " label = \"Legend\";" << std::endl;
+ // Set the color of the box surrounding the legend.
+ fs << " color = black;" << std::endl;
+ // We use invisible edges just to enforce the layout.
+ fs << " edge [ style = invis ];" << std::endl;
+
+ // Nodes.
+ fs << " legendNode0 [ label = \"Executable\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];" << std::endl;
+
+ fs << " legendNode1 [ label = \"Static Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];" << std::endl;
+ fs << " legendNode2 [ label = \"Shared Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];" << std::endl;
+ fs << " legendNode3 [ label = \"Module Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];" << std::endl;
+
+ fs << " legendNode4 [ label = \"Interface Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];" << std::endl;
+ fs << " legendNode5 [ label = \"Object Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];" << std::endl;
+ fs << " legendNode6 [ label = \"Unknown Library\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];" << std::endl;
+
+ fs << " legendNode7 [ label = \"Custom Target\", shape = "
+ << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];" << std::endl;
+
+ // Edges.
+ // Some of those are dummy (invisible) edges to enforce a layout.
+ fs << " legendNode0 -> legendNode1 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC
+ << " ];" << std::endl;
+ fs << " legendNode0 -> legendNode2 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC
+ << " ];" << std::endl;
+ fs << " legendNode0 -> legendNode3;" << std::endl;
+
+ fs << " legendNode1 -> legendNode4 [ label = \"Interface\", style = "
+ << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];" << std::endl;
+ fs << " legendNode2 -> legendNode5 [ label = \"Private\", style = "
+ << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];" << std::endl;
+ fs << " legendNode3 -> legendNode6 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC
+ << " ];" << std::endl;
+
+ fs << " legendNode0 -> legendNode7;" << std::endl;
+
+ fs << "}" << std::endl;
}
-void cmGraphVizWriter::WriteConnections(
- const std::string& targetName, std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
+void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs,
+ cmLinkItem const& item)
{
- auto targetPtrIt = this->TargetPtrs.find(targetName);
+ auto const& itemName = item.AsStr();
+ auto const& nodeName = this->NodeNames[itemName];
- if (targetPtrIt == this->TargetPtrs.end()) // not found at all
- {
- return;
- }
-
- this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
-
- if (targetPtrIt->second == nullptr) // it's an external library
- {
- return;
- }
+ auto const itemNameWithAliases = ItemNameWithAliases(itemName);
+ auto const escapedLabel = EscapeForDotFile(itemNameWithAliases);
- std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
- std::map<std::string, LinkLibraryScopeType> ll =
- getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target,
- GlobalGenerator);
-
- for (auto const& llit : ll) {
- const std::string& libName = llit.first;
- auto libNameIt = this->TargetNamesNodes.find(libName);
-
- // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
- if (libNameIt == this->TargetNamesNodes.end()) {
- continue;
- }
+ fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel
+ << "\", shape = " << getShapeForTarget(item) << " ];" << std::endl;
+}
- std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second);
- if (insertedConnections.find(connectionName) ==
- insertedConnections.end()) {
- insertedConnections.insert(connectionName);
- this->WriteNode(libName, this->TargetPtrs.find(libName)->second,
- insertedNodes, str);
+void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs,
+ cmLinkItem const& depender,
+ cmLinkItem const& dependee,
+ std::string const& edgeStyle)
+{
+ auto const& dependerName = depender.AsStr();
+ auto const& dependeeName = dependee.AsStr();
- str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\"";
+ fs << " \"" << this->NodeNames[dependerName] << "\" -> \""
+ << this->NodeNames[dependeeName] << "\" ";
- str << getLinkLibraryStyle(llit.second);
+ fs << edgeStyle;
- str << " // " << targetName << " -> " << libName << std::endl;
- this->WriteConnections(libName, insertedNodes, insertedConnections, str);
- }
- }
+ fs << " // " << dependerName << " -> " << dependeeName << std::endl;
}
-void cmGraphVizWriter::WriteDependerConnections(
- const std::string& targetName, std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
+bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item)
{
- auto targetPtrIt = this->TargetPtrs.find(targetName);
+ auto const itemName = item.AsStr();
- if (targetPtrIt == this->TargetPtrs.end()) // not found at all
- {
- return;
+ if (this->ItemNameFilteredOut(itemName)) {
+ return true;
}
- this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
-
- if (targetPtrIt->second == nullptr) // it's an external library
- {
- return;
+ if (item.Target == nullptr) {
+ return !this->GenerateForExternals;
}
- std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
-
- // now search who links against me
- for (auto const& tptr : this->TargetPtrs) {
- if (tptr.second == nullptr) {
- continue;
- }
-
- if (!this->GenerateForTargetType(tptr.second->GetType())) {
- continue;
- }
-
- // Now we have a target, check whether it links against targetName.
- // If so, draw a connection, and then continue with dependers on that one.
- std::map<std::string, LinkLibraryScopeType> ll =
- getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator);
-
- for (auto const& llit : ll) {
- if (llit.first == targetName) {
- // So this target links against targetName.
- auto dependerNodeNameIt = this->TargetNamesNodes.find(tptr.first);
-
- if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
- std::string connectionName =
- cmStrCat(dependerNodeNameIt->second, '-', myNodeName);
-
- if (insertedConnections.find(connectionName) ==
- insertedConnections.end()) {
- insertedConnections.insert(connectionName);
- this->WriteNode(tptr.first, tptr.second, insertedNodes, str);
-
- str << " \"" << dependerNodeNameIt->second << "\" -> \""
- << myNodeName << "\"";
- str << " // " << targetName << " -> " << tptr.first << std::endl;
- str << getLinkLibraryStyle(llit.second);
- this->WriteDependerConnections(tptr.first, insertedNodes,
- insertedConnections, str);
- }
- }
- break;
- }
+ if (item.Target->GetType() == cmStateEnums::UTILITY) {
+ if ((itemName.find("Nightly") == 0) ||
+ (itemName.find("Continuous") == 0) ||
+ (itemName.find("Experimental") == 0)) {
+ return true;
}
}
-}
-void cmGraphVizWriter::WriteNode(const std::string& targetName,
- const cmGeneratorTarget* target,
- std::set<std::string>& insertedNodes,
- cmGeneratedFileStream& str) const
-{
- if (insertedNodes.find(targetName) == insertedNodes.end()) {
- insertedNodes.insert(targetName);
- auto nameIt = this->TargetNamesNodes.find(targetName);
-
- str << " \"" << nameIt->second << "\" [ label=\"" << targetName
- << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl;
+ if (item.Target->IsImported() && !this->GenerateForExternals) {
+ return true;
}
-}
-void cmGraphVizWriter::CollectTargetsAndLibs()
-{
- if (!this->HaveTargetsAndLibs) {
- this->HaveTargetsAndLibs = true;
- int cnt = this->CollectAllTargets();
- if (this->GenerateForExternals) {
- this->CollectAllExternalLibs(cnt);
- }
- }
+ return !this->TargetTypeEnabled(item.Target->GetType());
}
-int cmGraphVizWriter::CollectAllTargets()
+bool cmGraphVizWriter::ItemNameFilteredOut(std::string const& itemName)
{
- int cnt = 0;
- // First pass get the list of all cmake targets
- for (cmLocalGenerator* lg : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
- for (cmGeneratorTarget* target : targets) {
- const std::string& realTargetName = target->GetName();
- if (this->IgnoreThisTarget(realTargetName)) {
- // Skip ignored targets
- continue;
- }
- // std::cout << "Found target: " << tit->first << std::endl;
- std::ostringstream ostr;
- ostr << this->GraphNodePrefix << cnt++;
- this->TargetNamesNodes[realTargetName] = ostr.str();
- this->TargetPtrs[realTargetName] = target;
- }
+ if (itemName == ">") {
+ // FIXME: why do we even receive such a target here?
+ return true;
}
- return cnt;
-}
-
-int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
-{
- // Ok, now find all the stuff we link to that is not in cmake
- for (cmLocalGenerator* lg : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
- for (cmGeneratorTarget* target : targets) {
- const std::string& realTargetName = target->GetName();
- if (this->IgnoreThisTarget(realTargetName)) {
- // Skip ignored targets
- continue;
- }
- const cmTarget::LinkLibraryVectorType* ll =
- &(target->Target->GetOriginalLinkLibraries());
- for (auto const& llit : *ll) {
- std::string libName = llit.first;
- if (this->IgnoreThisTarget(libName)) {
- // Skip ignored targets
- continue;
- }
-
- if (GlobalGenerator->IsAlias(libName)) {
- const auto tgt = GlobalGenerator->FindTarget(libName);
- if (tgt) {
- libName = tgt->GetName();
- }
- }
-
- auto tarIt = this->TargetPtrs.find(libName);
- if (tarIt == this->TargetPtrs.end()) {
- std::ostringstream ostr;
- ostr << this->GraphNodePrefix << cnt++;
- this->TargetNamesNodes[libName] = ostr.str();
- this->TargetPtrs[libName] = nullptr;
- // str << " \"" << ostr << "\" [ label=\"" << libName
- // << "\" shape=\"ellipse\"];" << std::endl;
- }
- }
- }
+ if (cmGlobalGenerator::IsReservedTarget(itemName)) {
+ return true;
}
- return cnt;
-}
-bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
-{
for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) {
if (regEx.is_valid()) {
- if (regEx.find(name)) {
+ if (regEx.find(itemName)) {
return true;
}
}
@@ -579,7 +438,7 @@ bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
return false;
}
-bool cmGraphVizWriter::GenerateForTargetType(
+bool cmGraphVizWriter::TargetTypeEnabled(
cmStateEnums::TargetType targetType) const
{
switch (targetType) {
@@ -592,9 +451,73 @@ bool cmGraphVizWriter::GenerateForTargetType(
case cmStateEnums::MODULE_LIBRARY:
return this->GenerateForModuleLibs;
case cmStateEnums::INTERFACE_LIBRARY:
- return this->GenerateForInterface;
+ return this->GenerateForInterfaceLibs;
+ case cmStateEnums::OBJECT_LIBRARY:
+ return this->GenerateForObjectLibs;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ return this->GenerateForUnknownLibs;
+ case cmStateEnums::UTILITY:
+ return this->GenerateForCustomTargets;
+ case cmStateEnums::GLOBAL_TARGET:
+ // Built-in targets like edit_cache, etc.
+ // We don't need/want those in the dot file.
+ return false;
default:
break;
}
return false;
}
+
+std::string cmGraphVizWriter::ItemNameWithAliases(
+ std::string const& itemName) const
+{
+ auto nameWithAliases = itemName;
+
+ for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) {
+ for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) {
+ if (aliasTargets.second == itemName) {
+ nameWithAliases += "\\n(" + aliasTargets.first + ")";
+ }
+ }
+ }
+
+ return nameWithAliases;
+}
+
+std::string cmGraphVizWriter::GetEdgeStyle(DependencyType dt)
+{
+ std::string style;
+ switch (dt) {
+ case DependencyType::LinkPrivate:
+ style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_PRIVATE) + " ]";
+ break;
+ case DependencyType::LinkInterface:
+ style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_INTERFACE) + " ]";
+ break;
+ default:
+ break;
+ }
+ return style;
+}
+
+std::string cmGraphVizWriter::EscapeForDotFile(std::string const& str)
+{
+ return cmSystemTools::EscapeChars(str.data(), "\"");
+}
+
+std::string cmGraphVizWriter::PathSafeString(std::string const& str)
+{
+ std::string pathSafeStr;
+
+ // We'll only keep alphanumerical characters, plus the following ones that
+ // are common, and safe on all platforms:
+ auto const extra_chars = std::set<char>{ '.', '-', '_' };
+
+ for (char c : str) {
+ if (std::isalnum(c) || extra_chars.find(c) != extra_chars.cend()) {
+ pathSafeStr += c;
+ }
+ }
+
+ return pathSafeStr;
+}
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index 9c3051f2c1..578660dbbb 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -6,87 +6,106 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
-#include <set>
+#include <memory>
#include <string>
#include <vector>
#include "cmsys/RegularExpression.hxx"
+#include "cmGeneratedFileStream.h"
+#include "cmLinkItemGraphVisitor.h"
#include "cmStateTypes.h"
-class cmGeneratedFileStream;
-class cmGeneratorTarget;
-class cmLocalGenerator;
+class cmLinkItem;
class cmGlobalGenerator;
/** This class implements writing files for graphviz (dot) for graphs
* representing the dependencies between the targets in the project. */
-class cmGraphVizWriter
+class cmGraphVizWriter : public cmLinkItemGraphVisitor
{
public:
- cmGraphVizWriter(const cmGlobalGenerator* globalGenerator);
+ cmGraphVizWriter(std::string const& fileName,
+ const cmGlobalGenerator* globalGenerator);
+ ~cmGraphVizWriter() override;
+
+ void VisitGraph(std::string const& name) override;
+
+ void OnItem(cmLinkItem const& item) override;
+
+ void OnDirectLink(cmLinkItem const& depender, cmLinkItem const& dependee,
+ DependencyType dt) override;
+
+ void OnIndirectLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee) override;
void ReadSettings(const std::string& settingsFileName,
const std::string& fallbackSettingsFileName);
- void WritePerTargetFiles(const std::string& fileName);
- void WriteTargetDependersFiles(const std::string& fileName);
+ void Write();
+
+private:
+ using FileStreamMap =
+ std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>;
+
+ void VisitLink(cmLinkItem const& depender, cmLinkItem const& dependee,
+ bool isDirectLink, std::string const& scopeType = "");
+
+ void WriteHeader(cmGeneratedFileStream& fs, std::string const& name);
- void WriteGlobalFile(const std::string& fileName);
+ void WriteFooter(cmGeneratedFileStream& fs);
-protected:
- void CollectTargetsAndLibs();
+ void WriteLegend(cmGeneratedFileStream& fs);
- int CollectAllTargets();
+ void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item);
- int CollectAllExternalLibs(int cnt);
+ void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target,
+ std::string const& fileNameSuffix = "");
- void WriteHeader(cmGeneratedFileStream& str) const;
+ void WriteConnection(cmGeneratedFileStream& fs,
+ cmLinkItem const& dependerTargetName,
+ cmLinkItem const& dependeeTargetName,
+ std::string const& edgeStyle);
- void WriteConnections(const std::string& targetName,
- std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections,
- cmGeneratedFileStream& str) const;
+ bool ItemExcluded(cmLinkItem const& item);
+ bool ItemNameFilteredOut(std::string const& itemName);
+ bool TargetTypeEnabled(cmStateEnums::TargetType targetType) const;
- void WriteDependerConnections(const std::string& targetName,
- std::set<std::string>& insertedNodes,
- std::set<std::string>& insertedConnections,
- cmGeneratedFileStream& str) const;
+ std::string ItemNameWithAliases(std::string const& itemName) const;
- void WriteNode(const std::string& targetName,
- const cmGeneratorTarget* target,
- std::set<std::string>& insertedNodes,
- cmGeneratedFileStream& str) const;
+ static std::string GetEdgeStyle(DependencyType dt);
- void WriteFooter(cmGeneratedFileStream& str) const;
+ static std::string EscapeForDotFile(std::string const& str);
- bool IgnoreThisTarget(const std::string& name);
+ static std::string PathSafeString(std::string const& str);
- bool GenerateForTargetType(cmStateEnums::TargetType targetType) const;
+ std::string FileName;
+ cmGeneratedFileStream GlobalFileStream;
+ FileStreamMap PerTargetFileStreams;
+ FileStreamMap TargetDependersFileStreams;
- std::string GraphType;
std::string GraphName;
std::string GraphHeader;
std::string GraphNodePrefix;
std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex;
- const cmGlobalGenerator* GlobalGenerator;
- const std::vector<cmLocalGenerator*>& LocalGenerators;
+ cmGlobalGenerator const* GlobalGenerator;
- std::map<std::string, const cmGeneratorTarget*> TargetPtrs;
- // maps from the actual target names to node names in dot:
- std::map<std::string, std::string> TargetNamesNodes;
+ int NextNodeId;
+ // maps from the actual item names to node names in dot:
+ std::map<std::string, std::string> NodeNames;
bool GenerateForExecutables;
bool GenerateForStaticLibs;
bool GenerateForSharedLibs;
bool GenerateForModuleLibs;
- bool GenerateForInterface;
+ bool GenerateForInterfaceLibs;
+ bool GenerateForObjectLibs;
+ bool GenerateForUnknownLibs;
+ bool GenerateForCustomTargets;
bool GenerateForExternals;
bool GeneratePerTarget;
bool GenerateDependers;
- bool HaveTargetsAndLibs;
};
#endif
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 0cd04cc1d9..69c9b7ed20 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -554,7 +554,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
// components of the install_name field then we need to create a
// mapping to be applied after installation.
std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
- std::string for_install = tgt->GetInstallNameDirForInstallTree();
+ std::string for_install = tgt->GetInstallNameDirForInstallTree(
+ config, "${CMAKE_INSTALL_PREFIX}");
if (for_build != for_install) {
// The directory portions differ. Append the filename to
// create the mapping.
@@ -577,7 +578,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string for_build =
this->Target->GetInstallNameDirForBuildTree(config);
- std::string for_install = this->Target->GetInstallNameDirForInstallTree();
+ std::string for_install = this->Target->GetInstallNameDirForInstallTree(
+ config, "${CMAKE_INSTALL_PREFIX}");
if (this->Target->IsFrameworkOnApple() && for_install.empty()) {
// Frameworks seem to have an id corresponding to their own full
@@ -775,7 +777,7 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
if (this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH")) {
os << "\n" << indent << " INSTALL_REMOVE_ENVIRONMENT_RPATH)\n";
} else {
- os << indent << ")\n";
+ os << ")\n";
}
}
}
diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx
new file mode 100644
index 0000000000..ab2cf9ea11
--- /dev/null
+++ b/Source/cmLinkItemGraphVisitor.cxx
@@ -0,0 +1,142 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLinkItemGraphVisitor.h"
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
+#include "cmMakefile.h"
+
+void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
+{
+ if (this->ItemVisited(item)) {
+ return;
+ }
+
+ this->OnItem(item);
+
+ this->VisitLinks(item, 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()) {
+ this->VisitLinks(item, rootItem, config);
+ }
+}
+
+void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
+ cmLinkItem const& rootItem,
+ std::string const& config)
+{
+ auto const& target = *item.Target;
+
+ DependencyMap dependencies;
+ cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies);
+
+ for (auto const& d : dependencies) {
+ auto const& dependency = d.second;
+ auto const& dependencyType = dependency.first;
+ auto const& dependee = dependency.second;
+ this->VisitItem(dependee);
+
+ if (this->LinkVisited(item, dependee)) {
+ continue;
+ }
+
+ this->OnDirectLink(item, dependee, dependencyType);
+
+ if (rootItem.AsStr() != item.AsStr()) {
+ this->OnIndirectLink(rootItem, dependee);
+ }
+
+ // Visit all the direct and indirect links.
+ this->VisitLinks(dependee, dependee);
+ this->VisitLinks(dependee, item);
+ this->VisitLinks(dependee, rootItem);
+ }
+}
+
+bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item)
+{
+ auto& collection = this->VisitedItems;
+
+ bool const visited = collection.find(item.AsStr()) != collection.cend();
+
+ if (!visited) {
+ collection.insert(item.AsStr());
+ }
+
+ return visited;
+}
+
+bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender,
+ cmLinkItem const& dependee)
+{
+ auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr());
+
+ bool const linkVisited =
+ this->VisitedLinks.find(link) != this->VisitedLinks.cend();
+
+ if (!linkVisited) {
+ this->VisitedLinks.insert(link);
+ }
+
+ return linkVisited;
+}
+
+void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
+ std::string const& config,
+ DependencyMap& dependencies)
+{
+ auto implementationLibraries = target.GetLinkImplementationLibraries(config);
+ if (implementationLibraries != nullptr) {
+ for (auto const& lib : implementationLibraries->Libraries) {
+ auto const& name = lib.AsStr();
+ dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
+ }
+ }
+
+ auto interfaceLibraries =
+ target.GetLinkInterfaceLibraries(config, &target, true);
+ if (interfaceLibraries != nullptr) {
+ for (auto const& lib : interfaceLibraries->Libraries) {
+ auto const& name = lib.AsStr();
+ if (dependencies.find(name) != dependencies.cend()) {
+ dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
+ } else {
+ dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
+ }
+ }
+ }
+
+ std::vector<cmGeneratorTarget*> objectLibraries;
+ target.GetObjectLibrariesCMP0026(objectLibraries);
+ for (auto const& lib : objectLibraries) {
+ auto const& name = lib->GetName();
+ if (dependencies.find(name) == dependencies.cend()) {
+ auto objectItem = cmLinkItem(lib, lib->GetBacktrace());
+ dependencies[name] = Dependency(DependencyType::Object, objectItem);
+ }
+ }
+
+ auto const& utilityItems = target.GetUtilityItems();
+ for (auto const& item : utilityItems) {
+ auto const& name = item.AsStr();
+ if (dependencies.find(name) == dependencies.cend()) {
+ dependencies[name] = Dependency(DependencyType::Utility, item);
+ }
+ }
+}
diff --git a/Source/cmLinkItemGraphVisitor.h b/Source/cmLinkItemGraphVisitor.h
new file mode 100644
index 0000000000..21dc659ad3
--- /dev/null
+++ b/Source/cmLinkItemGraphVisitor.h
@@ -0,0 +1,75 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmLinkItemGraphVisitor_h
+#define cmLinkItemGraphVisitor_h
+
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+
+#include "cmLinkItem.h"
+
+class cmGeneratorTarget;
+
+/** \class cmLinkItemGraphVisitor
+ * \brief Visits a graph of linked items.
+ *
+ * Allows to visit items and dependency links (direct and indirect) between
+ * those items.
+ * This abstract class takes care of the graph traversal, making sure that:
+ * - it terminates even in the presence of cycles;
+ * - it visits every object once (and only once);
+ * - it visits the objects in the same order every time.
+ *
+ * Children classes only have to implement OnItem() etc. to handle whatever
+ * logic they care about.
+ */
+class cmLinkItemGraphVisitor
+{
+public:
+ virtual ~cmLinkItemGraphVisitor() = default;
+
+ virtual void VisitGraph(std::string const& name) = 0;
+
+ void VisitItem(cmLinkItem const& item);
+
+protected:
+ enum class DependencyType
+ {
+ LinkInterface,
+ LinkPublic,
+ LinkPrivate,
+ Object,
+ Utility
+ };
+
+ virtual void OnItem(cmLinkItem const& item) = 0;
+
+ virtual void OnDirectLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee, DependencyType dt) = 0;
+
+ virtual void OnIndirectLink(cmLinkItem const& depender,
+ cmLinkItem const& dependee) = 0;
+
+private:
+ std::set<std::string> VisitedItems;
+
+ std::set<std::pair<std::string, std::string>> VisitedLinks;
+
+ void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem);
+ void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem,
+ std::string const& config);
+
+ using Dependency = std::pair<DependencyType, cmLinkItem>;
+ using DependencyMap = std::map<std::string, Dependency>;
+
+ bool ItemVisited(cmLinkItem const& item);
+ bool LinkVisited(cmLinkItem const& depender, cmLinkItem const& dependee);
+
+ static void GetDependencies(cmGeneratorTarget const& target,
+ std::string const& config,
+ DependencyMap& dependencies);
+};
+
+#endif
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index a2eb1b93e4..4b9b0159f2 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2266,7 +2266,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
std::vector<cmSourceFile*> sources;
target->GetSourceFiles(sources, buildType);
- for (const std::string& lang : { "C", "CXX" }) {
+ for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) {
auto langSources =
std::count_if(sources.begin(), sources.end(), [lang](cmSourceFile* sf) {
return lang == sf->GetLanguage() &&
@@ -2441,7 +2441,6 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
std::back_inserter(filtered_sources), [&](cmSourceFile* sf) {
return sf->GetLanguage() == lang &&
!sf->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION") &&
- !sf->GetPropertyAsBool("GENERATED") &&
!sf->GetProperty("COMPILE_OPTIONS") &&
!sf->GetProperty("COMPILE_DEFINITIONS") &&
!sf->GetProperty("COMPILE_FLAGS") &&
@@ -2453,8 +2452,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
batchSize = filtered_sources.size();
}
- for (size_t itemsLeft = filtered_sources.size(), chunk = batchSize,
- batch = 0;
+ for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
itemsLeft > 0; itemsLeft -= chunk, ++batch) {
chunk = std::min(itemsLeft, batchSize);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index ff1eaec935..fd346df685 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1329,7 +1329,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
if (target->GetType() != cmStateEnums::GLOBAL_TARGET &&
target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
- if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) {
+ if (cmSourceFile* sf = this->CreateVCProjBuildRule()) {
cmGeneratorTarget::AllConfigSource acs;
acs.Source = sf;
acs.Kind = cmGeneratorTarget::SourceKindCustomCommand;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f143ef704f..bf488b11a5 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4487,7 +4487,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::CMP0067 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0069 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 96a6386bf1..bf8183bbf1 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -3,6 +3,11 @@
#include "cmMessageCommand.h"
#include <cassert>
+#include <utility>
+
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
@@ -13,6 +18,55 @@
#include "cmSystemTools.h"
#include "cmake.h"
+namespace {
+
+enum class CheckingType
+{
+ UNDEFINED,
+ CHECK_START,
+ CHECK_PASS,
+ CHECK_FAIL
+};
+
+std::string IndentText(std::string text, cmMakefile& mf)
+{
+ auto indent =
+ cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), "");
+
+ const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() ||
+ mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW");
+ if (showContext) {
+ auto context = cmJoin(
+ cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), ".");
+ if (!context.empty()) {
+ indent.insert(0u, cmStrCat("["_s, context, "] "_s));
+ }
+ }
+
+ if (!indent.empty()) {
+ cmSystemTools::ReplaceString(text, "\n", "\n" + indent);
+ text.insert(0u, indent);
+ }
+ return text;
+}
+
+void ReportCheckResult(cm::string_view what, std::string result,
+ cmMakefile& mf)
+{
+ if (mf.GetCMakeInstance()->HasCheckInProgress()) {
+ auto text = mf.GetCMakeInstance()->GetTopCheckInProgressMessage() + " - " +
+ std::move(result);
+ mf.DisplayStatus(IndentText(std::move(text), mf), -1);
+ } else {
+ mf.GetMessenger()->DisplayMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("Ignored "_s, what, " without CHECK_START"_s),
+ mf.GetBacktrace());
+ }
+}
+
+} // anonymous namespace
+
// cmLibraryCommand
bool cmMessageCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -21,11 +75,15 @@ bool cmMessageCommand(std::vector<std::string> const& args,
status.SetError("called with incorrect number of arguments");
return false;
}
+
+ auto& mf = status.GetMakefile();
+
auto i = args.cbegin();
auto type = MessageType::MESSAGE;
auto fatal = false;
auto level = cmake::LogLevel::LOG_UNDEFINED;
+ auto checkingType = CheckingType::UNDEFINED;
if (*i == "SEND_ERROR") {
type = MessageType::FATAL_ERROR;
level = cmake::LogLevel::LOG_ERROR;
@@ -40,19 +98,30 @@ bool cmMessageCommand(std::vector<std::string> const& args,
level = cmake::LogLevel::LOG_WARNING;
++i;
} else if (*i == "AUTHOR_WARNING") {
- if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
- !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
+ if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
+ !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
fatal = true;
type = MessageType::AUTHOR_ERROR;
level = cmake::LogLevel::LOG_ERROR;
- } else if (!status.GetMakefile().IsOn(
- "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
+ } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
type = MessageType::AUTHOR_WARNING;
level = cmake::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
+ } else if (*i == "CHECK_START") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_START;
+ ++i;
+ } else if (*i == "CHECK_PASS") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_PASS;
+ ++i;
+ } else if (*i == "CHECK_FAIL") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_FAIL;
+ ++i;
} else if (*i == "STATUS") {
level = cmake::LogLevel::LOG_STATUS;
++i;
@@ -66,12 +135,12 @@ bool cmMessageCommand(std::vector<std::string> const& args,
level = cmake::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
- if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) {
+ if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
fatal = true;
type = MessageType::DEPRECATION_ERROR;
level = cmake::LogLevel::LOG_ERROR;
- } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") ||
- status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) {
+ } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
+ mf.IsOn("CMAKE_WARN_DEPRECATED")) {
type = MessageType::DEPRECATION_WARNING;
level = cmake::LogLevel::LOG_WARNING;
} else {
@@ -89,10 +158,19 @@ bool cmMessageCommand(std::vector<std::string> const& args,
assert("Message log level expected to be set" &&
level != cmake::LogLevel::LOG_UNDEFINED);
- auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel();
+ auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel();
assert("Expected a valid log level here" &&
desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
+ // Command line option takes precedence over the cache variable
+ if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) {
+ const auto desiredLevelFromCache =
+ cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
+ if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) {
+ desiredLevel = desiredLevelFromCache;
+ }
+ }
+
if (desiredLevel < level) {
// Suppress the message
return true;
@@ -100,37 +178,42 @@ bool cmMessageCommand(std::vector<std::string> const& args,
auto message = cmJoin(cmMakeRange(i, args.cend()), "");
- if (cmake::LogLevel::LOG_NOTICE <= level) {
- // Check if any indentation has requested:
- // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces
- // to be joined and prepended to the message lines.
- auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition(
- "CMAKE_MESSAGE_INDENT")),
- "");
- // Make every line of the `message` indented
- // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted`
- // here cuz it appends `\n` to the EOM ;-(
- cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
- message = indent + message;
- }
-
switch (level) {
case cmake::LogLevel::LOG_ERROR:
case cmake::LogLevel::LOG_WARNING:
// we've overridden the message type, above, so display it directly
- status.GetMakefile().GetMessenger()->DisplayMessage(
- type, message, status.GetMakefile().GetBacktrace());
+ mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
break;
case cmake::LogLevel::LOG_NOTICE:
- cmSystemTools::Message(message);
+ cmSystemTools::Message(IndentText(message, mf));
break;
case cmake::LogLevel::LOG_STATUS:
+ switch (checkingType) {
+ case CheckingType::CHECK_START:
+ mf.DisplayStatus(IndentText(message, mf), -1);
+ mf.GetCMakeInstance()->PushCheckInProgressMessage(message);
+ break;
+
+ case CheckingType::CHECK_PASS:
+ ReportCheckResult("CHECK_PASS"_s, message, mf);
+ break;
+
+ case CheckingType::CHECK_FAIL:
+ ReportCheckResult("CHECK_FAIL"_s, message, mf);
+ break;
+
+ default:
+ mf.DisplayStatus(IndentText(message, mf), -1);
+ break;
+ }
+ break;
+
case cmake::LogLevel::LOG_VERBOSE:
case cmake::LogLevel::LOG_DEBUG:
case cmake::LogLevel::LOG_TRACE:
- status.GetMakefile().DisplayStatus(message, -1);
+ mf.DisplayStatus(IndentText(message, mf), -1);
break;
default:
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 7bb5209da0..a25fd42d10 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -39,6 +39,11 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::string const& projectName = args[0];
+ if (!IncludeByVariable(status,
+ "CMAKE_PROJECT_" + projectName + "_INCLUDE_BEFORE")) {
+ return false;
+ }
+
mf.SetProjectName(projectName);
mf.AddCacheDefinition(projectName + "_BINARY_DIR",
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 82a3625b8b..19a0d29136 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -154,9 +154,8 @@ private:
#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
#define CM_SOURCE_REGEX \
- "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|" \
- "hpj" \
- "|bat)$"
+ "\\.(C|F|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \
+ "rc|def|r|odl|idl|hpj|bat)$"
#define CM_PCH_REGEX "cmake_pch\\.(h|hxx)$"
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 3a13e57a42..cc62952d8b 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -78,10 +78,18 @@ std::vector<std::string> prepareFilesPathsForTree(
for (auto const& filePath : filesPaths) {
std::string fullPath =
cmSystemTools::CollapseFullPath(filePath, currentSourceDir);
- // If provided file path is actually not a file, silently ignore it.
- if (cmSystemTools::FileExists(fullPath, /*isFile=*/true)) {
- prepared.emplace_back(std::move(fullPath));
+ // If provided file path is actually not a directory, silently ignore it.
+ if (cmSystemTools::FileIsDirectory(fullPath)) {
+ continue;
}
+
+ // Handle directory that doesn't exist yet.
+ if (!fullPath.empty() &&
+ (fullPath.back() == '/' || fullPath.back() == '\\')) {
+ continue;
+ }
+
+ prepared.emplace_back(std::move(fullPath));
}
return prepared;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 645907c21e..832e74ec7f 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -315,10 +315,14 @@ void cmStateSnapshot::SetDefaultDefinitions()
this->SetDefinition("UNIX", "1");
this->SetDefinition("CMAKE_HOST_UNIX", "1");
+# if defined(__ANDROID__)
+ this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android");
+# else
struct utsname uts_name;
if (uname(&uts_name) >= 0) {
this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname);
}
+# endif
#endif
#if defined(__CYGWIN__)
std::string legacy;
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index a50e8291b1..c4a4220f81 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1120,8 +1120,13 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path,
assert(local_path.front() != '\"');
assert(remote_path.front() != '\"');
- // The local path should never have a trailing slash.
- assert(local_path.empty() || local_path.back() != '/');
+ // The local path should never have a trailing slash except if it is just the
+ // bare root directory
+ assert(local_path.empty() || local_path.back() != '/' ||
+ local_path.size() == 1 ||
+ (local_path.size() == 3 && local_path[1] == ':' &&
+ ((local_path[0] >= 'A' && local_path[0] <= 'Z') ||
+ (local_path[0] >= 'a' && local_path[0] <= 'z'))));
// If the path is already relative then just return the path.
if (!cmSystemTools::FileIsFullPath(remote_path)) {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 99c16f2374..05c9e6ef36 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -380,6 +380,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("XCODE_SCHEME_MALLOC_STACK");
initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
+ initProp("XCODE_SCHEME_ENVIRONMENT");
}
#endif
}
@@ -511,8 +512,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
}
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- this->GetType() != cmStateEnums::UTILITY) {
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
// check for "CMAKE_VS_GLOBALS" variable and set up target properties
// if any
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 4995da972f..35e1c8c56f 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -2,19 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatch.h"
+#include <array>
#include <memory>
#include <utility>
#include <vector>
-static const char* const cmVariableWatchAccessStrings[] = {
- "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS",
- "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS"
-};
-
-const char* cmVariableWatch::GetAccessAsString(int access_type)
+const std::string& cmVariableWatch::GetAccessAsString(int access_type)
{
+ static const std::array<std::string, 6> cmVariableWatchAccessStrings = {
+ { "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS",
+ "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS" }
+ };
if (access_type < 0 || access_type >= cmVariableWatch::NO_ACCESS) {
- return "NO_ACCESS";
+ access_type = cmVariableWatch::NO_ACCESS;
}
return cmVariableWatchAccessStrings[access_type];
}
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index e4b3b7c47f..6c418ed0ab 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -46,7 +46,7 @@ public:
*/
enum
{
- VARIABLE_READ_ACCESS = 0,
+ VARIABLE_READ_ACCESS,
UNKNOWN_VARIABLE_READ_ACCESS,
UNKNOWN_VARIABLE_DEFINED_ACCESS,
VARIABLE_MODIFIED_ACCESS,
@@ -57,7 +57,7 @@ public:
/**
* Return the access as string
*/
- static const char* GetAccessAsString(int access_type);
+ static const std::string& GetAccessAsString(int access_type);
protected:
struct Pair
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index f2c8f3cdb9..039f1ba6ba 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatchCommand.h"
+#include <limits>
#include <memory>
#include <utility>
@@ -14,17 +15,17 @@
#include "cmVariableWatch.h"
#include "cmake.h"
+namespace {
struct cmVariableWatchCallbackData
{
bool InCallback;
std::string Command;
};
-static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
- int access_type,
- void* client_data,
- const char* newValue,
- const cmMakefile* mf)
+void cmVariableWatchCommandVariableAccessed(const std::string& variable,
+ int access_type, void* client_data,
+ const char* newValue,
+ const cmMakefile* mf)
{
cmVariableWatchCallbackData* data =
static_cast<cmVariableWatchCallbackData*>(client_data);
@@ -34,40 +35,35 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
}
data->InCallback = true;
- cmListFileFunction newLFF;
- cmListFileArgument arg;
- bool processed = false;
- const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
- const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
+ auto accessString = cmVariableWatch::GetAccessAsString(access_type);
/// Ultra bad!!
cmMakefile* makefile = const_cast<cmMakefile*>(mf);
std::string stack = makefile->GetProperty("LISTFILE_STACK");
if (!data->Command.empty()) {
- newLFF.Arguments.clear();
- newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999);
- newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted,
- 9999);
- newLFF.Arguments.emplace_back(newValue ? newValue : "",
- cmListFileArgument::Quoted, 9999);
- newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted,
- 9999);
- newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
+ cmListFileFunction newLFF;
+ const char* const currentListFile =
+ mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
+ const auto fakeLineNo =
+ std::numeric_limits<decltype(cmListFileArgument::Line)>::max();
+ newLFF.Arguments = {
+ { variable, cmListFileArgument::Quoted, fakeLineNo },
+ { accessString, cmListFileArgument::Quoted, fakeLineNo },
+ { newValue ? newValue : "", cmListFileArgument::Quoted, fakeLineNo },
+ { currentListFile, cmListFileArgument::Quoted, fakeLineNo },
+ { stack, cmListFileArgument::Quoted, fakeLineNo }
+ };
newLFF.Name = data->Command;
- newLFF.Line = 9999;
+ newLFF.Line = fakeLineNo;
cmExecutionStatus status(*makefile);
if (!makefile->ExecuteCommand(newLFF, status)) {
cmSystemTools::Error(
cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed "
"during the invocation of callback \"",
data->Command, "\"."));
- data->InCallback = false;
- return;
}
- processed = true;
- }
- if (!processed) {
+ } else {
makefile->IssueMessage(
MessageType::LOG,
cmStrCat("Variable \"", variable, "\" was accessed using ", accessString,
@@ -77,7 +73,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
data->InCallback = false;
}
-static void deleteVariableWatchCallbackData(void* client_data)
+void deleteVariableWatchCallbackData(void* client_data)
{
cmVariableWatchCallbackData* data =
static_cast<cmVariableWatchCallbackData*>(client_data);
@@ -91,7 +87,7 @@ class FinalAction
public:
/* NOLINTNEXTLINE(performance-unnecessary-value-param) */
FinalAction(cmMakefile* makefile, std::string variable)
- : Action(std::make_shared<Impl>(makefile, std::move(variable)))
+ : Action{ std::make_shared<Impl>(makefile, std::move(variable)) }
{
}
@@ -101,8 +97,8 @@ private:
struct Impl
{
Impl(cmMakefile* makefile, std::string variable)
- : Makefile(makefile)
- , Variable(std::move(variable))
+ : Makefile{ makefile }
+ , Variable{ std::move(variable) }
{
}
@@ -112,12 +108,13 @@ private:
this->Variable, cmVariableWatchCommandVariableAccessed);
}
- cmMakefile* Makefile;
- std::string Variable;
+ cmMakefile* const Makefile;
+ std::string const Variable;
};
std::shared_ptr<Impl const> Action;
};
+} // anonymous namespace
bool cmVariableWatchCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -136,10 +133,10 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args,
return false;
}
- cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
+ auto* const data = new cmVariableWatchCallbackData;
data->InCallback = false;
- data->Command = command;
+ data->Command = std::move(command);
if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch(
variable, cmVariableWatchCommandVariableAccessed, data,
@@ -149,6 +146,6 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args,
}
status.GetMakefile().AddFinalAction(
- FinalAction(&status.GetMakefile(), variable));
+ FinalAction{ &status.GetMakefile(), variable });
return true;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 3843bf24c4..dac86a182b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -543,6 +543,11 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
}
+ if (const char* vcTargetsPath =
+ this->GlobalGenerator->GetCustomVCTargetsPath()) {
+ e1.Element("VCTargetsPath", vcTargetsPath);
+ }
+
std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
for (std::string const& keyIt : keys) {
static const char* prefix = "VS_GLOBAL_";
@@ -676,6 +681,8 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WritePlatformExtensions(e1);
}
+
+ this->WriteDotNetDocumentationFile(e0);
Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
this->WriteWinRTPackageCertificateKeyFile(e0);
this->WritePathAndIncrementalLinkOptions(e0);
@@ -910,6 +917,18 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
}
}
+void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0)
+{
+ std::string const documentationFile =
+ this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE");
+
+ if (this->ProjectType == csproj && !documentationFile.empty()) {
+ Elem e1(e0, "PropertyGroup");
+ Elem e2(e1, "DocumentationFile");
+ e2.Content(documentationFile);
+ }
+}
+
void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
{
std::vector<cmSourceFile const*> resxObjs;
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index a18a33dd89..0835cde9f7 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -79,6 +79,7 @@ private:
void WriteDotNetReference(Elem& e1, std::string const& ref,
std::string const& hint,
std::string const& config);
+ void WriteDotNetDocumentationFile(Elem& e0);
void WriteImports(Elem& e0);
void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref);
void WriteEmbeddedResourceGroup(Elem& e0);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index f63a264006..4a6108d9ee 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -735,6 +735,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
return;
}
this->SetLogLevel(logLevel);
+ this->LogLevelWasSetViaCLI = true;
} else if (arg.find("--loglevel=", 0) == 0) {
// This is supported for backward compatibility. This option only
// appeared in the 3.15.x release series and was renamed to
@@ -746,6 +747,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
return;
}
this->SetLogLevel(logLevel);
+ this->LogLevelWasSetViaCLI = true;
+ } else if (arg == "--log-context") {
+ this->SetShowLogContext(true);
} else if (arg.find("--trace-expand", 0) == 0) {
std::cout << "Running with expanded trace output on.\n";
this->SetTrace(true);
@@ -2287,7 +2291,7 @@ void cmake::MarkCliAsUsed(const std::string& variable)
void cmake::GenerateGraphViz(const std::string& fileName) const
{
#ifndef CMAKE_BOOTSTRAP
- cmGraphVizWriter gvWriter(this->GetGlobalGenerator());
+ cmGraphVizWriter gvWriter(fileName, this->GetGlobalGenerator());
std::string settingsFile =
cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake");
@@ -2295,9 +2299,8 @@ void cmake::GenerateGraphViz(const std::string& fileName) const
cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake");
gvWriter.ReadSettings(settingsFile, fallbackSettingsFile);
- gvWriter.WritePerTargetFiles(fileName);
- gvWriter.WriteTargetDependersFiles(fileName);
- gvWriter.WriteGlobalFile(fileName);
+
+ gvWriter.Write();
#endif
}
@@ -2616,6 +2619,14 @@ int cmake::Build(int jobs, const std::string& dir,
return 1;
}
}
+ const char* cachedGeneratorToolset =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
+ if (cachedGeneratorToolset) {
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
+ if (!gen->SetGeneratorToolset(cachedGeneratorToolset, true, &mf)) {
+ return 1;
+ }
+ }
std::string output;
std::string projName;
const char* cachedProjectName =
diff --git a/Source/cmake.h b/Source/cmake.h
index 687c1056b1..9e78436ff7 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -5,12 +5,15 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <set>
+#include <stack>
#include <string>
#include <unordered_set>
+#include <utility>
#include <vector>
#include "cmGeneratedFileStream.h"
@@ -380,15 +383,40 @@ public:
*/
cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); }
+ bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; }
+
//! Get the selected log level for `message()` commands during the cmake run.
LogLevel GetLogLevel() const { return this->MessageLogLevel; }
void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
static LogLevel StringToLogLevel(const std::string& levelStr);
+ bool HasCheckInProgress() const
+ {
+ return !this->CheckInProgressMessages.empty();
+ }
+ std::size_t GetCheckInProgressSize() const
+ {
+ return this->CheckInProgressMessages.size();
+ }
+ std::string GetTopCheckInProgressMessage()
+ {
+ auto message = this->CheckInProgressMessages.top();
+ this->CheckInProgressMessages.pop();
+ return message;
+ }
+ void PushCheckInProgressMessage(std::string message)
+ {
+ this->CheckInProgressMessages.emplace(std::move(message));
+ }
+
//! Do we want debug output during the cmake run.
bool GetDebugOutput() { return this->DebugOutput; }
void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
+ //! Should `message` command display context.
+ bool GetShowLogContext() const { return this->LogContext; }
+ void SetShowLogContext(bool b) { this->LogContext = b; }
+
//! Do we want trace output during the cmake run.
bool GetTrace() { return this->Trace; }
void SetTrace(bool b) { this->Trace = b; }
@@ -587,6 +615,10 @@ private:
std::vector<std::string> TraceOnlyThisSources;
LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
+ bool LogLevelWasSetViaCLI = false;
+ bool LogContext = false;
+
+ std::stack<std::string> CheckInProgressMessages;
void UpdateConversionPathTable();
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 6d3e6ee300..baf975ecb2 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -73,6 +73,7 @@ const char* cmDocumentationOptions[][2] = {
{ "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>",
"Set the verbosity of messages from CMake files. "
"--loglevel is also accepted for backward compatibility reasons." },
+ { "--log-context", "Prepend log messages with context, if given" },
{ "--debug-trycompile",
"Do not delete the try_compile build tree. Only "
"useful on one try_compile at a time." },
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 91ee598b25..a7b11cd944 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -99,11 +99,14 @@ static const char* cmDocumentationOptions[][2] = {
{ "-U, --union", "Take the Union of -I and -R" },
{ "--rerun-failed", "Run only the tests that failed previously" },
{ "--repeat-until-fail <n>",
- "Require each test to run <n> "
- "times without failing in order to pass" },
+ "Require each test to run <n> times without failing in order to pass" },
+ { "--repeat-until-pass <n>",
+ "Allow each test to run up to <n> times in order to pass" },
+ { "--repeat-after-timeout <n>",
+ "Allow each test to run up to <n> times if it times out" },
{ "--max-width <width>", "Set the max width for a test name to output" },
{ "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." },
- { "--hardware-spec-file <file>", "Set the hardware spec file to use." },
+ { "--resource-spec-file <file>", "Set the resource spec file to use." },
{ "--no-label-summary", "Disable timing summary information for labels." },
{ "--no-subproject-summary",
"Disable timing summary information for "
diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in
index b06752115c..75a2d4d0f9 100644
--- a/Source/kwsys/Encoding.hxx.in
+++ b/Source/kwsys/Encoding.hxx.in
@@ -68,6 +68,8 @@ public:
* absolute paths with Windows-style backslashes.
**/
static std::wstring ToWindowsExtendedPath(std::string const&);
+ static std::wstring ToWindowsExtendedPath(const char* source);
+ static std::wstring ToWindowsExtendedPath(std::wstring const& wsource);
# endif
#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index 4593c9251c..5cad934ec3 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -221,8 +221,18 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr)
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
- std::wstring wsource = Encoding::ToWide(source);
+ return ToWindowsExtendedPath(ToWide(source));
+}
+// Convert local paths to UNC style paths
+std::wstring Encoding::ToWindowsExtendedPath(const char* source)
+{
+ return ToWindowsExtendedPath(ToWide(source));
+}
+
+// Convert local paths to UNC style paths
+std::wstring Encoding::ToWindowsExtendedPath(std::wstring const& wsource)
+{
// Resolve any relative paths
DWORD wfull_len;
@@ -269,7 +279,7 @@ std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
// If this case has been reached, then the path is invalid. Leave it
// unchanged
- return Encoding::ToWide(source);
+ return wsource;
}
# endif
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index df7eb45589..0c2366b842 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -70,10 +70,10 @@ private:
* \brief Creates an invalid match object
*/
inline RegularExpressionMatch::RegularExpressionMatch()
+ : startp{}
+ , endp{}
+ , searchstring{}
{
- startp[0] = nullptr;
- endp[0] = nullptr;
- searchstring = nullptr;
}
/**