summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/add_custom_command.rst10
-rw-r--r--Help/command/string.rst2
-rw-r--r--Help/prop_test/PROCESSORS.rst9
-rw-r--r--Help/release/dev/timestamp.rst5
-rw-r--r--Modules/CMakeFindDependencyMacro.cmake45
-rw-r--r--Modules/FindMatlab.cmake9
-rw-r--r--Modules/FindOpenSSL.cmake2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx137
-rw-r--r--Source/CTest/cmCTestTestHandler.h3
-rw-r--r--Source/cmCustomCommandGenerator.cxx14
-rw-r--r--Source/cmCustomCommandGenerator.h1
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx10
-rw-r--r--Source/cmTimestamp.cxx2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx12
-rw-r--r--Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt4
-rw-r--r--Tests/RunCMake/add_custom_command/RemoveEmptyCommands-check.cmake63
-rw-r--r--Tests/RunCMake/add_custom_command/RemoveEmptyCommands.cmake22
-rw-r--r--Tests/RunCMake/add_custom_command/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/CTestConfigCTestScript-stdout.txt7
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariable-stdout.txt7
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stdout.txt5
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCMakeLists-stdout.txt2
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfig-stdout.txt5
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfigNoSummary-stdout.txt3
-rw-r--r--Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCommandLine-stdout.txt2
-rw-r--r--Tests/RunCMake/string/Timestamp-stderr.txt2
-rw-r--r--Tests/RunCMake/string/Timestamp.cmake2
28 files changed, 247 insertions, 144 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index d038406..1b0aa14 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -225,3 +225,13 @@ of the following is specified:
:command:`add_custom_target` command.
``POST_BUILD``
Run after all other rules within the target have been executed.
+
+.. note::
+ Because generator expressions can be used in custom commands,
+ it is possible to define ``COMMAND`` lines or whole custom commands
+ which evaluate to empty strings for certain configurations.
+ For **Visual Studio 2010 (and newer)** generators these command
+ lines or custom commands will be omitted for the specific
+ configuration and no "empty-string-command" will be added.
+
+ This allows to add individual build events for every configuration.
diff --git a/Help/command/string.rst b/Help/command/string.rst
index ba4a412..fb3893f 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -324,6 +324,7 @@ specifiers:
%j The day of the current year (001-366).
%m The month of the current year (01-12).
%b Abbreviated month name (e.g. Oct).
+ %B Full month name (e.g. October).
%M The minute of the current hour (00-59).
%s Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).
%S The second of the current minute.
@@ -331,6 +332,7 @@ specifiers:
%U The week number of the current year (00-53).
%w The day of the current week. 0 is Sunday. (0-6)
%a Abbreviated weekday name (e.g. Fri).
+ %A Full weekday name (e.g. Friday).
%y The last two digits of the current year (00-99)
%Y The current year.
diff --git a/Help/prop_test/PROCESSORS.rst b/Help/prop_test/PROCESSORS.rst
index 763b6d0..a1211fb 100644
--- a/Help/prop_test/PROCESSORS.rst
+++ b/Help/prop_test/PROCESSORS.rst
@@ -1,8 +1,13 @@
PROCESSORS
----------
-How many process slots this test requires
+Set to specify how many process slots this test requires.
Denotes the number of processors that this test will require. This is
typically used for MPI tests, and should be used in conjunction with
-the ctest_test PARALLEL_LEVEL option.
+the :command:`ctest_test` ``PARALLEL_LEVEL`` option.
+
+This will also be used to display a weighted test timing result in label and
+subproject summaries in the command line output of :manual:`ctest(1)`. The wall
+clock time for the test run will be multiplied by this property to give a
+better idea of how much cpu resource CTest allocated for the test.
diff --git a/Help/release/dev/timestamp.rst b/Help/release/dev/timestamp.rst
new file mode 100644
index 0000000..e40009e
--- /dev/null
+++ b/Help/release/dev/timestamp.rst
@@ -0,0 +1,5 @@
+timestamp
+---------
+
+* The :command:`string(TIMESTAMP)` command now supports ``%A``
+ for full weekday name and ``%B`` for full month name.
diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake
index 81606ce..6a89fff 100644
--- a/Modules/CMakeFindDependencyMacro.cmake
+++ b/Modules/CMakeFindDependencyMacro.cmake
@@ -1,23 +1,34 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CMakeFindDependencyMacro
-# -------------------------
-#
-# ::
-#
-# find_dependency(<dep> [...])
-#
-#
-# ``find_dependency()`` wraps a :command:`find_package` call for a package
-# dependency. It is designed to be used in a <package>Config.cmake file, and it
-# forwards the correct parameters for QUIET and REQUIRED which were passed to
-# the original :command:`find_package` call. It also sets an informative
-# diagnostic message if the dependency could not be found.
-#
-# Any additional arguments specified are forwarded to :command:`find_package`.
-#
+#[=======================================================================[.rst:
+CMakeFindDependencyMacro
+-------------------------
+
+.. command:: find_dependency
+
+ The ``find_dependency()`` macro wraps a :command:`find_package` call for
+ a package dependency::
+
+ find_dependency(<dep> [...])
+
+ It is designed to be used in a
+ :ref:`Package Configuration File <Config File Packages>`
+ (``<package>Config.cmake``). ``find_dependency`` forwards the correct
+ parameters for ``QUIET`` and ``REQUIRED`` which were passed to
+ the original :command:`find_package` call. Any additional arguments
+ specified are forwarded to :command:`find_package`.
+
+ If the dependency could not be found it sets an informative diagnostic
+ message and calls :command:`return` to end processing of the calling
+ package configuration file and return to the :command:`find_package`
+ command that loaded it.
+
+ .. note::
+
+ The call to :command:`return` makes this macro unsuitable to call
+ from :ref:`Find Modules`.
+#]=======================================================================]
macro(find_dependency dep)
if (NOT ${dep}_FOUND)
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index cd8246d..7493281 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -1134,7 +1134,14 @@ else()
# testing if we are able to extract the needed information from the registry
set(_matlab_versions_from_registry)
- matlab_extract_all_installed_versions_from_registry(CMAKE_CL_64 _matlab_versions_from_registry)
+
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_matlab_win64 ON)
+ else()
+ set(_matlab_win64 OFF)
+ endif()
+
+ matlab_extract_all_installed_versions_from_registry(_matlab_win64 _matlab_versions_from_registry)
# the returned list is empty, doing the search on all known versions
if(NOT _matlab_versions_from_registry)
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index f32eb50..0187e0d 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -149,6 +149,7 @@ if(WIN32 AND NOT CYGWIN)
libcryptod
libeay32${_OPENSSL_MSVC_RT_MODE}d
libeay32d
+ cryptod
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
@@ -176,6 +177,7 @@ if(WIN32 AND NOT CYGWIN)
libssld
ssleay32${_OPENSSL_MSVC_RT_MODE}d
ssleay32d
+ ssld
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 04380a0..0dd1651 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 9)
-set(CMake_VERSION_PATCH 20170909)
+set(CMake_VERSION_PATCH 20170912)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 18d9346..9962c49 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -535,14 +535,13 @@ int cmCTestTestHandler::ProcessHandler()
<< static_cast<int>(percent + .5f) << "% tests passed, "
<< failed.size() << " tests failed out of " << total
<< std::endl);
-
- if (!this->CTest->GetLabelsForSubprojects().empty() &&
- this->CTest->GetSubprojectSummary()) {
- this->PrintSubprojectSummary();
- } else if (this->CTest->GetLabelSummary()) {
- this->PrintLabelSummary();
+ if ((!this->CTest->GetLabelsForSubprojects().empty() &&
+ this->CTest->GetSubprojectSummary())) {
+ this->PrintLabelOrSubprojectSummary(true);
+ }
+ if (this->CTest->GetLabelSummary()) {
+ this->PrintLabelOrSubprojectSummary(false);
}
-
char realBuf[1024];
sprintf(realBuf, "%6.2f sec", clock_finish - clock_start);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
@@ -620,96 +619,32 @@ int cmCTestTestHandler::ProcessHandler()
return 0;
}
-void cmCTestTestHandler::PrintLabelSummary()
-{
- cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
- std::map<std::string, double> labelTimes;
- std::map<std::string, int> labelCounts;
- std::set<std::string> labels;
- // initialize maps
- std::string::size_type maxlen = 0;
- for (; it != this->TestList.end(); ++it) {
- cmCTestTestProperties& p = *it;
- if (!p.Labels.empty()) {
- for (std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l) {
- if ((*l).size() > maxlen) {
- maxlen = (*l).size();
- }
- labels.insert(*l);
- labelTimes[*l] = 0;
- labelCounts[*l] = 0;
- }
- }
- }
- cmCTestTestHandler::TestResultsVector::iterator ri =
- this->TestResults.begin();
- // fill maps
- for (; ri != this->TestResults.end(); ++ri) {
- cmCTestTestResult& result = *ri;
- cmCTestTestProperties& p = *result.Properties;
- if (!p.Labels.empty()) {
- for (std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l) {
- labelTimes[*l] += result.ExecutionTime;
- ++labelCounts[*l];
- }
- }
- }
- // now print times
- if (!labels.empty()) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:",
- this->Quiet);
- }
- for (std::set<std::string>::const_iterator i = labels.begin();
- i != labels.end(); ++i) {
- std::string label = *i;
- label.resize(maxlen + 3, ' ');
-
- char buf[1024];
- sprintf(buf, "%6.2f sec", labelTimes[*i]);
-
- std::ostringstream labelCountStr;
- labelCountStr << "(" << labelCounts[*i] << " test";
- if (labelCounts[*i] > 1) {
- labelCountStr << "s";
- }
- labelCountStr << ")";
-
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
- << label << " = " << buf << " "
- << labelCountStr.str(),
- this->Quiet);
- if (this->LogFile) {
- *this->LogFile << "\n" << *i << " = " << buf << "\n";
- }
- }
- if (!labels.empty()) {
- if (this->LogFile) {
- *this->LogFile << "\n";
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
- }
-}
-
-void cmCTestTestHandler::PrintSubprojectSummary()
+void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
{
+ // collect subproject labels
std::vector<std::string> subprojects =
this->CTest->GetLabelsForSubprojects();
-
- cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
std::map<std::string, double> labelTimes;
std::map<std::string, int> labelCounts;
std::set<std::string> labels;
- // initialize maps
std::string::size_type maxlen = 0;
- for (; it != this->TestList.end(); ++it) {
+ // initialize maps
+ for (cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
+ it != this->TestList.end(); ++it) {
cmCTestTestProperties& p = *it;
for (std::vector<std::string>::iterator l = p.Labels.begin();
l != p.Labels.end(); ++l) {
+ // first check to see if the current label is a subproject label
+ bool isSubprojectLabel = false;
std::vector<std::string>::iterator subproject =
std::find(subprojects.begin(), subprojects.end(), *l);
if (subproject != subprojects.end()) {
+ isSubprojectLabel = true;
+ }
+ // if we are doing sub projects and this label is one, then use it
+ // if we are not doing sub projects and the label is not one use it
+ if ((doSubProject && isSubprojectLabel) ||
+ (!doSubProject && !isSubprojectLabel)) {
if ((*l).size() > maxlen) {
maxlen = (*l).size();
}
@@ -719,26 +654,32 @@ void cmCTestTestHandler::PrintSubprojectSummary()
}
}
}
- cmCTestTestHandler::TestResultsVector::iterator ri =
- this->TestResults.begin();
// fill maps
- for (; ri != this->TestResults.end(); ++ri) {
+ for (cmCTestTestHandler::TestResultsVector::iterator ri =
+ this->TestResults.begin();
+ ri != this->TestResults.end(); ++ri) {
cmCTestTestResult& result = *ri;
cmCTestTestProperties& p = *result.Properties;
for (std::vector<std::string>::iterator l = p.Labels.begin();
l != p.Labels.end(); ++l) {
- std::vector<std::string>::iterator subproject =
- std::find(subprojects.begin(), subprojects.end(), *l);
- if (subproject != subprojects.end()) {
- labelTimes[*l] += result.ExecutionTime;
+ // only use labels found in labels
+ if (labels.find(*l) != labels.end()) {
+ labelTimes[*l] += result.ExecutionTime * result.Properties->Processors;
++labelCounts[*l];
}
}
}
+ // if no labels are found return and print nothing
+ if (labels.empty()) {
+ return;
+ }
// now print times
- if (!labels.empty()) {
+ if (doSubProject) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"\nSubproject Time Summary:", this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:",
+ this->Quiet);
}
for (std::set<std::string>::const_iterator i = labels.begin();
i != labels.end(); ++i) {
@@ -746,7 +687,7 @@ void cmCTestTestHandler::PrintSubprojectSummary()
label.resize(maxlen + 3, ' ');
char buf[1024];
- sprintf(buf, "%6.2f sec", labelTimes[*i]);
+ sprintf(buf, "%6.2f sec*proc", labelTimes[*i]);
std::ostringstream labelCountStr;
labelCountStr << "(" << labelCounts[*i] << " test";
@@ -754,7 +695,6 @@ void cmCTestTestHandler::PrintSubprojectSummary()
labelCountStr << "s";
}
labelCountStr << ")";
-
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
<< label << " = " << buf << " "
<< labelCountStr.str(),
@@ -763,13 +703,12 @@ void cmCTestTestHandler::PrintSubprojectSummary()
*this->LogFile << "\n" << *i << " = " << buf << "\n";
}
}
- if (!labels.empty()) {
- if (this->LogFile) {
- *this->LogFile << "\n";
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
+ if (this->LogFile) {
+ *this->LogFile << "\n";
}
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
}
+
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
{
// if not using Labels to filter then return
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 965552c..4c5b55f 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -232,8 +232,7 @@ private:
*/
virtual void GenerateDartOutput(cmXMLWriter& xml);
- void PrintLabelSummary();
- void PrintSubprojectSummary();
+ void PrintLabelOrSubprojectSummary(bool isSubProject);
/**
* Run the tests for a directory and any subdirectories
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index fdc0a97..fa1c70e 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -13,6 +13,8 @@
#include "cmSystemTools.h"
#include "cm_auto_ptr.hxx"
+#include <stddef.h>
+
cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
const std::string& config,
cmLocalGenerator* lg)
@@ -97,6 +99,18 @@ const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
return nullptr;
}
+bool cmCustomCommandGenerator::HasOnlyEmptyCommandLines() const
+{
+ for (size_t i = 0; i < this->CommandLines.size(); ++i) {
+ for (size_t j = 0; j < this->CommandLines[i].size(); ++j) {
+ if (!this->CommandLines[i][j].empty()) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
if (const char* emulator = this->GetCrossCompilingEmulator(c)) {
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index ea33b51..34fd653 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -40,6 +40,7 @@ public:
std::vector<std::string> const& GetOutputs() const;
std::vector<std::string> const& GetByproducts() const;
std::vector<std::string> const& GetDepends() const;
+ bool HasOnlyEmptyCommandLines() const;
};
#endif
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 41025af..d772d95 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -191,13 +191,17 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
// Write each command on a single line.
for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
+ // Add this command line.
+ std::string cmd = ccg.GetCommand(c);
+
+ if (cmd.empty()) {
+ continue;
+ }
+
// Start a new line.
script += newline;
newline = newline_text;
- // Add this command line.
- std::string cmd = ccg.GetCommand(c);
-
// Use "call " before any invocations of .bat or .cmd files
// invoked as custom commands.
//
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 4dea24c..9fb79d9 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -123,7 +123,9 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
switch (flag) {
case 'a':
+ case 'A':
case 'b':
+ case 'B':
case 'd':
case 'H':
case 'I':
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 7fe2f2a..bd3e82d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3536,11 +3536,13 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
i != commands.end(); ++i) {
cmCustomCommandGenerator ccg(*i, configName, this->LocalGenerator);
- comment += pre;
- comment += lg->ConstructComment(ccg);
- script += pre;
- pre = "\n";
- script += cmVS10EscapeXML(lg->ConstructScript(ccg));
+ if (!ccg.HasOnlyEmptyCommandLines()) {
+ comment += pre;
+ comment += lg->ConstructComment(ccg);
+ script += pre;
+ pre = "\n";
+ script += cmVS10EscapeXML(lg->ConstructScript(ccg));
+ }
}
comment = cmVS10EscapeComment(comment);
if (this->ProjectType != csproj) {
diff --git a/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
index 7fe04eb..9cfe41c 100644
--- a/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/LabelCount-stdout.txt
@@ -1,7 +1,7 @@
100% tests passed, 0 tests failed out of 4
+
+Label Time Summary:
-+'bar' = +[0-9.]+ sec \(3 tests\)
-+'foo' = +[0-9.]+ sec \(1 test\)
++'bar' = +[0-9.]+ sec\*proc \(3 tests\)
++'foo' = +[0-9.]+ sec\*proc \(1 test\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/add_custom_command/RemoveEmptyCommands-check.cmake b/Tests/RunCMake/add_custom_command/RemoveEmptyCommands-check.cmake
new file mode 100644
index 0000000..b297044
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/RemoveEmptyCommands-check.cmake
@@ -0,0 +1,63 @@
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/exe.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(inGroup FALSE)
+set(inCommand FALSE)
+
+set(expected_Debug
+ "cmd_1 cmd_1_arg"
+ "cmd_1_dbg cmd_1_dbg_arg"
+ "cmd_2_dbg cmd_2_dbg_arg"
+ "cmd_3_dbg cmd_3_dbg_arg")
+
+set(expected_Release
+ "cmd_1 cmd_1_arg"
+ "cmd_3_rel cmd_3_rel_arg")
+
+# extract build events
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<ItemDefinitionGroup Condition=.*Configuration.*Platform.*>$")
+ set(inGroup TRUE)
+ string(REGEX MATCH "=='(.*)\\|(.*)'" out ${line})
+ set(config ${CMAKE_MATCH_1})
+ elseif(line MATCHES "^ *</ItemDefinitionGroup>$")
+ set(inGroup FALSE)
+ elseif(inGroup)
+ if(line MATCHES "^ *<Command>.*$")
+ set(inCommand TRUE)
+ string(REGEX MATCH "<Command>(.*)" cmd ${line})
+ set(currentCommand ${CMAKE_MATCH_1})
+ elseif(line MATCHES "^(.*)</Command>$")
+ string(REGEX MATCH "(.*)</Command>" cmd ${line})
+ list(APPEND currentCommand ${CMAKE_MATCH_1})
+ set(command_${config} ${currentCommand})
+ set(inCommand FALSE)
+ elseif(inCommand)
+ list(APPEND currentCommand ${line})
+ endif()
+ endif()
+endforeach()
+
+foreach(config "Debug" "Release")
+ set(currentName command_${config})
+ set(expectedName expected_${config})
+ set(strippedCommand "")
+ if(DEFINED ${currentName})
+ foreach(v ${${currentName}})
+ if(${v} MATCHES "cmd_")
+ list(APPEND strippedCommand ${v})
+ endif()
+ endforeach()
+ if(NOT "${strippedCommand}" STREQUAL
+ "${${expectedName}}")
+ message(" - ${strippedCommand}")
+ message(" + ${${expectedName}}")
+ set(RunCMake_TEST_FAILED "build event command does not match")
+ return()
+ endif()
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/add_custom_command/RemoveEmptyCommands.cmake b/Tests/RunCMake/add_custom_command/RemoveEmptyCommands.cmake
new file mode 100644
index 0000000..eb190cc
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/RemoveEmptyCommands.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+
+# reduce number of configuration types
+set(CMAKE_CONFIGURATION_TYPES "Debug" "Release")
+
+set(main_file "${CMAKE_BINARY_DIR}/main.cpp")
+file(WRITE "${main_file}" "test")
+add_executable(exe "${main_file}")
+
+# add one command for all and one for debug only
+add_custom_command(TARGET exe
+ COMMAND "cmd_1" "cmd_1_arg"
+ COMMAND $<$<CONFIG:Debug>:cmd_1_dbg> $<$<CONFIG:Debug>:cmd_1_dbg_arg>)
+
+# add command for debug only
+add_custom_command(TARGET exe
+ COMMAND $<$<CONFIG:Debug>:cmd_2_dbg> $<$<CONFIG:Debug>:cmd_2_dbg_arg>)
+
+# add separate commands for configurations
+add_custom_command(TARGET exe
+ COMMAND $<$<CONFIG:Debug>:cmd_3_dbg> $<$<CONFIG:Debug>:cmd_3_dbg_arg>
+ COMMAND $<$<CONFIG:Release>:cmd_3_rel> $<$<CONFIG:Release>:cmd_3_rel_arg>)
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 397c63d..c12e5aa 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -10,3 +10,7 @@ run_cmake(SourceByproducts)
run_cmake(SourceUsesTerminal)
run_cmake(TargetImported)
run_cmake(TargetNotInDir)
+
+if(${RunCMake_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
+ run_cmake(RemoveEmptyCommands)
+endif()
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/CTestConfigCTestScript-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/CTestConfigCTestScript-stdout.txt
index ae00e51..05b484d 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/CTestConfigCTestScript-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/CTestConfigCTestScript-stdout.txt
@@ -1,7 +1,10 @@
17% tests passed, 5 tests failed out of 6
+
Subproject Time Summary:
-MyExperimentalFeature += +[0-9.]+ sec \(5 tests\)
-MyProductionCode += +[0-9.]+ sec \(1 test\)
+MyExperimentalFeature += +[0-9.]+ sec\*proc \(5 tests\)
+MyProductionCode += +[0-9.]+ sec\*proc \(1 test\)
++
+Label Time Summary:
+NotASubproject += +[0-9.]+ sec\*proc \(6 tests\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariable-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariable-stdout.txt
index ae00e51..05b484d 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariable-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariable-stdout.txt
@@ -1,7 +1,10 @@
17% tests passed, 5 tests failed out of 6
+
Subproject Time Summary:
-MyExperimentalFeature += +[0-9.]+ sec \(5 tests\)
-MyProductionCode += +[0-9.]+ sec \(1 test\)
+MyExperimentalFeature += +[0-9.]+ sec\*proc \(5 tests\)
+MyProductionCode += +[0-9.]+ sec\*proc \(1 test\)
++
+Label Time Summary:
+NotASubproject += +[0-9.]+ sec\*proc \(6 tests\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stdout.txt
index a78a99a..c2c1bc7 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stdout.txt
@@ -1,6 +1,9 @@
0% tests passed, 1 tests failed out of 1
+
Subproject Time Summary:
-MyThirdPartyDependency += +[0-9.]+ sec \(1 test\)
+MyThirdPartyDependency += +[0-9.]+ sec\*proc \(1 test\)
++
+Label Time Summary:
+NotASubproject += +[0-9.]+ sec\*proc \(1 test\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCMakeLists-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCMakeLists-stdout.txt
index b5d76a9..3567a92 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCMakeLists-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCMakeLists-stdout.txt
@@ -1,6 +1,6 @@
50% tests passed, 1 tests failed out of 2
+
Subproject Time Summary:
-MySubproject += +[0-9.]+ sec \(2 tests\)
+MySubproject += +[0-9.]+ sec\*proc \(2 tests\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfig-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfig-stdout.txt
index 01851fd..3a71022 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfig-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfig-stdout.txt
@@ -1,6 +1,9 @@
67% tests passed, 1 tests failed out of 3
+
Subproject Time Summary:
-MySubproject += +[0-9.]+ sec \(2 tests\)
+MySubproject += +[0-9.]+ sec\*proc \(2 tests\)
++
+Label Time Summary:
+NotASubproject += +[0-9.]+ sec\*proc \(1 test\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfigNoSummary-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfigNoSummary-stdout.txt
index 0209bfe..1146bfe 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfigNoSummary-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCTestConfigNoSummary-stdout.txt
@@ -1,7 +1,6 @@
67% tests passed, 1 tests failed out of 3
+
Label Time Summary:
-MySubproject += +[0-9.]+ sec \(2 tests\)
-NotASubproject += +[0-9.]+ sec \(1 test\)
+NotASubproject += +[0-9.]+ sec\*proc \(1 test\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCommandLine-stdout.txt b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCommandLine-stdout.txt
index b5d76a9..3567a92 100644
--- a/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCommandLine-stdout.txt
+++ b/Tests/RunCMake/ctest_labels_for_subprojects/ModuleVariableCommandLine-stdout.txt
@@ -1,6 +1,6 @@
50% tests passed, 1 tests failed out of 2
+
Subproject Time Summary:
-MySubproject += +[0-9.]+ sec \(2 tests\)
+MySubproject += +[0-9.]+ sec\*proc \(2 tests\)
+
Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/string/Timestamp-stderr.txt b/Tests/RunCMake/string/Timestamp-stderr.txt
index 653974c..cd4dcb3 100644
--- a/Tests/RunCMake/string/Timestamp-stderr.txt
+++ b/Tests/RunCMake/string/Timestamp-stderr.txt
@@ -1 +1 @@
-RESULT=2005-08-07 23:19:49 Sun Aug 05 day=219 wd=0 week=32 %I=11 epoch=1123456789
+RESULT=2005-08-07 23:19:49 Sunday=Sun August=Aug 05 day=219 wd=0 week=32 %I=11 epoch=1123456789
diff --git a/Tests/RunCMake/string/Timestamp.cmake b/Tests/RunCMake/string/Timestamp.cmake
index d242039..cba258d 100644
--- a/Tests/RunCMake/string/Timestamp.cmake
+++ b/Tests/RunCMake/string/Timestamp.cmake
@@ -1,3 +1,3 @@
set(ENV{SOURCE_DATE_EPOCH} "1123456789")
-string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %a %b %y day=%j wd=%w week=%U %%I=%I epoch=%s" UTC)
+string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %A=%a %B=%b %y day=%j wd=%w week=%U %%I=%I epoch=%s" UTC)
message("RESULT=${RESULT}")