summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/cpack_gen/deb.rst14
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake177
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx45
-rw-r--r--Source/CTest/cmCTestBuildCommand.h23
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx12
-rw-r--r--Source/CTest/cmCTestConfigureCommand.h10
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx44
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h19
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx147
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h48
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.cxx15
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.h11
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx155
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h48
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx104
-rw-r--r--Source/CTest/cmCTestTestCommand.h37
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx7
-rw-r--r--Source/CTest/cmCTestUpdateCommand.h2
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx64
-rw-r--r--Source/CTest/cmCTestUploadCommand.h18
-rw-r--r--Source/cmAddCustomCommandCommand.cxx40
-rw-r--r--Source/cmAddCustomTargetCommand.cxx6
-rw-r--r--Source/cmArgumentParser.cxx6
-rw-r--r--Source/cmArgumentParser.h21
-rw-r--r--Source/cmCheckCustomOutputs.cxx36
-rw-r--r--Source/cmCheckCustomOutputs.h18
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx17
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx16
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx18
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h2
-rw-r--r--Source/cmake.cxx2
-rw-r--r--Tests/CPackComponentsDEB/MyLibCPackConfig-components-description1.cmake.in7
-rw-r--r--Tests/CPackComponentsDEB/MyLibCPackConfig-components-description2.cmake.in10
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake18
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake20
-rw-r--r--Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake25
-rw-r--r--Tests/RunCMake/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CPack/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/ExpectedFiles.cmake16
-rw-r--r--Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake65
-rw-r--r--Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/test.cmake45
-rw-r--r--Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake9
-rw-r--r--Tests/RunCMake/Configure/RerunCMake-build3-result.txt1
-rw-r--r--Tests/RunCMake/Configure/RerunCMake-build3-stdout.txt1
-rw-r--r--Tests/RunCMake/Configure/RerunCMake-build4-result.txt1
-rw-r--r--Tests/RunCMake/Configure/RerunCMake-build4-stdout.txt1
-rw-r--r--Tests/RunCMake/Configure/RerunCMake.cmake6
-rw-r--r--Tests/RunCMake/Configure/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt2
-rw-r--r--Tests/RunCMake/add_custom_command/BadByproduct-result.txt1
-rw-r--r--Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt36
-rw-r--r--Tests/RunCMake/add_custom_command/BadByproduct.cmake6
-rw-r--r--Tests/RunCMake/add_custom_command/BadOutput-result.txt1
-rw-r--r--Tests/RunCMake/add_custom_command/BadOutput-stderr.txt36
-rw-r--r--Tests/RunCMake/add_custom_command/BadOutput.cmake6
-rw-r--r--Tests/RunCMake/add_custom_command/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/add_custom_target/BadByproduct-result.txt1
-rw-r--r--Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt36
-rw-r--r--Tests/RunCMake/add_custom_target/BadByproduct.cmake6
-rw-r--r--Tests/RunCMake/add_custom_target/RunCMakeTest.cmake7
-rwxr-xr-xbootstrap1
64 files changed, 886 insertions, 695 deletions
diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index 23f0515..db71c87 100644
--- a/Help/cpack_gen/deb.rst
+++ b/Help/cpack_gen/deb.rst
@@ -179,16 +179,24 @@ List of CPack DEB generator specific variables:
* Default : ``CPACK_PACKAGE_CONTACT``
.. variable:: CPACK_DEBIAN_PACKAGE_DESCRIPTION
- CPACK_COMPONENT_<COMPONENT>_DESCRIPTION
+ CPACK_DEBIAN_<COMPONENT>_DESCRIPTION
The Debian package description
* Mandatory : YES
* Default :
- - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` if set or
- - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+ - :variable:`CPACK_DEBIAN_<COMPONENT>_DESCRIPTION` (component
+ based installers only) if set, or :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` if set, or
+ - :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION` (component
+ based installers only) if set, or :variable:`CPACK_PACKAGE_DESCRIPTION` if set, or
+ - content of the file specified in :variable:`CPACK_PACKAGE_DESCRIPTION_FILE` if set
+ If after that description is not set, :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` going to be
+ used if set. Otherwise, :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` will be added as the first
+ line of description as defined in `Debian Policy Manual`_.
+
+.. _Debian Policy Manual: https://www.debian.org/doc/debian-policy/ch-controlfields.html#description
.. variable:: CPACK_DEBIAN_PACKAGE_SECTION
CPACK_DEBIAN_<COMPONENT>_PACKAGE_SECTION
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 7791822..ad8e078 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -56,6 +56,67 @@ function(extract_so_info shared_object libname version)
endif()
endfunction()
+function(cpack_deb_check_description SUMMARY LINES RESULT_VARIABLE)
+ set(_result TRUE)
+
+ # Get the summary line
+ if(NOT SUMMARY MATCHES "^[^\\s].*$")
+ set(_result FALSE)
+ set(${RESULT_VARIABLE} ${_result} PARENT_SCOPE)
+ return()
+ endif()
+
+ foreach(_line IN LISTS LINES)
+ if(NOT _line MATCHES "^ +[^ ]+.*$")
+ set(_result FALSE)
+ break()
+ endif()
+ endforeach()
+
+ set(${RESULT_VARIABLE} ${_result} PARENT_SCOPE)
+endfunction()
+
+function(cpack_deb_format_package_description TEXT OUTPUT_VAR)
+ # Turn the possible multi-line string into a list
+ string(UUID uuid NAMESPACE 00000000-0000-0000-0000-000000000000 TYPE SHA1)
+ string(REPLACE ";" "${uuid}" _text "${TEXT}")
+ string(REPLACE "\n" ";" _lines "${_text}")
+ list(POP_FRONT _lines _summary)
+
+ # Check if reformatting required
+ cpack_deb_check_description("${_summary}" "${_lines}" _result)
+ if(_result)
+ # Ok, no formatting required
+ set(${OUTPUT_VAR} "${TEXT}" PARENT_SCOPE)
+ return()
+ endif()
+
+ # Format the summary line
+ string(STRIP "${_summary}" _summary)
+
+ # Make sure the rest formatted properly
+ set(_result)
+ foreach(_line IN LISTS _lines)
+ string(STRIP "${_line}" _line_strip)
+ if(NOT _line_strip)
+ # Replace empty lines w/ a _single full stop character_
+ set(_line " .")
+ else()
+ # Prepend the normal lines w/ a single space.
+ # If the line already starts w/ at least one space,
+ # it'll become _verbatim_ (assuming it supposed to be
+ # verbatim in the original text).
+ string(PREPEND _line " ")
+ endif()
+ list(APPEND _result "${_line}")
+ endforeach()
+
+ list(PREPEND _result "${_summary}")
+ list(JOIN _result "\n" _result)
+ string(REPLACE "${uuid}" ";" _result "${_result}")
+ set(${OUTPUT_VAR} "${_result}" PARENT_SCOPE)
+endfunction()
+
function(cpack_deb_prepare_package_vars)
# CPACK_DEBIAN_PACKAGE_SHLIBDEPS
# If specify OFF, only user depends are used
@@ -102,7 +163,7 @@ function(cpack_deb_prepare_package_vars)
RESULT_VARIABLE FILE_RESULT_
OUTPUT_VARIABLE INSTALL_FILE_)
if(NOT FILE_RESULT_ EQUAL 0)
- message (FATAL_ERROR "CPackDeb: execution of command: '${FILE_EXECUTABLE} ./${FILE_}' failed with exit code: ${FILE_RESULT_}")
+ message(FATAL_ERROR "CPackDeb: execution of command: '${FILE_EXECUTABLE} ./${FILE_}' failed with exit code: ${FILE_RESULT_}")
endif()
list(APPEND CPACK_DEB_INSTALL_FILES "${INSTALL_FILE_}")
endforeach()
@@ -210,7 +271,7 @@ function(cpack_deb_prepare_package_vars)
if(_TMP_VERSION MATCHES "dpkg-shlibdeps version ([0-9]+\\.[0-9]+\\.[0-9]+)")
set(SHLIBDEPS_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
else()
- set(SHLIBDEPS_EXECUTABLE_VERSION "")
+ unset(SHLIBDEPS_EXECUTABLE_VERSION)
endif()
if(CPACK_DEBIAN_PACKAGE_DEBUG)
@@ -253,7 +314,7 @@ function(cpack_deb_prepare_package_vars)
message( "CPackDeb Debug: dpkg-shlibdeps warnings \n${SHLIBDEPS_ERROR}")
endif()
if(NOT SHLIBDEPS_RESULT EQUAL 0)
- message (FATAL_ERROR "CPackDeb: dpkg-shlibdeps: '${SHLIBDEPS_ERROR}';\n"
+ message(FATAL_ERROR "CPackDeb: dpkg-shlibdeps: '${SHLIBDEPS_ERROR}';\n"
"executed command: '${SHLIBDEPS_EXECUTABLE} ${IGNORE_MISSING_INFO_FLAG} -O ${CPACK_DEB_BINARY_FILES}';\n"
"found files: '${INSTALL_FILE_}';\n"
"files info: '${CPACK_DEB_INSTALL_FILES}';\n"
@@ -388,7 +449,7 @@ function(cpack_deb_prepare_package_vars)
# if per-component variable, overrides the global CPACK_DEBIAN_PACKAGE_${variable_type_}
# automatic dependency discovery will be performed afterwards.
if(CPACK_DEB_PACKAGE_COMPONENT)
- foreach(value_type_ DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS CONFLICTS PROVIDES REPLACES SOURCE SECTION PRIORITY NAME)
+ foreach(value_type_ IN ITEMS DEPENDS RECOMMENDS SUGGESTS PREDEPENDS ENHANCES BREAKS CONFLICTS PROVIDES REPLACES SOURCE SECTION PRIORITY NAME)
set(_component_var "CPACK_DEBIAN_${_local_component_name}_PACKAGE_${value_type_}")
# if set, overrides the global variable
@@ -402,21 +463,15 @@ function(cpack_deb_prepare_package_vars)
endforeach()
if(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS)
- set(COMPONENT_DEPENDS "")
- foreach (_PACK ${CPACK_COMPONENT_${_local_component_name}_DEPENDS})
+ unset(COMPONENT_DEPENDS)
+ foreach(_PACK IN LISTS CPACK_COMPONENT_${_local_component_name}_DEPENDS)
get_component_package_name(_PACK_NAME "${_PACK}")
- if(COMPONENT_DEPENDS)
- set(COMPONENT_DEPENDS "${_PACK_NAME} (= ${CPACK_DEBIAN_PACKAGE_VERSION}), ${COMPONENT_DEPENDS}")
- else()
- set(COMPONENT_DEPENDS "${_PACK_NAME} (= ${CPACK_DEBIAN_PACKAGE_VERSION})")
- endif()
+ list(PREPEND COMPONENT_DEPENDS "${_PACK_NAME} (= ${CPACK_DEBIAN_PACKAGE_VERSION})")
endforeach()
+ list(JOIN COMPONENT_DEPENDS ", " COMPONENT_DEPENDS)
if(COMPONENT_DEPENDS)
- if(CPACK_DEBIAN_PACKAGE_DEPENDS)
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "${COMPONENT_DEPENDS}, ${CPACK_DEBIAN_PACKAGE_DEPENDS}")
- else()
- set(CPACK_DEBIAN_PACKAGE_DEPENDS "${COMPONENT_DEPENDS}")
- endif()
+ list(PREPEND CPACK_DEBIAN_PACKAGE_DEPENDS ${COMPONENT_DEPENDS})
+ list(JOIN CPACK_DEBIAN_PACKAGE_DEPENDS ", " CPACK_DEBIAN_PACKAGE_DEPENDS)
endif()
endif()
endif()
@@ -424,12 +479,9 @@ function(cpack_deb_prepare_package_vars)
# at this point, the CPACK_DEBIAN_PACKAGE_DEPENDS is properly set
# to the minimal dependency of the package
# Append automatically discovered dependencies .
- if(NOT "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}" STREQUAL "")
- if (CPACK_DEBIAN_PACKAGE_DEPENDS)
- set (CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}")
- else ()
- set (CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS}")
- endif ()
+ if(CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS)
+ list(APPEND CPACK_DEBIAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_PACKAGE_AUTO_DEPENDS})
+ list(JOIN CPACK_DEBIAN_PACKAGE_DEPENDS ", " CPACK_DEBIAN_PACKAGE_DEPENDS)
endif()
if(NOT CPACK_DEBIAN_PACKAGE_DEPENDS)
@@ -445,26 +497,53 @@ function(cpack_deb_prepare_package_vars)
endif()
# Description: (mandatory)
- if(NOT CPACK_DEB_PACKAGE_COMPONENT)
- if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION)
- if(NOT CPACK_PACKAGE_DESCRIPTION_SUMMARY)
- message(FATAL_ERROR "CPackDeb: Debian package requires a summary for a package, set CPACK_PACKAGE_DESCRIPTION_SUMMARY or CPACK_DEBIAN_PACKAGE_DESCRIPTION")
- endif()
- set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
- endif()
+ # Try package description first
+ if(CPACK_DEB_PACKAGE_COMPONENT)
+ cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION"
+ "CPACK_DEBIAN_${_local_component_name}_DESCRIPTION"
+ "CPACK_COMPONENT_${_local_component_name}_DESCRIPTION")
else()
- set(component_description_var CPACK_COMPONENT_${_local_component_name}_DESCRIPTION)
-
- # component description overrides package description
- if(${component_description_var})
- set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${${component_description_var}})
- elseif(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION)
- if(NOT CPACK_PACKAGE_DESCRIPTION_SUMMARY)
- message(FATAL_ERROR "CPackDeb: Debian package requires a summary for a package, set CPACK_PACKAGE_DESCRIPTION_SUMMARY or CPACK_DEBIAN_PACKAGE_DESCRIPTION or ${component_description_var}")
- endif()
+ cpack_deb_variable_fallback("CPACK_DEBIAN_PACKAGE_DESCRIPTION"
+ "CPACK_DEBIAN_PACKAGE_DESCRIPTION"
+ "CPACK_PACKAGE_DESCRIPTION")
+ endif()
+
+ # Still no description? ... and description file has set ...
+ if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION AND CPACK_PACKAGE_DESCRIPTION_FILE)
+ # Read `CPACK_PACKAGE_DESCRIPTION_FILE` then...
+ file(READ ${CPACK_PACKAGE_DESCRIPTION_FILE} CPACK_DEBIAN_PACKAGE_DESCRIPTION)
+ endif()
+
+ # Still no description? #2
+ if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION)
+ # Try to get `CPACK_PACKAGE_DESCRIPTION_SUMMARY` as the last hope
+ if(CPACK_PACKAGE_DESCRIPTION_SUMMARY)
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
+ else()
+ # Giving up! Report an error...
+ set(_description_failure_message
+ "CPackDeb: Debian package requires a summary for a package, set CPACK_PACKAGE_DESCRIPTION_SUMMARY or CPACK_DEBIAN_PACKAGE_DESCRIPTION")
+ if(CPACK_DEB_PACKAGE_COMPONENT)
+ string(APPEND _description_failure_message
+ " or CPACK_DEBIAN_${_local_component_name}_DESCRIPTION")
+ endif()
+ message(FATAL_ERROR _description_failure_message)
endif()
+
+ # Ok, description has set. According to the `Debian Policy Manual`_ the frist
+ # line is a pacakge summary. Try to get it as well...
+ # See also: https://www.debian.org/doc/debian-policy/ch-controlfields.html#description
+ elseif(CPACK_PACKAGE_DESCRIPTION_SUMMARY)
+ # Merge summary w/ the detailed description
+ string(PREPEND CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n")
endif()
+ # assert(CPACK_DEBIAN_PACKAGE_DESCRIPTION)
+
+ # Make sure description is properly formatted
+ cpack_deb_format_package_description(
+ "${CPACK_DEBIAN_PACKAGE_DESCRIPTION}"
+ CPACK_DEBIAN_PACKAGE_DESCRIPTION
+ )
# Homepage: (optional)
if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CMAKE_PROJECT_HOMEPAGE_URL)
@@ -519,7 +598,7 @@ function(cpack_deb_prepare_package_vars)
# Are we packaging components ?
if(CPACK_DEB_PACKAGE_COMPONENT)
# override values with per component version if set
- foreach(VAR_NAME_ "PACKAGE_CONTROL_EXTRA" "PACKAGE_CONTROL_STRICT_PERMISSION")
+ foreach(VAR_NAME_ IN ITEMS PACKAGE_CONTROL_EXTRA PACKAGE_CONTROL_STRICT_PERMISSION)
if(CPACK_DEBIAN_${_local_component_name}_${VAR_NAME_})
set(CPACK_DEBIAN_${VAR_NAME_} "${CPACK_DEBIAN_${_local_component_name}_${VAR_NAME_}}")
endif()
@@ -527,12 +606,12 @@ function(cpack_deb_prepare_package_vars)
get_component_package_name(CPACK_DEBIAN_PACKAGE_NAME ${_local_component_name})
endif()
- set(CPACK_DEBIAN_PACKAGE_SHLIBS_LIST "")
-
- if (NOT CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY)
+ if(NOT CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY "=")
endif()
+ unset(CPACK_DEBIAN_PACKAGE_SHLIBS_LIST)
+
if(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
if(READELF_EXECUTABLE)
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
@@ -544,9 +623,7 @@ function(cpack_deb_prepare_package_vars)
message(AUTHOR_WARNING "Shared library '${_FILE}' is missing soname or soversion. Library will not be added to DEBIAN/shlibs control file.")
endif()
endforeach()
- if (CPACK_DEBIAN_PACKAGE_SHLIBS_LIST)
- string(REPLACE ";" "\n" CPACK_DEBIAN_PACKAGE_SHLIBS_LIST "${CPACK_DEBIAN_PACKAGE_SHLIBS_LIST}")
- endif()
+ list(JOIN CPACK_DEBIAN_PACKAGE_SHLIBS_LIST "\n" CPACK_DEBIAN_PACKAGE_SHLIBS_LIST)
else()
message(FATAL_ERROR "Readelf utility is not available. CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS option is not available.")
endif()
@@ -554,7 +631,7 @@ function(cpack_deb_prepare_package_vars)
# add ldconfig call in default postrm and postint
set(CPACK_ADD_LDCONFIG_CALL 0)
- foreach(_FILE ${CPACK_DEB_SHARED_OBJECT_FILES})
+ foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
get_filename_component(_DIR ${_FILE} DIRECTORY)
# all files in CPACK_DEB_SHARED_OBJECT_FILES have dot at the beginning
if(_DIR STREQUAL "./lib" OR _DIR STREQUAL "./usr/lib")
@@ -565,12 +642,12 @@ function(cpack_deb_prepare_package_vars)
if(CPACK_ADD_LDCONFIG_CALL)
set(CPACK_DEBIAN_GENERATE_POSTINST 1)
set(CPACK_DEBIAN_GENERATE_POSTRM 1)
- foreach(f ${PACKAGE_CONTROL_EXTRA})
+ foreach(f IN LISTS PACKAGE_CONTROL_EXTRA)
get_filename_component(n "${f}" NAME)
- if("${n}" STREQUAL "postinst")
+ if(n STREQUAL "postinst")
set(CPACK_DEBIAN_GENERATE_POSTINST 0)
endif()
- if("${n}" STREQUAL "postrm")
+ if(n STREQUAL "postrm")
set(CPACK_DEBIAN_GENERATE_POSTRM 0)
endif()
endforeach()
@@ -671,7 +748,7 @@ function(cpack_deb_prepare_package_vars)
if(BUILD_IDS)
set(GEN_DBGSYMDIR "${DBGSYMDIR}" PARENT_SCOPE)
set(GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DBGSYM_OUTPUT_FILE_NAME}" PARENT_SCOPE)
- string(REPLACE ";" " " BUILD_IDS "${BUILD_IDS}")
+ list(JOIN BUILD_IDS " " BUILD_IDS)
set(GEN_BUILD_IDS "${BUILD_IDS}" PARENT_SCOPE)
endif()
endfunction()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8ed7b2f..71a7dbd 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -168,6 +168,8 @@ set(SRCS
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
cmCacheManager.cxx
cmCacheManager.h
+ cmCheckCustomOutputs.h
+ cmCheckCustomOutputs.cxx
cmCLocaleEnvironmentScope.h
cmCLocaleEnvironmentScope.cxx
cmCommandArgumentParserHelper.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f85707d..d24c2c0 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 15)
-set(CMake_VERSION_PATCH 20190924)
+set(CMake_VERSION_PATCH 20190925)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 02b00e3..ce690f9 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -9,6 +9,7 @@
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cm_static_string_view.hxx"
#include "cmake.h"
#include <cstring>
@@ -16,17 +17,15 @@
class cmExecutionStatus;
-cmCTestBuildCommand::cmCTestBuildCommand()
+void cmCTestBuildCommand::BindArguments()
{
- this->GlobalGenerator = nullptr;
- this->Arguments[ctb_NUMBER_ERRORS] = "NUMBER_ERRORS";
- this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS";
- this->Arguments[ctb_TARGET] = "TARGET";
- this->Arguments[ctb_CONFIGURATION] = "CONFIGURATION";
- this->Arguments[ctb_FLAGS] = "FLAGS";
- this->Arguments[ctb_PROJECT_NAME] = "PROJECT_NAME";
- this->Arguments[ctb_LAST] = nullptr;
- this->Last = ctb_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("NUMBER_ERRORS"_s, this->NumberErrors);
+ this->Bind("NUMBER_WARNINGS"_s, this->NumberWarnings);
+ this->Bind("TARGET"_s, this->Target);
+ this->Bind("CONFIGURATION"_s, this->Configuration);
+ this->Bind("FLAGS"_s, this->Flags);
+ this->Bind("PROJECT_NAME"_s, this->ProjectName);
}
cmCTestBuildCommand::~cmCTestBuildCommand()
@@ -60,20 +59,17 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
//
const char* ctestBuildConfiguration =
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
- const char* cmakeBuildConfiguration =
- (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
- ? this->Values[ctb_CONFIGURATION]
+ const char* cmakeBuildConfiguration = !this->Configuration.empty()
+ ? this->Configuration.c_str()
: ((ctestBuildConfiguration && *ctestBuildConfiguration)
? ctestBuildConfiguration
: this->CTest->GetConfigType().c_str());
- const char* cmakeBuildAdditionalFlags =
- (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
- ? this->Values[ctb_FLAGS]
+ const char* cmakeBuildAdditionalFlags = !this->Flags.empty()
+ ? this->Flags.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
- const char* cmakeBuildTarget =
- (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
- ? this->Values[ctb_TARGET]
+ const char* cmakeBuildTarget = !this->Target.empty()
+ ? this->Target.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
if (cmakeGeneratorName && *cmakeGeneratorName) {
@@ -153,16 +149,13 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
bool ret = cmCTestHandlerCommand::InitialPass(args, status);
- if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) {
+ if (!this->NumberErrors.empty()) {
this->Makefile->AddDefinition(
- this->Values[ctb_NUMBER_ERRORS],
- std::to_string(this->Handler->GetTotalErrors()));
+ this->NumberErrors, std::to_string(this->Handler->GetTotalErrors()));
}
- if (this->Values[ctb_NUMBER_WARNINGS] &&
- *this->Values[ctb_NUMBER_WARNINGS]) {
+ if (!this->NumberWarnings.empty()) {
this->Makefile->AddDefinition(
- this->Values[ctb_NUMBER_WARNINGS],
- std::to_string(this->Handler->GetTotalWarnings()));
+ this->NumberWarnings, std::to_string(this->Handler->GetTotalWarnings()));
}
return ret;
}
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 14f70bf..791e1f0 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -27,7 +27,6 @@ class cmGlobalGenerator;
class cmCTestBuildCommand : public cmCTestHandlerCommand
{
public:
- cmCTestBuildCommand();
~cmCTestBuildCommand() override;
/**
@@ -49,23 +48,19 @@ public:
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
- cmGlobalGenerator* GlobalGenerator;
+ cmGlobalGenerator* GlobalGenerator = nullptr;
protected:
cmCTestBuildHandler* Handler;
- enum
- {
- ctb_BUILD = ct_LAST,
- ctb_NUMBER_ERRORS,
- ctb_NUMBER_WARNINGS,
- ctb_TARGET,
- ctb_CONFIGURATION,
- ctb_FLAGS,
- ctb_PROJECT_NAME,
- ctb_LAST
- };
-
+ void BindArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
+
+ std::string NumberErrors;
+ std::string NumberWarnings;
+ std::string Target;
+ std::string Configuration;
+ std::string Flags;
+ std::string ProjectName;
};
#endif
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 8a56f3d..948b9fb 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -8,25 +8,25 @@
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cm_static_string_view.hxx"
#include "cmake.h"
#include <cstring>
#include <sstream>
#include <vector>
-cmCTestConfigureCommand::cmCTestConfigureCommand()
+void cmCTestConfigureCommand::BindArguments()
{
- this->Arguments[ctc_OPTIONS] = "OPTIONS";
- this->Arguments[ctc_LAST] = nullptr;
- this->Last = ctc_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("OPTIONS"_s, this->Options);
}
cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
{
std::vector<std::string> options;
- if (this->Values[ctc_OPTIONS]) {
- cmExpandList(this->Values[ctc_OPTIONS], options);
+ if (!this->Options.empty()) {
+ cmExpandList(this->Options, options);
}
if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) {
diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h
index 36ca7d5..0bc7848 100644
--- a/Source/CTest/cmCTestConfigureCommand.h
+++ b/Source/CTest/cmCTestConfigureCommand.h
@@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestConfigureCommand : public cmCTestHandlerCommand
{
public:
- cmCTestConfigureCommand();
-
/**
* This is a virtual constructor for the command.
*/
@@ -42,14 +40,10 @@ public:
std::string GetName() const override { return "ctest_configure"; }
protected:
+ void BindArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
- enum
- {
- ctc_FIRST = ct_LAST,
- ctc_OPTIONS,
- ctc_LAST
- };
+ std::string Options;
};
#endif
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 07aae76..b66bba7 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -2,14 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageCommand.h"
+#include <set>
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
+#include "cm_static_string_view.hxx"
class cmCTestGenericHandler;
-cmCTestCoverageCommand::cmCTestCoverageCommand()
+void cmCTestCoverageCommand::BindArguments()
+{
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("LABELS"_s, this->Labels);
+}
+
+void cmCTestCoverageCommand::CheckArguments(
+ std::vector<std::string> const& keywords)
{
- this->LabelsMentioned = false;
+ this->LabelsMentioned =
+ !this->Labels.empty() || cmContains(keywords, "LABELS");
}
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
@@ -24,34 +36,10 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
// If a LABELS option was given, select only files with the labels.
if (this->LabelsMentioned) {
- handler->SetLabelFilter(this->Labels);
+ handler->SetLabelFilter(
+ std::set<std::string>(this->Labels.begin(), this->Labels.end()));
}
handler->SetQuiet(this->Quiet);
return handler;
}
-
-bool cmCTestCoverageCommand::CheckArgumentKeyword(std::string const& arg)
-{
- // Look for arguments specific to this command.
- if (arg == "LABELS") {
- this->ArgumentDoing = ArgumentDoingLabels;
- this->LabelsMentioned = true;
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentKeyword(arg);
-}
-
-bool cmCTestCoverageCommand::CheckArgumentValue(std::string const& arg)
-{
- // Handle states specific to this command.
- if (this->ArgumentDoing == ArgumentDoingLabels) {
- this->Labels.insert(arg);
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
-}
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 75aefdf..fcffa75 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -8,9 +8,9 @@
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
-#include <set>
#include <string>
#include <utility>
+#include <vector>
#include <cm/memory>
@@ -24,8 +24,6 @@ class cmCTestGenericHandler;
class cmCTestCoverageCommand : public cmCTestHandlerCommand
{
public:
- cmCTestCoverageCommand();
-
/**
* This is a virtual constructor for the command.
*/
@@ -42,22 +40,13 @@ public:
*/
std::string GetName() const override { return "ctest_coverage"; }
- using Superclass = cmCTestHandlerCommand;
-
protected:
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool CheckArgumentKeyword(std::string const& arg) override;
- bool CheckArgumentValue(std::string const& arg) override;
-
- enum
- {
- ArgumentDoingLabels = Superclass::ArgumentDoingLast1,
- ArgumentDoingLast2
- };
-
bool LabelsMentioned;
- std::set<std::string> Labels;
+ std::vector<std::string> Labels;
};
#endif
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 9c5425d..3f9ce4e 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -7,31 +7,16 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
+#include "cm_static_string_view.hxx"
+#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <sstream>
-cmCTestHandlerCommand::cmCTestHandlerCommand()
-{
- const size_t INIT_SIZE = 100;
- size_t cc;
- this->Arguments.reserve(INIT_SIZE);
- for (cc = 0; cc < INIT_SIZE; ++cc) {
- this->Arguments.push_back(nullptr);
- }
- this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE";
- this->Arguments[ct_CAPTURE_CMAKE_ERROR] = "CAPTURE_CMAKE_ERROR";
- this->Arguments[ct_SOURCE] = "SOURCE";
- this->Arguments[ct_BUILD] = "BUILD";
- this->Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX";
- this->Last = ct_LAST;
- this->AppendXML = false;
- this->Quiet = false;
-}
-
namespace {
// class to save and restore the error state for ctest_* commands
// if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error
@@ -90,30 +75,30 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// save error state and restore it if needed
SaveRestoreErrorState errorState;
// Allocate space for argument values.
- this->Values.clear();
- this->Values.resize(this->Last, nullptr);
+ this->BindArguments();
// Process input arguments.
- this->ArgumentDoing = ArgumentDoingNone;
- // look at all arguments and do not short circuit on the first
- // bad one so that CAPTURE_CMAKE_ERROR can override setting the
- // global error state
- bool foundBadArgument = false;
- for (std::string const& arg : args) {
- // Check this argument.
- if (!this->CheckArgumentKeyword(arg) && !this->CheckArgumentValue(arg)) {
- std::ostringstream e;
- e << "called with unknown argument \"" << arg << "\".";
- this->SetError(e.str());
- foundBadArgument = true;
- }
- // note bad argument
- if (this->ArgumentDoing == ArgumentDoingError) {
- foundBadArgument = true;
- }
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValue;
+ std::vector<std::string> parsedKeywords;
+ this->Parse(args, &unparsedArguments, &keywordsMissingValue,
+ &parsedKeywords);
+ this->CheckArguments(keywordsMissingValue);
+
+ std::sort(parsedKeywords.begin(), parsedKeywords.end());
+ auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
+ if (it != parsedKeywords.end()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Called with more than one value for ", *it));
+ }
+
+ bool const foundBadArgument = !unparsedArguments.empty();
+ if (foundBadArgument) {
+ this->SetError(cmStrCat("called with unknown argument \"",
+ unparsedArguments.front(), "\"."));
}
- bool captureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
- *this->Values[ct_CAPTURE_CMAKE_ERROR]);
+ bool const captureCMakeError = !this->CaptureCMakeError.empty();
// now that arguments are parsed check to see if there is a
// CAPTURE_CMAKE_ERROR specified let the errorState object know.
if (captureCMakeError) {
@@ -123,8 +108,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
if (foundBadArgument) {
// store the cmake error
if (captureCMakeError) {
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- "-1");
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
std::string const err = this->GetName() + " " + status.GetError();
if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
@@ -146,10 +130,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetConfigType(ctestConfigType);
}
- if (this->Values[ct_BUILD]) {
+ if (!this->Build.empty()) {
this->CTest->SetCTestConfiguration(
- "BuildDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
+ "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(),
this->Quiet);
} else {
std::string const& bdir =
@@ -163,13 +146,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
"CTEST_BINARY_DIRECTORY not set" << std::endl;);
}
}
- if (this->Values[ct_SOURCE]) {
+ if (!this->Source.empty()) {
cmCTestLog(this->CTest, DEBUG,
- "Set source directory to: " << this->Values[ct_SOURCE]
- << std::endl);
+ "Set source directory to: " << this->Source << std::endl);
this->CTest->SetCTestConfiguration(
- "SourceDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
@@ -192,8 +173,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
"Cannot instantiate test handler " << this->GetName()
<< std::endl);
if (captureCMakeError) {
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- "-1");
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
std::string const& err = status.GetError();
if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
@@ -203,11 +183,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- handler->SetAppendXML(this->AppendXML);
+ handler->SetAppendXML(this->Append);
handler->PopulateCustomVectors(this->Makefile);
- if (this->Values[ct_SUBMIT_INDEX]) {
- handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX]));
+ if (!this->SubmitIndex.empty()) {
+ handler->SetSubmitIndex(atoi(this->SubmitIndex.c_str()));
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
@@ -216,8 +196,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->GetCTestConfiguration("BuildDirectory") +
" : " + std::strerror(workdir.GetLastResult()));
if (captureCMakeError) {
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- "-1");
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
cmCTestLog(this->CTest, ERROR_MESSAGE,
this->GetName() << " " << status.GetError() << "\n");
// return success because failure is recorded in CAPTURE_CMAKE_ERROR
@@ -227,9 +206,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
int res = handler->ProcessHandler();
- if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
- this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
- std::to_string(res));
+ if (!this->ReturnValue.empty()) {
+ this->Makefile->AddDefinition(this->ReturnValue, std::to_string(res));
}
this->ProcessAdditionalValues(handler);
// log the error message if there was an error
@@ -245,8 +223,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
}
// store the captured cmake error state 0 or -1
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- returnString);
+ this->Makefile->AddDefinition(this->CaptureCMakeError, returnString);
}
return true;
}
@@ -255,47 +232,17 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
{
}
-bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestHandlerCommand::BindArguments()
{
- // Look for non-value arguments common to all commands.
- if (arg == "APPEND") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->AppendXML = true;
- return true;
- }
- if (arg == "QUIET") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->Quiet = true;
- return true;
- }
-
- // Check for a keyword in our argument/value table.
- for (unsigned int k = 0; k < this->Arguments.size(); ++k) {
- if (this->Arguments[k] && arg == this->Arguments[k]) {
- this->ArgumentDoing = ArgumentDoingKeyword;
- this->ArgumentIndex = k;
- return true;
- }
- }
- return false;
+ this->Bind("APPEND"_s, this->Append);
+ this->Bind("QUIET"_s, this->Quiet);
+ this->Bind("RETURN_VALUE"_s, this->ReturnValue);
+ this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
+ this->Bind("SOURCE"_s, this->Source);
+ this->Bind("BUILD"_s, this->Build);
+ this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
+void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
{
- if (this->ArgumentDoing == ArgumentDoingKeyword) {
- this->ArgumentDoing = ArgumentDoingNone;
- unsigned int k = this->ArgumentIndex;
- if (this->Values[k]) {
- std::ostringstream e;
- e << "Called with more than one value for " << this->Arguments[k];
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
- return true;
- }
- this->Values[k] = arg.c_str();
- cmCTestLog(this->CTest, DEBUG,
- "Set " << this->Arguments[k] << " to " << arg << "\n");
- return true;
- }
- return false;
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 79d61f3..5bbc569 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -5,9 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmArgumentParser.h"
#include "cmCTestCommand.h"
-#include <stddef.h>
#include <string>
#include <vector>
@@ -19,11 +19,11 @@ class cmExecutionStatus;
*
* cmCTestHandlerCommand defineds the command to test the project.
*/
-class cmCTestHandlerCommand : public cmCTestCommand
+class cmCTestHandlerCommand
+ : public cmCTestCommand
+ , public cmArgumentParser<void>
{
public:
- cmCTestHandlerCommand();
-
/**
* The name of the command as specified in CMakeList.txt.
*/
@@ -36,42 +36,22 @@ public:
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
- enum
- {
- ct_NONE,
- ct_RETURN_VALUE,
- ct_CAPTURE_CMAKE_ERROR,
- ct_BUILD,
- ct_SOURCE,
- ct_SUBMIT_INDEX,
- ct_LAST
- };
-
protected:
virtual cmCTestGenericHandler* InitializeHandler() = 0;
virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler);
// Command argument handling.
- virtual bool CheckArgumentKeyword(std::string const& arg);
- virtual bool CheckArgumentValue(std::string const& arg);
- enum
- {
- ArgumentDoingNone,
- ArgumentDoingError,
- ArgumentDoingKeyword,
- ArgumentDoingLast1
- };
- int ArgumentDoing;
- unsigned int ArgumentIndex;
-
- bool AppendXML;
- bool Quiet;
-
- std::string ReturnVariable;
- std::vector<const char*> Arguments;
- std::vector<const char*> Values;
- size_t Last;
+ virtual void BindArguments();
+ virtual void CheckArguments(std::vector<std::string> const& keywords);
+
+ bool Append = false;
+ bool Quiet = false;
+ std::string CaptureCMakeError;
+ std::string ReturnValue;
+ std::string Build;
+ std::string Source;
+ std::string SubmitIndex;
};
#define CTEST_COMMAND_APPEND_OPTION_DOCS \
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index 804efa5..abad5fc 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -2,18 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckCommand.h"
-#include <string>
-#include <vector>
-
#include "cmCTest.h"
#include "cmCTestMemCheckHandler.h"
#include "cmMakefile.h"
+#include "cm_static_string_view.hxx"
-cmCTestMemCheckCommand::cmCTestMemCheckCommand()
+void cmCTestMemCheckCommand::BindArguments()
{
- this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT";
- this->Arguments[ctm_LAST] = nullptr;
- this->Last = ctm_LAST;
+ this->cmCTestTestCommand::BindArguments();
+ this->Bind("DEFECT_COUNT"_s, this->DefectCount);
}
cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
@@ -43,9 +40,9 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
void cmCTestMemCheckCommand::ProcessAdditionalValues(
cmCTestGenericHandler* handler)
{
- if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) {
+ if (!this->DefectCount.empty()) {
this->Makefile->AddDefinition(
- this->Values[ctm_DEFECT_COUNT],
+ this->DefectCount,
std::to_string(
static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount()));
}
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index 5dad4e7..8f4ffb8 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <string>
#include <utility>
#include <cm/memory>
@@ -22,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestMemCheckCommand : public cmCTestTestCommand
{
public:
- cmCTestMemCheckCommand();
-
/**
* This is a virtual constructor for the command.
*/
@@ -36,15 +35,13 @@ public:
}
protected:
+ void BindArguments() override;
+
cmCTestGenericHandler* InitializeActualHandler() override;
void ProcessAdditionalValues(cmCTestGenericHandler* handler) override;
- enum
- {
- ctm_DEFECT_COUNT = ctt_LAST,
- ctm_LAST
- };
+ std::string DefectCount;
};
#endif
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 2e2cf1a..706b45a 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -2,14 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitCommand.h"
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestSubmitHandler.h"
#include "cmCommand.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cm_static_string_view.hxx"
+#include <set>
#include <sstream>
#include <utility>
@@ -17,18 +21,6 @@
class cmExecutionStatus;
-cmCTestSubmitCommand::cmCTestSubmitCommand()
-{
- this->PartsMentioned = false;
- this->FilesMentioned = false;
- this->InternalTest = false;
- this->RetryCount = "";
- this->RetryDelay = "";
- this->CDashUpload = false;
- this->Arguments[cts_BUILD_ID] = "BUILD_ID";
- this->Last = cts_LAST;
-}
-
/**
* This is a virtual constructor for the command.
*/
@@ -106,13 +98,18 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// without any of the default parts.
//
handler->SelectParts(std::set<cmCTest::Part>());
- handler->SelectFiles(this->Files);
+ handler->SelectFiles(
+ std::set<std::string>(this->Files.begin(), this->Files.end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
if (this->PartsMentioned) {
- handler->SelectParts(this->Parts);
+ auto parts =
+ cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ return this->CTest->GetPartFromName(arg.c_str());
+ });
+ handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
}
// Pass along any HTTPHEADER to the handler if this option was given.
@@ -140,133 +137,61 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);
- if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) {
- this->Makefile->AddDefinition(this->Values[cts_BUILD_ID],
- this->CTest->GetBuildID());
+ if (!this->BuildID.empty()) {
+ this->Makefile->AddDefinition(this->BuildID, this->CTest->GetBuildID());
}
return ret;
}
-bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestSubmitCommand::BindArguments()
{
if (this->CDashUpload) {
// Arguments specific to the CDASH_UPLOAD signature.
- if (arg == "CDASH_UPLOAD") {
- this->ArgumentDoing = ArgumentDoingCDashUpload;
- return true;
- }
-
- if (arg == "CDASH_UPLOAD_TYPE") {
- this->ArgumentDoing = ArgumentDoingCDashUploadType;
- return true;
- }
+ this->Bind("CDASH_UPLOAD", this->CDashUploadFile);
+ this->Bind("CDASH_UPLOAD_TYPE", this->CDashUploadType);
} else {
// Arguments that cannot be used with CDASH_UPLOAD.
- if (arg == "PARTS") {
- this->ArgumentDoing = ArgumentDoingParts;
- this->PartsMentioned = true;
- return true;
- }
-
- if (arg == "FILES") {
- this->ArgumentDoing = ArgumentDoingFiles;
- this->FilesMentioned = true;
- return true;
- }
+ this->Bind("PARTS"_s, this->Parts);
+ this->Bind("FILES"_s, this->Files);
}
// Arguments used by both modes.
- if (arg == "HTTPHEADER") {
- this->ArgumentDoing = ArgumentDoingHttpHeader;
- return true;
- }
-
- if (arg == "RETRY_COUNT") {
- this->ArgumentDoing = ArgumentDoingRetryCount;
- return true;
- }
-
- if (arg == "RETRY_DELAY") {
- this->ArgumentDoing = ArgumentDoingRetryDelay;
- return true;
- }
-
- if (arg == "SUBMIT_URL") {
- this->ArgumentDoing = ArgumentDoingSubmitURL;
- return true;
- }
-
- if (arg == "INTERNAL_TEST_CHECKSUM") {
- this->InternalTest = true;
- return true;
- }
+ this->Bind("BUILD_ID"_s, this->BuildID);
+ this->Bind("HTTPHEADER"_s, this->HttpHeaders);
+ this->Bind("RETRY_COUNT"_s, this->RetryCount);
+ this->Bind("RETRY_DELAY"_s, this->RetryDelay);
+ this->Bind("SUBMIT_URL"_s, this->SubmitURL);
+ this->Bind("INTERNAL_TEST_CHECKSUM", this->InternalTest);
// Look for other arguments.
- return this->Superclass::CheckArgumentKeyword(arg);
+ this->cmCTestHandlerCommand::BindArguments();
}
-bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
+void cmCTestSubmitCommand::CheckArguments(
+ std::vector<std::string> const& keywords)
{
- // Handle states specific to this command.
- if (this->ArgumentDoing == ArgumentDoingParts) {
+ this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS");
+ this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES");
+
+ cmEraseIf(this->Parts, [this](std::string const& arg) -> bool {
cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str());
- if (p != cmCTest::PartCount) {
- this->Parts.insert(p);
- } else {
+ if (p == cmCTest::PartCount) {
std::ostringstream e;
e << "Part name \"" << arg << "\" is invalid.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
+ return true;
}
- return true;
- }
+ return false;
+ });
- if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg)) {
- this->Files.insert(arg);
- } else {
+ cmEraseIf(this->Files, [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
std::ostringstream e;
e << "File \"" << arg << "\" does not exist. Cannot submit "
<< "a non-existent file.";
this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
+ return true;
}
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingHttpHeader) {
- this->HttpHeaders.push_back(arg);
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingRetryCount) {
- this->RetryCount = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingRetryDelay) {
- this->RetryDelay = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingCDashUpload) {
- this->ArgumentDoing = ArgumentDoingNone;
- this->CDashUploadFile = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingCDashUploadType) {
- this->ArgumentDoing = ArgumentDoingNone;
- this->CDashUploadType = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingSubmitURL) {
- this->ArgumentDoing = ArgumentDoingNone;
- this->SubmitURL = arg;
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
+ return false;
+ });
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index 8562207..249f844 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -5,11 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTest.h"
#include "cmCTestHandlerCommand.h"
#include <memory>
-#include <set>
#include <string>
#include <vector>
@@ -26,7 +24,6 @@ class cmExecutionStatus;
class cmCTestSubmitCommand : public cmCTestHandlerCommand
{
public:
- cmCTestSubmitCommand();
std::unique_ptr<cmCommand> Clone() override;
bool InitialPass(std::vector<std::string> const& args,
@@ -37,45 +34,26 @@ public:
*/
std::string GetName() const override { return "ctest_submit"; }
- using Superclass = cmCTestHandlerCommand;
-
protected:
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool CheckArgumentKeyword(std::string const& arg) override;
- bool CheckArgumentValue(std::string const& arg) override;
-
- enum
- {
- ArgumentDoingParts = Superclass::ArgumentDoingLast1,
- ArgumentDoingFiles,
- ArgumentDoingRetryDelay,
- ArgumentDoingRetryCount,
- ArgumentDoingCDashUpload,
- ArgumentDoingCDashUploadType,
- ArgumentDoingHttpHeader,
- ArgumentDoingSubmitURL,
- ArgumentDoingLast2
- };
-
- enum
- {
- cts_BUILD_ID = ct_LAST,
- cts_LAST
- };
+ bool CDashUpload = false;
+ bool FilesMentioned = false;
+ bool InternalTest = false;
+ bool PartsMentioned = false;
- bool PartsMentioned;
- std::set<cmCTest::Part> Parts;
- bool FilesMentioned;
- bool InternalTest;
- std::set<std::string> Files;
- std::string RetryCount;
- std::string RetryDelay;
- bool CDashUpload;
+ std::string BuildID;
std::string CDashUploadFile;
std::string CDashUploadType;
- std::vector<std::string> HttpHeaders;
+ std::string RetryCount;
+ std::string RetryDelay;
std::string SubmitURL;
+
+ std::vector<std::string> Files;
+ std::vector<std::string> HttpHeaders;
+ std::vector<std::string> Parts;
};
#endif
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 3a29ad3..c277db8 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -8,30 +8,29 @@
#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
+#include "cm_static_string_view.hxx"
#include <chrono>
#include <cstdlib>
#include <sstream>
-#include <vector>
-cmCTestTestCommand::cmCTestTestCommand()
+void cmCTestTestCommand::BindArguments()
{
- this->Arguments[ctt_START] = "START";
- this->Arguments[ctt_END] = "END";
- this->Arguments[ctt_STRIDE] = "STRIDE";
- this->Arguments[ctt_EXCLUDE] = "EXCLUDE";
- this->Arguments[ctt_INCLUDE] = "INCLUDE";
- this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
- this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
- this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE";
- this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP";
- this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP";
- this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
- this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
- this->Arguments[ctt_STOP_TIME] = "STOP_TIME";
- this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD";
- this->Arguments[ctt_LAST] = nullptr;
- this->Last = ctt_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("START"_s, this->Start);
+ this->Bind("END"_s, this->End);
+ this->Bind("STRIDE"_s, this->Stride);
+ this->Bind("EXCLUDE"_s, this->Exclude);
+ this->Bind("INCLUDE"_s, this->Include);
+ this->Bind("EXCLUDE_LABEL"_s, this->ExcludeLabel);
+ this->Bind("INCLUDE_LABEL"_s, this->IncludeLabel);
+ this->Bind("EXCLUDE_FIXTURE"_s, this->ExcludeFixture);
+ this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup);
+ this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup);
+ this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel);
+ this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom);
+ this->Bind("STOP_TIME"_s, this->StopTime);
+ this->Bind("TEST_LOAD"_s, this->TestLoad);
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
@@ -51,57 +50,44 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
this->CTest->SetTimeOut(timeout);
cmCTestGenericHandler* handler = this->InitializeActualHandler();
- if (this->Values[ctt_START] || this->Values[ctt_END] ||
- this->Values[ctt_STRIDE]) {
- std::ostringstream testsToRunString;
- if (this->Values[ctt_START]) {
- testsToRunString << this->Values[ctt_START];
- }
- testsToRunString << ",";
- if (this->Values[ctt_END]) {
- testsToRunString << this->Values[ctt_END];
- }
- testsToRunString << ",";
- if (this->Values[ctt_STRIDE]) {
- testsToRunString << this->Values[ctt_STRIDE];
- }
- handler->SetOption("TestsToRunInformation",
- testsToRunString.str().c_str());
+ if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) {
+ handler->SetOption(
+ "TestsToRunInformation",
+ cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str());
}
- if (this->Values[ctt_EXCLUDE]) {
- handler->SetOption("ExcludeRegularExpression", this->Values[ctt_EXCLUDE]);
+ if (!this->Exclude.empty()) {
+ handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str());
}
- if (this->Values[ctt_INCLUDE]) {
- handler->SetOption("IncludeRegularExpression", this->Values[ctt_INCLUDE]);
+ if (!this->Include.empty()) {
+ handler->SetOption("IncludeRegularExpression", this->Include.c_str());
}
- if (this->Values[ctt_EXCLUDE_LABEL]) {
+ if (!this->ExcludeLabel.empty()) {
handler->SetOption("ExcludeLabelRegularExpression",
- this->Values[ctt_EXCLUDE_LABEL]);
+ this->ExcludeLabel.c_str());
}
- if (this->Values[ctt_INCLUDE_LABEL]) {
- handler->SetOption("LabelRegularExpression",
- this->Values[ctt_INCLUDE_LABEL]);
+ if (!this->IncludeLabel.empty()) {
+ handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE]) {
+ if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE]);
+ this->ExcludeFixture.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) {
+ if (!this->ExcludeFixtureSetup.empty()) {
handler->SetOption("ExcludeFixtureSetupRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE_SETUP]);
+ this->ExcludeFixtureSetup.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) {
+ if (!this->ExcludeFixtureCleanup.empty()) {
handler->SetOption("ExcludeFixtureCleanupRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]);
+ this->ExcludeFixtureCleanup.c_str());
}
- if (this->Values[ctt_PARALLEL_LEVEL]) {
- handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]);
+ if (!this->ParallelLevel.empty()) {
+ handler->SetOption("ParallelLevel", this->ParallelLevel.c_str());
}
- if (this->Values[ctt_SCHEDULE_RANDOM]) {
- handler->SetOption("ScheduleRandom", this->Values[ctt_SCHEDULE_RANDOM]);
+ if (!this->ScheduleRandom.empty()) {
+ handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
}
- if (this->Values[ctt_STOP_TIME]) {
- this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]);
+ if (!this->StopTime.empty()) {
+ this->CTest->SetStopTime(this->StopTime);
}
// Test load is determined by: TEST_LOAD argument,
@@ -109,12 +95,12 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
// command line argument... in that order.
unsigned long testLoad;
const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
- if (this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) {
- if (!cmStrToULong(this->Values[ctt_TEST_LOAD], &testLoad)) {
+ if (!this->TestLoad.empty()) {
+ if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) {
testLoad = 0;
cmCTestLog(this->CTest, WARNING,
- "Invalid value for 'TEST_LOAD' : "
- << this->Values[ctt_TEST_LOAD] << std::endl);
+ "Invalid value for 'TEST_LOAD' : " << this->TestLoad
+ << std::endl);
}
} else if (ctestTestLoad && *ctestTestLoad) {
if (!cmStrToULong(ctestTestLoad, &testLoad)) {
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index a9ba3ab..edd21b7 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestTestCommand : public cmCTestHandlerCommand
{
public:
- cmCTestTestCommand();
-
/**
* This is a virtual constructor for the command.
*/
@@ -42,29 +40,24 @@ public:
std::string GetName() const override { return "ctest_test"; }
protected:
+ void BindArguments() override;
virtual cmCTestGenericHandler* InitializeActualHandler();
cmCTestGenericHandler* InitializeHandler() override;
- enum
- {
- ctt_BUILD = ct_LAST,
- ctt_RETURN_VALUE,
- ctt_START,
- ctt_END,
- ctt_STRIDE,
- ctt_EXCLUDE,
- ctt_INCLUDE,
- ctt_EXCLUDE_LABEL,
- ctt_INCLUDE_LABEL,
- ctt_EXCLUDE_FIXTURE,
- ctt_EXCLUDE_FIXTURE_SETUP,
- ctt_EXCLUDE_FIXTURE_CLEANUP,
- ctt_PARALLEL_LEVEL,
- ctt_SCHEDULE_RANDOM,
- ctt_STOP_TIME,
- ctt_TEST_LOAD,
- ctt_LAST
- };
+ std::string Start;
+ std::string End;
+ std::string Stride;
+ std::string Exclude;
+ std::string Include;
+ std::string ExcludeLabel;
+ std::string IncludeLabel;
+ std::string ExcludeFixture;
+ std::string ExcludeFixtureSetup;
+ std::string ExcludeFixtureCleanup;
+ std::string ParallelLevel;
+ std::string ScheduleRandom;
+ std::string StopTime;
+ std::string TestLoad;
};
#endif
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 65dc921..673eb9a 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -7,14 +7,11 @@
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <vector>
-
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
{
- if (this->Values[ct_SOURCE]) {
+ if (!this->Source.empty()) {
this->CTest->SetCTestConfiguration(
- "SourceDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h
index 5b0e07e..a4798a5 100644
--- a/Source/CTest/cmCTestUpdateCommand.h
+++ b/Source/CTest/cmCTestUpdateCommand.h
@@ -23,8 +23,6 @@ class cmCTestGenericHandler;
class cmCTestUpdateCommand : public cmCTestHandlerCommand
{
public:
- cmCTestUpdateCommand() {}
-
/**
* This is a virtual constructor for the command.
*/
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index 59fbf37..9180821 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -2,61 +2,45 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadCommand.h"
+#include <set>
#include <sstream>
#include <vector>
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestUploadHandler.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSystemTools.h"
+#include "cm_static_string_view.hxx"
-cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
-{
- cmCTestUploadHandler* handler = this->CTest->GetUploadHandler();
- handler->Initialize();
- handler->SetFiles(this->Files);
- handler->SetQuiet(this->Quiet);
- return handler;
-}
-
-bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestUploadCommand::BindArguments()
{
- if (arg == "FILES") {
- this->ArgumentDoing = ArgumentDoingFiles;
- return true;
- }
- if (arg == "QUIET") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->Quiet = true;
- return true;
- }
- if (arg == "CAPTURE_CMAKE_ERROR") {
- this->ArgumentDoing = ArgumentDoingCaptureCMakeError;
- return true;
- }
- return false;
+ this->Bind("FILES"_s, this->Files);
+ this->Bind("QUIET"_s, this->Quiet);
+ this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg)
+void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
{
- if (this->ArgumentDoing == ArgumentDoingCaptureCMakeError) {
- this->Values[ct_CAPTURE_CMAKE_ERROR] = arg.c_str();
- return true;
- }
- if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg)) {
- this->Files.insert(arg);
+ cmEraseIf(this->Files, [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return true;
}
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
return false;
- }
+ });
+}
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
+cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
+{
+ cmCTestUploadHandler* handler = this->CTest->GetUploadHandler();
+ handler->Initialize();
+ handler->SetFiles(
+ std::set<std::string>(this->Files.begin(), this->Files.end()));
+ handler->SetQuiet(this->Quiet);
+ return handler;
}
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index 39314f2..f78f0ec 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -8,9 +8,9 @@
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
-#include <set>
#include <string>
#include <utility>
+#include <vector>
#include <cm/memory>
@@ -41,22 +41,12 @@ public:
*/
std::string GetName() const override { return "ctest_upload"; }
- using Superclass = cmCTestHandlerCommand;
-
protected:
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const&) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool CheckArgumentKeyword(std::string const& arg) override;
- bool CheckArgumentValue(std::string const& arg) override;
-
- enum
- {
- ArgumentDoingFiles = Superclass::ArgumentDoingLast1,
- ArgumentDoingCaptureCMakeError,
- ArgumentDoingLast2
- };
-
- std::set<std::string> Files;
+ std::vector<std::string> Files;
};
#endif
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 35db6a4..94de851 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -5,6 +5,7 @@
#include <sstream>
#include <unordered_set>
+#include "cmCheckCustomOutputs.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
@@ -16,9 +17,6 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
-static bool cmAddCustomCommandCommandCheckOutputs(
- const std::vector<std::string>& outputs, cmExecutionStatus& status);
-
bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -307,9 +305,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
}
// Make sure the output names and locations are safe.
- if (!cmAddCustomCommandCommandCheckOutputs(output, status) ||
- !cmAddCustomCommandCommandCheckOutputs(outputs, status) ||
- !cmAddCustomCommandCommandCheckOutputs(byproducts, status)) {
+ if (!cmCheckCustomOutputs(output, "OUTPUT", status) ||
+ !cmCheckCustomOutputs(outputs, "OUTPUTS", status) ||
+ !cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
return false;
}
@@ -322,8 +320,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
// No command for this output exists.
status.SetError(
- cmStrCat("given APPEND option with output\n\"", output[0],
- "\"\nwhich is not already a custom command output."));
+ cmStrCat("given APPEND option with output\n ", output[0],
+ "\nwhich is not already a custom command output."));
return false;
}
@@ -387,29 +385,3 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
return true;
}
-
-bool cmAddCustomCommandCommandCheckOutputs(
- const std::vector<std::string>& outputs, cmExecutionStatus& status)
-{
- cmMakefile& mf = status.GetMakefile();
- for (std::string const& o : outputs) {
- // Make sure the file will not be generated into the source
- // directory during an out of source build.
- if (!mf.CanIWriteThisFile(o)) {
- std::string e = "attempted to have a file \"" + o +
- "\" in a source directory as an output of custom command.";
- status.SetError(e);
- cmSystemTools::SetFatalErrorOccured();
- return false;
- }
-
- // Make sure the output file name has no invalid characters.
- std::string::size_type pos = o.find_first_of("#<>");
- if (pos != std::string::npos) {
- status.SetError(cmStrCat("called with OUTPUT containing a \"", o[pos],
- "\". This character is not allowed."));
- return false;
- }
- }
- return true;
-}
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 9fd1234..b580c43 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -4,6 +4,7 @@
#include <utility>
+#include "cmCheckCustomOutputs.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
@@ -205,6 +206,11 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
return false;
}
+ // Make sure the byproduct names and locations are safe.
+ if (!cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
+ return false;
+ }
+
// Add the utility target to the makefile.
bool escapeOldStyle = !verbatim;
cmTarget* target = mf.AddUtilityCommand(
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index 751d117..4c87177 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -61,10 +61,14 @@ void Instance::Bind(MultiStringList& val)
void Instance::Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue)
+ std::vector<std::string>* keywordsMissingValue,
+ std::vector<std::string>* parsedKeywords)
{
auto const it = this->Bindings.Find(arg);
if (it != this->Bindings.end()) {
+ if (parsedKeywords != nullptr) {
+ parsedKeywords->emplace_back(arg);
+ }
it->second(*this, result);
if (this->ExpectValue && keywordsMissingValue != nullptr) {
keywordsMissingValue->emplace_back(arg);
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index b6798bc..9be2488 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -45,7 +45,8 @@ public:
void Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue);
+ std::vector<std::string>* keywordsMissingValue,
+ std::vector<std::string>* parsedKeywords);
private:
ActionMap const& Bindings;
@@ -79,21 +80,25 @@ public:
template <typename Range>
void Parse(Result& result, Range const& args,
std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr) const
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
- instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue);
+ instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
}
}
template <typename Range>
Result Parse(Range const& args,
std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr) const
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
{
Result result;
- this->Parse(result, args, unparsedArguments, keywordsMissingValue);
+ this->Parse(result, args, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
return result;
}
@@ -116,11 +121,13 @@ public:
template <typename Range>
void Parse(Range const& args,
std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr) const
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
- instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue);
+ instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
}
}
diff --git a/Source/cmCheckCustomOutputs.cxx b/Source/cmCheckCustomOutputs.cxx
new file mode 100644
index 0000000..7645c88
--- /dev/null
+++ b/Source/cmCheckCustomOutputs.cxx
@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCheckCustomOutputs.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+ cm::string_view keyword, cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+
+ for (std::string const& o : outputs) {
+ // Make sure the file will not be generated into the source
+ // directory during an out of source build.
+ if (!mf.CanIWriteThisFile(o)) {
+ status.SetError(
+ cmStrCat("attempted to have a file\n ", o,
+ "\nin a source directory as an output of custom command."));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ // Make sure the output file name has no invalid characters.
+ std::string::size_type pos = o.find_first_of("#<>");
+ if (pos != std::string::npos) {
+ status.SetError(cmStrCat("called with ", keyword, " containing a \"",
+ o[pos], "\". This character is not allowed."));
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/Source/cmCheckCustomOutputs.h b/Source/cmCheckCustomOutputs.h
new file mode 100644
index 0000000..7c4b3fe
--- /dev/null
+++ b/Source/cmCheckCustomOutputs.h
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCheckCustomOutputs_h
+#define cmCheckCustomOutputs_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cm/string_view>
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+ cm::string_view keyword, cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 7faafba..0915189 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -45,6 +45,14 @@ static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
{ "", "", "", "", 0 }
};
+namespace {
+std::string GetSLNFile(cmLocalGenerator* root)
+{
+ return cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+ root->GetProjectName(), ".sln");
+}
+}
+
cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
cmake* cm, std::string const& platformInGeneratorName)
: cmGlobalVisualStudioGenerator(cm, platformInGeneratorName)
@@ -286,8 +294,10 @@ void cmGlobalVisualStudio7Generator::Generate()
this->OutputSLNFile();
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
- if (!cmSystemTools::GetErrorOccuredFlag()) {
- this->CallVisualStudioMacro(MacroReload);
+ if (!cmSystemTools::GetErrorOccuredFlag() &&
+ !this->LocalGenerators.empty()) {
+ this->CallVisualStudioMacro(MacroReload,
+ GetSLNFile(this->LocalGenerators[0]));
}
}
@@ -298,8 +308,7 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile(
return;
}
this->CurrentProject = root->GetProjectName();
- std::string fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
- root->GetProjectName(), ".sln");
+ std::string fname = GetSLNFile(root);
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
if (!fout) {
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 108a44f..7a564ed 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -288,11 +288,10 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
}
void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
- MacroName m, const char* vsSolutionFile)
+ MacroName m, const std::string& vsSolutionFile)
{
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
- cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
std::string dir = this->GetUserMacrosDirectory();
// Only really try to call the macro if:
@@ -307,27 +306,18 @@ void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
if (cmSystemTools::FileExists(macrosFile.c_str()) &&
IsVisualStudioMacrosFileRegistered(
macrosFile, this->GetUserMacrosRegKeyBase(), nextSubkeyName)) {
- std::string topLevelSlnName;
- if (vsSolutionFile) {
- topLevelSlnName = vsSolutionFile;
- } else {
- topLevelSlnName =
- cmStrCat(mf->GetCurrentBinaryDirectory(), '/',
- this->LocalGenerators[0]->GetProjectName(), ".sln");
- }
-
if (m == MacroReload) {
std::vector<std::string> filenames;
this->GetFilesReplacedDuringGenerate(filenames);
if (!filenames.empty()) {
std::string projects = cmJoin(filenames, ";");
cmCallVisualStudioMacro::CallMacro(
- topLevelSlnName, CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
+ vsSolutionFile, CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
this->GetCMakeInstance()->GetDebugOutput());
}
} else if (m == MacroStop) {
cmCallVisualStudioMacro::CallMacro(
- topLevelSlnName, CMAKE_VSMACROS_STOP_MACRONAME, "",
+ vsSolutionFile, CMAKE_VSMACROS_STOP_MACRONAME, "",
this->GetCMakeInstance()->GetDebugOutput());
}
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index bd615ec..4f2007f 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -90,7 +90,7 @@ public:
* Call the ReloadProjects macro if necessary based on
* GetFilesReplacedDuringGenerate results.
*/
- void CallVisualStudioMacro(MacroName m, const char* vsSolutionFile = 0);
+ void CallVisualStudioMacro(MacroName m, const std::string& vsSolutionFile);
// return true if target is fortran only
bool TargetIsFortranOnly(const cmGeneratorTarget* gt);
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 34aac49..d28905a 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1466,6 +1466,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
// output files for custom command
std::stringstream outputs;
+ bool symbolic = false;
{
const char* sep = "";
for (std::string const& o : ccg.GetOutputs()) {
@@ -1473,6 +1474,12 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
ConvertToWindowsSlash(out);
outputs << sep << out;
sep = ";";
+ if (!symbolic) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(
+ o, cmSourceFileLocationKind::Known)) {
+ symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ }
+ }
}
}
if (this->ProjectType == csproj) {
@@ -1482,7 +1489,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
outputs.str(), comment);
} else {
this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
- outputs.str(), comment);
+ outputs.str(), comment, symbolic);
}
}
}
@@ -1490,7 +1497,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
Elem& e2, std::string const& config, std::string const& script,
std::string const& additional_inputs, std::string const& outputs,
- std::string const& comment)
+ std::string const& comment, bool symbolic)
{
const std::string cond = this->CalcCondition(config);
e2.WritePlatformConfigTag("Message", cond, comment);
@@ -1502,6 +1509,13 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
// VS >= 11 let us turn off linking of custom command outputs.
e2.WritePlatformConfigTag("LinkObjects", cond, "false");
}
+ if (symbolic &&
+ this->LocalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS16) {
+ // VS >= 16.4 warn if outputs are not created, but one of our
+ // outputs is marked SYMBOLIC and not expected to be created.
+ e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
+ }
}
void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 4dd92eb..a18a33d 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -142,7 +142,7 @@ private:
std::string const& script,
std::string const& additional_inputs,
std::string const& outputs,
- std::string const& comment);
+ std::string const& comment, bool symbolic);
void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
std::string const& commandName,
std::string const& script,
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 96d903e..b96eedb 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1751,7 +1751,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
cmGlobalVisualStudioGenerator* gg =
static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop,
- this->VSSolutionFile.c_str());
+ this->VSSolutionFile);
}
#endif
return ret;
diff --git a/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description1.cmake.in b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description1.cmake.in
index 74d816c..67b108b 100644
--- a/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description1.cmake.in
+++ b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description1.cmake.in
@@ -15,8 +15,9 @@ set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
# overriding previous descriptions
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "main description")
-set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION "applications_description")
-set(CPACK_COMPONENT_HEADERS_DESCRIPTION "headers_description")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "main description") # This become a summary line (the first one) of all descriptions
+set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION "applications_description")
+set(CPACK_COMPONENT_HEADERS_DESCRIPTION "headers_description")
# libraries does not have any description and should inherit from CPACK_PACKAGE_DESCRIPTION_SUMMARY
+# plus content of the `CPACK_PACKAGE_DESCRIPTION_FILE`.
unset(CPACK_COMPONENT_LIBRARIES_DESCRIPTION)
diff --git a/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description2.cmake.in b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description2.cmake.in
index cda79bc..d877325 100644
--- a/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description2.cmake.in
+++ b/Tests/CPackComponentsDEB/MyLibCPackConfig-components-description2.cmake.in
@@ -15,12 +15,12 @@ set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
#set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
# overriding previous descriptions
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "main description 2")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "main description 2")
-# Components do not have any description
+# Components do not have any description.
+# So, content of `CPACK_PACKAGE_DESCRIPTION_FILE` gonna used
+# after summary line.
unset(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION)
unset(CPACK_COMPONENT_HEADERS_DESCRIPTION)
-unset(CPACK_COMPONENT_LIBRARIES_DESCRIPTION)
-
-set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "library description")
+set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "library description")
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
index f74137c..86a74b2 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake
@@ -48,26 +48,26 @@ if(DPKGDEB_EXECUTABLE)
DPKGDEB_OUTPUT "${dpkg_output}"
METAENTRY "Package:")
- dpkgdeb_return_specific_metaentry(dpkg_description
- DPKGDEB_OUTPUT "${dpkg_output}"
- METAENTRY "Description:")
+ get_package_description("${dpkg_output}" dpkg_description)
message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'")
if(dpkg_package_name STREQUAL "mylib-applications")
- if(NOT "${dpkg_description}" STREQUAL "applications_description")
+ set(expected_description "main description\n applications_description")
+ if(NOT dpkg_description STREQUAL expected_description)
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description")
+ "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`")
endif()
elseif(dpkg_package_name STREQUAL "mylib-headers")
- if(NOT dpkg_description STREQUAL "headers_description")
+ set(expected_description "main description\n headers_description")
+ if(NOT dpkg_description STREQUAL expected_description)
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description")
+ "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`")
endif()
elseif(dpkg_package_name STREQUAL "mylib-libraries")
- if(NOT dpkg_description STREQUAL "main description")
+ if(NOT dpkg_description MATCHES "main description\n.*")
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'")
+ "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` =~ `main description.*`")
endif()
else()
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
index 241dda5..d53c73d 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake
@@ -48,26 +48,20 @@ if(DPKGDEB_EXECUTABLE)
DPKGDEB_OUTPUT "${dpkg_output}"
METAENTRY "Package:")
- dpkgdeb_return_specific_metaentry(dpkg_description
- DPKGDEB_OUTPUT "${dpkg_output}"
- METAENTRY "Description:")
+ get_package_description("${dpkg_output}" dpkg_description)
message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'")
- if(dpkg_package_name STREQUAL "mylib-applications")
- if(NOT dpkg_description STREQUAL "main description 2")
- set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description")
- endif()
- elseif(dpkg_package_name STREQUAL "mylib-headers")
- if(NOT dpkg_description STREQUAL "main description 2")
+ if(dpkg_package_name STREQUAL "mylib-applications" OR dpkg_package_name STREQUAL "mylib-headers")
+ if(NOT dpkg_description MATCHES "main description 2\n.*")
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description")
+ "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` =~ `main description 2`")
endif()
elseif(dpkg_package_name STREQUAL "mylib-libraries")
- if(NOT dpkg_description STREQUAL "library description")
+ set(expected_description "main description 2\n library description")
+ if(NOT dpkg_description STREQUAL expected_description)
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
- "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'")
+ "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: `${dpkg_description}` != `${expected_description}`")
endif()
else()
set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all}
diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
index 2093e7e..b172da2 100644
--- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake
@@ -200,4 +200,29 @@ function(dpkgdeb_return_specific_metaentry output)
endif()
endfunction()
+function(get_package_description DPKG_OUTPUT RESULT_VAR)
+ string(UUID uuid NAMESPACE 00000000-0000-0000-0000-000000000000 TYPE SHA1)
+ string(REPLACE ";" "${uuid}" DPKG_OUTPUT "${DPKG_OUTPUT}")
+ string(REPLACE "\n" ";" DPKG_OUTPUT "${DPKG_OUTPUT}")
+
+ unset(_actual_description)
+ set(_parse_description FALSE)
+ foreach(_line IN LISTS DPKG_OUTPUT)
+ if(_line MATCHES " Description:.*")
+ set(_parse_description TRUE)
+ string(REPLACE " Description: " "" _line "${_line}")
+ list(APPEND _actual_description "${_line}")
+ elseif(_parse_description)
+ if(_line MATCHES " [A-Z][A-Za-z\-]+: .*")
+ set(_parse_description FALSE)
+ else()
+ list(APPEND _actual_description "${_line}")
+ endif()
+ endif()
+ endforeach()
+ list(JOIN _actual_description "\n" _actual_description)
+
+ set(${RESULT_VAR} "${_actual_description}" PARENT_SCOPE)
+endfunction()
+
cmake_policy(POP)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index c663484..026baa7 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -167,7 +167,7 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(CompilerChange)
endif()
add_RunCMake_test(CompilerNotFound)
-add_RunCMake_test(Configure)
+add_RunCMake_test(Configure -DMSVC_IDE=${MSVC_IDE})
add_RunCMake_test(DisallowedCommands)
add_RunCMake_test(ExternalData)
add_RunCMake_test(FeatureSummary)
@@ -510,6 +510,7 @@ set(cpack_tests
DEB.TIMESTAMPS
DEB.MD5SUMS
DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY
+ DEB.DEB_DESCRIPTION
RPM.CUSTOM_BINARY_SPEC_FILE
RPM.CUSTOM_NAMES
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 8e98961..b0b7a99 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -39,3 +39,10 @@ run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;inval
if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode")
run_cpack_test(CPACK_INSTALL_CMAKE_CONFIGURATIONS "ZIP" false "MONOLITHIC")
endif()
+run_cpack_test_subtests(
+ DEB_DESCRIPTION
+ "CPACK_DEBIAN_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION;CPACK_PACKAGE_DESCRIPTION_FILE"
+ "DEB.DEB_DESCRIPTION"
+ false
+ "MONOLITHIC;COMPONENT"
+)
diff --git a/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/ExpectedFiles.cmake
new file mode 100644
index 0000000..39f18a3
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/ExpectedFiles.cmake
@@ -0,0 +1,16 @@
+set(EXPECTED_FILES_COUNT_MONOLITHIC "1")
+set(EXPECTED_FILES_COUNT_COMPONENT "2")
+set(EXPECTED_FILES_COUNT "${EXPECTED_FILES_COUNT_${PACKAGING_TYPE}}")
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ set(EXPECTED_FILE_1 "deb_description-0.1.1-*-satu.deb")
+ set(EXPECTED_FILE_2 "deb_description-0.1.1-*-dua.deb")
+ set(EXPECTED_FILE_CONTENT_1_LIST "/satu;/satu/CMakeLists.txt")
+ set(EXPECTED_FILE_CONTENT_2_LIST "/dua;/dua/CMakeLists.txt")
+
+elseif(PACKAGING_TYPE STREQUAL "MONOLITHIC")
+ set(EXPECTED_FILE_CONTENT_1_LIST "/dua;/dua/CMakeLists.txt;/satu;/satu/CMakeLists.txt")
+
+endif()
+
+# kate: indent-width 2;
diff --git a/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake
new file mode 100644
index 0000000..e9ac13a
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/VerifyResult.cmake
@@ -0,0 +1,65 @@
+function(checkPackageDescription FILE EXPECTED_DESCRIPTION)
+ getPackageInfo("${FILE}" "_file_info")
+ string(UUID uuid NAMESPACE 00000000-0000-0000-0000-000000000000 TYPE SHA1)
+ string(REPLACE ";" "${uuid}" _file_info "${_file_info}")
+ string(REPLACE ";" "${uuid}" EXPECTED_DESCRIPTION "${EXPECTED_DESCRIPTION}")
+ string(REPLACE "\n" ";" _file_info "${_file_info}")
+
+ set(_actual_description)
+ set(_parse_description FALSE)
+ foreach(_line IN LISTS _file_info)
+ if(_line MATCHES " Description:.*")
+ set(_parse_description TRUE)
+ list(APPEND _actual_description "${_line}")
+ elseif(_parse_description)
+ if(_line MATCHES " [A-Z][A-Za-z\-]+: .*")
+ set(_parse_description FALSE)
+ else()
+ list(APPEND _actual_description "${_line}")
+ endif()
+ endif()
+ endforeach()
+ list(JOIN _actual_description "\n" _actual_description)
+
+ if(NOT _actual_description STREQUAL EXPECTED_DESCRIPTION)
+ set(_error "---[BEGIN Expected description]---\n${EXPECTED_DESCRIPTION}---[END Expected description]---\n")
+ string(APPEND _error "---[BEGIN Actual description]---\n${_actual_description}---[END Actual description]---\n")
+ string(REPLACE "${uuid}" ";" _error "${_error}")
+ message(FATAL_ERROR "${_error}")
+ endif()
+endfunction()
+
+# ALERT The output of `dpkg -I *.deb` indented by one space
+set(_expected_description [[ Description: This is the summary line
+ This is the Debian package multiline description.
+ .
+ It must be formatted properly! Otherwise, the result `*.deb`
+ package become broken and cant be installed!
+ .
+ It may contains `;` characters (even like this `;;;;`). Example:
+ .
+ - one;
+ - two;
+ - three;
+ .
+ ... and they are properly handled by the automatic description formatter!
+ .
+ See also: https://www.debian.org/doc/debian-policy/ch-controlfields.html#description]])
+
+# ATTENTION The code in `cmCPackGenerator.cxx` to read `CPACK_PACKAGE_DESCRIPTION_FILE`
+# has a BUG: it appends the `\n` character to every line of the
+# input, even if there was no EOL (e.g. at the last line of the file).
+# That is WHY for this sub-test the one more pre-formatted "empty"
+# line required!
+# NOTE For component based installers content of the file gonna read by
+# `CPackDeb` module and the `file(READ...)` command so no the mentioned
+# workaround required!
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_PACKAGE_DESCRIPTION_FILE" AND PACKAGING_TYPE STREQUAL "MONOLITHIC")
+ string(APPEND _expected_description "\n ." )
+endif()
+
+foreach(_file_no RANGE 1 ${EXPECTED_FILES_COUNT})
+ checkPackageDescription("${FOUND_FILE_${_file_no}}" "${_expected_description}")
+endforeach()
+
+# kate: indent-width 2;
diff --git a/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/test.cmake b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/test.cmake
new file mode 100644
index 0000000..ce3f651
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEB_DESCRIPTION/test.cmake
@@ -0,0 +1,45 @@
+install(FILES CMakeLists.txt DESTINATION satu COMPONENT satu)
+install(FILES CMakeLists.txt DESTINATION dua COMPONENT dua)
+
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "This is the summary line")
+set(_description [[This is the Debian package multiline description.
+
+It must be formatted properly! Otherwise, the result `*.deb`
+package become broken and cant be installed!
+
+It may contains `;` characters (even like this `;;;;`). Example:
+
+ - one;
+ - two;
+ - three;
+
+... and they are properly handled by the automatic description formatter!
+
+See also: https://www.debian.org/doc/debian-policy/ch-controlfields.html#description]])
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_DEBIAN_PACKAGE_DESCRIPTION")
+ if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ set(CPACK_DEBIAN_SATU_DESCRIPTION "${_description}")
+ set(CPACK_DEBIAN_DUA_DESCRIPTION "${_description}")
+ else()
+ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${_description}")
+ endif()
+
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_PACKAGE_DESCRIPTION")
+ # NOTE Documented fallback variable
+ if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ set(CPACK_COMPONENT_SATU_DESCRIPTION "${_description}")
+ set(CPACK_COMPONENT_DUA_DESCRIPTION "${_description}")
+ else()
+ set(CPACK_PACKAGE_DESCRIPTION "${_description}")
+ endif()
+
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "CPACK_PACKAGE_DESCRIPTION_FILE")
+ # NOTE Getting the description from the file
+ set(_file "${CMAKE_CURRENT_BINARY_DIR}/description.txt")
+ file(WRITE "${_file}" "${_description}")
+ set(CPACK_PACKAGE_DESCRIPTION_FILE "${_file}")
+
+endif()
+
+# kate: indent-width 2;
diff --git a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake
index b4bdb61..c47b40e 100644
--- a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake
@@ -8,6 +8,9 @@ endfunction()
if(GENERATOR_TYPE STREQUAL "DEB")
set(name_ "Package")
set(group_ "Section")
+ # NOTE For a Debian package the first line of the `Description`
+ # field is generated by CMake and gonna be ignored
+ set(ignore_rest_cond_ ".*\n")
elseif(GENERATOR_TYPE STREQUAL "RPM")
set(name_ "Name")
set(group_ "Group")
@@ -33,6 +36,6 @@ if(GENERATOR_TYPE STREQUAL "RPM")
endif()
# check package description
-checkPackageInfo_("description" "${FOUND_FILE_1}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_1")
-checkPackageInfo_("description" "${FOUND_FILE_2}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_2")
-checkPackageInfo_("description" "${FOUND_FILE_3}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_3")
+checkPackageInfo_("description" "${FOUND_FILE_1}" ".*Description${whitespaces_}:${ignore_rest_cond_}${whitespaces_}Description for pkg_1")
+checkPackageInfo_("description" "${FOUND_FILE_2}" ".*Description${whitespaces_}:${ignore_rest_cond_}${whitespaces_}Description for pkg_2")
+checkPackageInfo_("description" "${FOUND_FILE_3}" ".*Description${whitespaces_}:${ignore_rest_cond_}${whitespaces_}Description for pkg_3")
diff --git a/Tests/RunCMake/Configure/RerunCMake-build3-result.txt b/Tests/RunCMake/Configure/RerunCMake-build3-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/Configure/RerunCMake-build3-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/Configure/RerunCMake-build3-stdout.txt b/Tests/RunCMake/Configure/RerunCMake-build3-stdout.txt
new file mode 100644
index 0000000..dde2ea6
--- /dev/null
+++ b/Tests/RunCMake/Configure/RerunCMake-build3-stdout.txt
@@ -0,0 +1 @@
+Rerun error 3
diff --git a/Tests/RunCMake/Configure/RerunCMake-build4-result.txt b/Tests/RunCMake/Configure/RerunCMake-build4-result.txt
new file mode 100644
index 0000000..d197c91
--- /dev/null
+++ b/Tests/RunCMake/Configure/RerunCMake-build4-result.txt
@@ -0,0 +1 @@
+[^0]
diff --git a/Tests/RunCMake/Configure/RerunCMake-build4-stdout.txt b/Tests/RunCMake/Configure/RerunCMake-build4-stdout.txt
new file mode 100644
index 0000000..b8727e1
--- /dev/null
+++ b/Tests/RunCMake/Configure/RerunCMake-build4-stdout.txt
@@ -0,0 +1 @@
+Rerun error 4
diff --git a/Tests/RunCMake/Configure/RerunCMake.cmake b/Tests/RunCMake/Configure/RerunCMake.cmake
index 5a561bf..c0b0798 100644
--- a/Tests/RunCMake/Configure/RerunCMake.cmake
+++ b/Tests/RunCMake/Configure/RerunCMake.cmake
@@ -9,3 +9,9 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${depend})
file(READ ${depend} content)
file(WRITE ${output} "${content}")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS RerunCMake.txt)
+
+set(error ${CMAKE_CURRENT_BINARY_DIR}/CustomCMakeError.txt)
+if(EXISTS ${error})
+ file(READ ${error} content)
+ message(FATAL_ERROR "Rerun error ${content}")
+endif()
diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake
index 4a135be..76d843c 100644
--- a/Tests/RunCMake/Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake
@@ -14,6 +14,7 @@ set(input "${RunCMake_TEST_BINARY_DIR}/CustomCMakeInput.txt")
set(stamp "${RunCMake_TEST_BINARY_DIR}/CustomCMakeStamp.txt")
set(depend "${RunCMake_TEST_BINARY_DIR}/CustomCMakeDepend.txt")
set(output "${RunCMake_TEST_BINARY_DIR}/CustomCMakeOutput.txt")
+set(error "${RunCMake_TEST_BINARY_DIR}/CustomCMakeError.txt")
file(WRITE "${input}" "1")
file(WRITE "${depend}" "1")
run_cmake(RerunCMake)
@@ -22,6 +23,22 @@ file(WRITE "${input}" "2")
run_cmake_command(RerunCMake-build1 ${CMAKE_COMMAND} --build .)
file(WRITE "${depend}" "2")
run_cmake_command(RerunCMake-build2 ${CMAKE_COMMAND} --build .)
+execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) # handle 1s resolution
+file(WRITE "${depend}" "3")
+file(WRITE "${error}" "3")
+set(RunCMake_TEST_OUTPUT_MERGE 1)
+run_cmake_command(RerunCMake-build3 ${CMAKE_COMMAND} --build .)
+if(MSVC_IDE)
+ # Make sure that for Visual Studio the error occurs from within the build
+ # system.
+ file(REMOVE "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/generate.stamp.list")
+ file(WRITE "${error}" "4")
+ # With Visual Studio the error must be on stdout, otherwise the error was not
+ # emitted by ZERO_CHECK.
+ set(RunCMake_TEST_OUTPUT_MERGE 0)
+ run_cmake_command(RerunCMake-build4 ${CMAKE_COMMAND} --build .)
+endif()
+unset(RunCMake_TEST_OUTPUT_MERGE)
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
diff --git a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
index cd542d8..b7ee23a 100644
--- a/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
+++ b/Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt
@@ -1,7 +1,7 @@
CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
add_custom_command given APPEND option with output
- .*RunCMake/add_custom_command/AppendNotOutput-build/out.*
+ .*RunCMake/add_custom_command/AppendNotOutput-build/out
which is not already a custom command output.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/add_custom_command/BadByproduct-result.txt b/Tests/RunCMake/add_custom_command/BadByproduct-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadByproduct-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt b/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt
new file mode 100644
index 0000000..086e397
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadByproduct-stderr.txt
@@ -0,0 +1,36 @@
+CMake Error at BadByproduct.cmake:2 \(add_custom_command\):
+ add_custom_command called with BYPRODUCTS containing a "#". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:3 \(add_custom_command\):
+ add_custom_command called with BYPRODUCTS containing a "<". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:4 \(add_custom_command\):
+ add_custom_command called with BYPRODUCTS containing a ">". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:5 \(add_custom_command\):
+ add_custom_command called with BYPRODUCTS containing a "<". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:6 \(add_custom_command\):
+ add_custom_command attempted to have a file
+
+ .*RunCMake/add_custom_command/f
+
+ in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/BadByproduct.cmake b/Tests/RunCMake/add_custom_command/BadByproduct.cmake
new file mode 100644
index 0000000..91bca52
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadByproduct.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_command(OUTPUT a BYPRODUCTS "a#")
+add_custom_command(OUTPUT b BYPRODUCTS "a<")
+add_custom_command(OUTPUT c BYPRODUCTS "a>")
+add_custom_command(OUTPUT d BYPRODUCTS "$<CONFIG>/#")
+add_custom_command(OUTPUT e BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/f)
diff --git a/Tests/RunCMake/add_custom_command/BadOutput-result.txt b/Tests/RunCMake/add_custom_command/BadOutput-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadOutput-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt b/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt
new file mode 100644
index 0000000..731e58d
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadOutput-stderr.txt
@@ -0,0 +1,36 @@
+CMake Error at BadOutput.cmake:2 \(add_custom_command\):
+ add_custom_command called with OUTPUT containing a "#". This character is
+ not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:3 \(add_custom_command\):
+ add_custom_command called with OUTPUT containing a "<". This character is
+ not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:4 \(add_custom_command\):
+ add_custom_command called with OUTPUT containing a ">". This character is
+ not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:5 \(add_custom_command\):
+ add_custom_command called with OUTPUT containing a "<". This character is
+ not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadOutput.cmake:6 \(add_custom_command\):
+ add_custom_command attempted to have a file
+
+ .*RunCMake/add_custom_command/e
+
+ in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/BadOutput.cmake b/Tests/RunCMake/add_custom_command/BadOutput.cmake
new file mode 100644
index 0000000..6875fe9
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/BadOutput.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_command(OUTPUT "a#" COMMAND a)
+add_custom_command(OUTPUT "a<" COMMAND b)
+add_custom_command(OUTPUT "a>" COMMAND c)
+add_custom_command(OUTPUT "$<CONFIG>/#" COMMAND d)
+add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/e COMMAND f)
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 270df2f..96642fa 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -4,6 +4,8 @@ run_cmake(AppendLiteralQuotes)
run_cmake(AppendNoOutput)
run_cmake(AppendNotOutput)
run_cmake(BadArgument)
+run_cmake(BadByproduct)
+run_cmake(BadOutput)
run_cmake(GeneratedProperty)
run_cmake(LiteralQuotes)
run_cmake(NoArguments)
diff --git a/Tests/RunCMake/add_custom_target/BadByproduct-result.txt b/Tests/RunCMake/add_custom_target/BadByproduct-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadByproduct-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt b/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt
new file mode 100644
index 0000000..0f58550
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadByproduct-stderr.txt
@@ -0,0 +1,36 @@
+CMake Error at BadByproduct.cmake:2 \(add_custom_target\):
+ add_custom_target called with BYPRODUCTS containing a "#". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:3 \(add_custom_target\):
+ add_custom_target called with BYPRODUCTS containing a "<". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:4 \(add_custom_target\):
+ add_custom_target called with BYPRODUCTS containing a ">". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:5 \(add_custom_target\):
+ add_custom_target called with BYPRODUCTS containing a "<". This character
+ is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+
+
+CMake Error at BadByproduct.cmake:6 \(add_custom_target\):
+ add_custom_target attempted to have a file
+
+ .*RunCMake/add_custom_target/j
+
+ in a source directory as an output of custom command.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_target/BadByproduct.cmake b/Tests/RunCMake/add_custom_target/BadByproduct.cmake
new file mode 100644
index 0000000..963d641
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/BadByproduct.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+add_custom_target(a BYPRODUCTS "a#" COMMAND b)
+add_custom_target(c BYPRODUCTS "a<" COMMAND d)
+add_custom_target(e BYPRODUCTS "a>" COMMAND f)
+add_custom_target(g BYPRODUCTS "$<CONFIG>/#" COMMAND h)
+add_custom_target(i BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/j COMMAND k)
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index 49c7d3e..f5d5dd2 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -1,11 +1,12 @@
include(RunCMake)
-run_cmake(CommandExpandsEmpty)
-run_cmake(GeneratedProperty)
-run_cmake(NoArguments)
+run_cmake(BadByproduct)
run_cmake(BadTargetName)
run_cmake(ByproductsNoCommand)
+run_cmake(CommandExpandsEmpty)
+run_cmake(GeneratedProperty)
run_cmake(LiteralQuotes)
+run_cmake(NoArguments)
run_cmake(UsesTerminalNoCommand)
function(run_TargetOrder)
diff --git a/bootstrap b/bootstrap
index e7b06b4..1f5f066 100755
--- a/bootstrap
+++ b/bootstrap
@@ -278,6 +278,7 @@ CMAKE_CXX_SOURCES="\
cmCMakePolicyCommand \
cmCPackPropertiesGenerator \
cmCacheManager \
+ cmCheckCustomOutputs \
cmCommand \
cmCommandArgumentParserHelper \
cmCommands \