diff options
25 files changed, 734 insertions, 438 deletions
diff --git a/Help/command/cmake_parse_arguments.rst b/Help/command/cmake_parse_arguments.rst new file mode 100644 index 0000000..6206611 --- /dev/null +++ b/Help/command/cmake_parse_arguments.rst @@ -0,0 +1,85 @@ +cmake_parse_arguments +--------------------- + +``cmake_parse_arguments`` is intended to be used in macros or functions for +parsing the arguments given to that macro or function. It processes the +arguments and defines a set of variables which hold the values of the +respective options. + +:: + + cmake_parse_arguments(<prefix> <options> <one_value_keywords> + <multi_value_keywords> args...) + + +The ``<options>`` argument contains all options for the respective macro, +i.e. keywords which can be used when calling the macro without any value +following, like e.g. the ``OPTIONAL`` keyword of the :command:`install` +command. + +The ``<one_value_keywords>`` argument contains all keywords for this macro +which are followed by one value, like e.g. ``DESTINATION`` keyword of the +:command:`install` command. + +The ``<multi_value_keywords>`` argument contains all keywords for this +macro which can be followed by more than one value, like e.g. the +``TARGETS`` or ``FILES`` keywords of the :command:`install` command. + +.. note:: + + All keywords shall be unique. I.e. every keyword shall only be specified + once in either ``<options>``, ``<one_value_keywords>`` or + ``<multi_value_keywords>``. A warning will be emitted if uniqueness is + violated. + +When done, ``cmake_parse_arguments`` will have defined for each of the +keywords listed in ``<options>``, ``<one_value_keywords>`` and +``<multi_value_keywords>`` a variable composed of the given ``<prefix>`` +followed by ``"_"`` and the name of the respective keyword. These +variables will then hold the respective value from the argument list. +For the ``<options>`` keywords this will be ``TRUE`` or ``FALSE``. + +All remaining arguments are collected in a variable +``<prefix>_UNPARSED_ARGUMENTS``, this can be checked afterwards to see +whether your macro was called with unrecognized parameters. + +As an example here a ``my_install()`` macro, which takes similar arguments +as the real :command:`install` command: + +.. code-block:: cmake + + function(MY_INSTALL) + set(options OPTIONAL FAST) + set(oneValueArgs DESTINATION RENAME) + set(multiValueArgs TARGETS CONFIGURATIONS) + cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # ... + +Assume ``my_install()`` has been called like this: + +.. code-block:: cmake + + my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) + +After the ``cmake_parse_arguments`` call the macro will have set the +following variables:: + + MY_INSTALL_OPTIONAL = TRUE + MY_INSTALL_FAST = FALSE (was not used in call to my_install) + MY_INSTALL_DESTINATION = "bin" + MY_INSTALL_RENAME = "" (was not used) + MY_INSTALL_TARGETS = "foo;bar" + MY_INSTALL_CONFIGURATIONS = "" (was not used) + MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (nothing expected after "OPTIONAL") + +You can then continue and process these variables. + +Keywords terminate lists of values, e.g. if directly after a +one_value_keyword another recognized keyword follows, this is +interpreted as the beginning of the new option. E.g. +``my_install(TARGETS foo DESTINATION OPTIONAL)`` would result in +``MY_INSTALL_DESTINATION`` set to ``"OPTIONAL"``, but as ``OPTIONAL`` +is a keyword itself ``MY_INSTALL_DESTINATION`` will be empty and +``MY_INSTALL_OPTIONAL`` will therefore be set to ``TRUE``. diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index 5b92b51..d0c2986 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -29,6 +29,7 @@ These commands may be used freely in CMake projects. /command/build_command /command/cmake_host_system_information /command/cmake_minimum_required + /command/cmake_parse_arguments /command/cmake_policy /command/configure_file /command/continue diff --git a/Help/release/dev/CMakeParseArguments-native-impl.rst b/Help/release/dev/CMakeParseArguments-native-impl.rst new file mode 100644 index 0000000..114a099 --- /dev/null +++ b/Help/release/dev/CMakeParseArguments-native-impl.rst @@ -0,0 +1,6 @@ +CMakeParseArguments-native-impl +------------------------------- + +* The :command:`cmake_parse_arguments` command is now implemented natively. + The :module:`CMakeParseArguments` module remains as an empty placeholder + for compatibility. diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index b7975d3..45dda40 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -424,7 +424,9 @@ function(get_item_rpaths item rpaths_var) string(REGEX MATCHALL "rpath [^\n]+" load_cmds_ov "${load_cmds_ov}") string(REGEX REPLACE "rpath " "" load_cmds_ov "${load_cmds_ov}") if(load_cmds_ov) - gp_append_unique(${rpaths_var} "${load_cmds_ov}") + foreach(rpath ${load_cmds_ov}) + gp_append_unique(${rpaths_var} "${rpath}") + endforeach() endif() endif() diff --git a/Modules/CMakeParseArguments.cmake b/Modules/CMakeParseArguments.cmake index 8553f38..fc64ab9 100644 --- a/Modules/CMakeParseArguments.cmake +++ b/Modules/CMakeParseArguments.cmake @@ -2,86 +2,10 @@ # CMakeParseArguments # ------------------- # -# -# -# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> -# <multi_value_keywords> args...) -# -# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions -# for parsing the arguments given to that macro or function. It -# processes the arguments and defines a set of variables which hold the -# values of the respective options. -# -# The <options> argument contains all options for the respective macro, -# i.e. keywords which can be used when calling the macro without any -# value following, like e.g. the OPTIONAL keyword of the install() -# command. -# -# The <one_value_keywords> argument contains all keywords for this macro -# which are followed by one value, like e.g. DESTINATION keyword of the -# install() command. -# -# The <multi_value_keywords> argument contains all keywords for this -# macro which can be followed by more than one value, like e.g. the -# TARGETS or FILES keywords of the install() command. -# -# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the -# keywords listed in <options>, <one_value_keywords> and -# <multi_value_keywords> a variable composed of the given <prefix> -# followed by "_" and the name of the respective keyword. These -# variables will then hold the respective value from the argument list. -# For the <options> keywords this will be TRUE or FALSE. -# -# All remaining arguments are collected in a variable -# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see -# whether your macro was called with unrecognized parameters. -# -# As an example here a my_install() macro, which takes similar arguments -# as the real install() command: -# -# :: -# -# function(MY_INSTALL) -# set(options OPTIONAL FAST) -# set(oneValueArgs DESTINATION RENAME) -# set(multiValueArgs TARGETS CONFIGURATIONS) -# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" -# "${multiValueArgs}" ${ARGN} ) -# ... -# -# -# -# Assume my_install() has been called like this: -# -# :: -# -# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) -# -# -# -# After the cmake_parse_arguments() call the macro will have set the -# following variables: -# -# :: -# -# MY_INSTALL_OPTIONAL = TRUE -# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install() -# MY_INSTALL_DESTINATION = "bin" -# MY_INSTALL_RENAME = "" (was not used) -# MY_INSTALL_TARGETS = "foo;bar" -# MY_INSTALL_CONFIGURATIONS = "" (was not used) -# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" -# -# -# -# You can then continue and process these variables. -# -# Keywords terminate lists of values, e.g. if directly after a -# one_value_keyword another recognized keyword follows, this is -# interpreted as the beginning of the new option. E.g. -# my_install(TARGETS foo DESTINATION OPTIONAL) would result in -# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION -# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. +# This module once implemented the :command:`cmake_parse_arguments` command +# that is now implemented natively by CMake. It is now an empty placeholder +# for compatibility with projects that include it to get the command from +# CMake 3.4 and lower. #============================================================================= # Copyright 2010 Alexander Neundorf <neundorf@kde.org> @@ -95,67 +19,3 @@ #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) - - -if(__CMAKE_PARSE_ARGUMENTS_INCLUDED) - return() -endif() -set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE) - - -function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames) - # first set all result variables to empty/FALSE - foreach(arg_name ${_singleArgNames} ${_multiArgNames}) - set(${prefix}_${arg_name}) - endforeach() - - foreach(option ${_optionNames}) - set(${prefix}_${option} FALSE) - endforeach() - - set(${prefix}_UNPARSED_ARGUMENTS) - - set(insideValues FALSE) - set(currentArgName) - - # now iterate over all arguments and fill the result variables - foreach(currentArg ${ARGN}) - list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword - list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword - list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword - - if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1) - if(insideValues) - if("${insideValues}" STREQUAL "SINGLE") - set(${prefix}_${currentArgName} ${currentArg}) - set(insideValues FALSE) - elseif("${insideValues}" STREQUAL "MULTI") - list(APPEND ${prefix}_${currentArgName} ${currentArg}) - endif() - else() - list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) - endif() - else() - if(NOT ${optionIndex} EQUAL -1) - set(${prefix}_${currentArg} TRUE) - set(insideValues FALSE) - elseif(NOT ${singleArgIndex} EQUAL -1) - set(currentArgName ${currentArg}) - set(${prefix}_${currentArgName}) - set(insideValues "SINGLE") - elseif(NOT ${multiArgIndex} EQUAL -1) - set(currentArgName ${currentArg}) - set(${prefix}_${currentArgName}) - set(insideValues "MULTI") - endif() - endif() - - endforeach() - - # propagate the result variables to the caller: - foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) - set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) - endforeach() - set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) - -endfunction() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8fe4618..7515139 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 4) -set(CMake_VERSION_PATCH 20151217) +set(CMake_VERSION_PATCH 20151218) #set(CMake_VERSION_RC 1) diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx index 1184514..0782b3b 100644 --- a/Source/cmBootstrapCommands1.cxx +++ b/Source/cmBootstrapCommands1.cxx @@ -54,6 +54,7 @@ #include "cmFunctionCommand.cxx" #include "cmPathLabel.cxx" #include "cmSearchPath.cxx" +#include "cmParseArgumentsCommand.cxx" void GetBootstrapCommands1(std::vector<cmCommand*>& commands) { @@ -91,4 +92,5 @@ void GetBootstrapCommands1(std::vector<cmCommand*>& commands) commands.push_back(new cmFindProgramCommand); commands.push_back(new cmForEachCommand); commands.push_back(new cmFunctionCommand); + commands.push_back(new cmParseArgumentsCommand); } diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx new file mode 100644 index 0000000..a861965 --- /dev/null +++ b/Source/cmParseArgumentsCommand.cxx @@ -0,0 +1,192 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Matthias Maennich <matthias@maennich.net> + Copyright 2010 Alexander Neundorf <neundorf@kde.org> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmParseArgumentsCommand.h" +#include "cmAlgorithms.h" + +//---------------------------------------------------------------------------- +bool cmParseArgumentsCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + // cmake_parse_arguments(prefix options single multi <ARGN>) + // 1 2 3 4 + if (args.size() < 4) + { + this->SetError("must be called with at least 4 arguments."); + return false; + } + + std::vector<std::string>::const_iterator argIter = args.begin(), + argEnd = args.end(); + // the first argument is the prefix + const std::string prefix = (*argIter++) + "_"; + + // define the result maps holding key/value pairs for + // options, single values and multi values + typedef std::map<std::string, bool> options_map; + typedef std::map<std::string, std::string> single_map; + typedef std::map<std::string, std::vector<std::string> > multi_map; + options_map options; + single_map single; + multi_map multi; + + // anything else is put into a vector of unparsed strings + std::vector<std::string> unparsed; + + // remember already defined keywords + std::set<std::string> used_keywords; + const std::string dup_warning = "keyword defined more than once: "; + + // the second argument is a (cmake) list of options without argument + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(*argIter++, list); + for (std::vector<std::string>::const_iterator iter = list.begin(), + end = list.end(); + iter != end; ++iter) + { + if (!used_keywords.insert(*iter).second) + { + this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter); + } + options[*iter]; // default initialize + } + + // the third argument is a (cmake) list of single argument options + list.clear(); + cmSystemTools::ExpandListArgument(*argIter++, list); + for (std::vector<std::string>::const_iterator iter = list.begin(), + end = list.end(); + iter != end; ++iter) + { + if (!used_keywords.insert(*iter).second) + { + this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter); + } + single[*iter]; // default initialize + } + + // the fourth argument is a (cmake) list of multi argument options + list.clear(); + cmSystemTools::ExpandListArgument(*argIter++, list); + for (std::vector<std::string>::const_iterator iter = list.begin(), + end = list.end(); + iter != end; ++iter) + { + if (!used_keywords.insert(*iter).second) + { + this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter); + } + multi[*iter]; // default initialize + } + + enum insideValues + { + NONE, + SINGLE, + MULTI + } insideValues = NONE; + std::string currentArgName; + + // now iterate over the remaining arguments + // and fill in the values where applicable + for(; argIter != argEnd; ++argIter) + { + const options_map::iterator optIter = options.find(*argIter); + if (optIter != options.end()) + { + insideValues = NONE; + optIter->second = true; + continue; + } + + const single_map::iterator singleIter = single.find(*argIter); + if (singleIter != single.end()) + { + insideValues = SINGLE; + currentArgName = *argIter; + continue; + } + + const multi_map::iterator multiIter = multi.find(*argIter); + if (multiIter != multi.end()) + { + insideValues = MULTI; + currentArgName = *argIter; + continue; + } + + switch(insideValues) + { + case SINGLE: + single[currentArgName] = *argIter; + insideValues = NONE; + break; + case MULTI: + multi[currentArgName].push_back(*argIter); + break; + default: + unparsed.push_back(*argIter); + break; + } + } + + // now iterate over the collected values and update their definition + // within the current scope. undefine if necessary. + + for (options_map::const_iterator iter = options.begin(), end = options.end(); + iter != end; ++iter) + { + this->Makefile->AddDefinition(prefix + iter->first, + iter->second? "TRUE": "FALSE"); + } + for (single_map::const_iterator iter = single.begin(), end = single.end(); + iter != end; ++iter) + { + if (!iter->second.empty()) + { + this->Makefile->AddDefinition(prefix + iter->first, + iter->second.c_str()); + } + else + { + this->Makefile->RemoveDefinition(prefix + iter->first); + } + } + + for (multi_map::const_iterator iter = multi.begin(), end = multi.end(); + iter != end; ++iter) + { + if (!iter->second.empty()) + { + this->Makefile->AddDefinition(prefix + iter->first, + cmJoin(cmMakeRange(iter->second), ";") + .c_str()); + } + else + { + this->Makefile->RemoveDefinition(prefix + iter->first); + } + } + + if (!unparsed.empty()) + { + this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS", + cmJoin(cmMakeRange(unparsed), ";").c_str()); + } + else + { + this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS"); + } + + return true; +} diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h new file mode 100644 index 0000000..7fbf642 --- /dev/null +++ b/Source/cmParseArgumentsCommand.h @@ -0,0 +1,54 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Matthias Maennich <matthias@maennich.net> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmParseArgumentsCommand_h +#define cmParseArgumentsCommand_h + +#include "cmCommand.h" + +/** \class cmParseArgumentsCommand + * + */ +class cmParseArgumentsCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmParseArgumentsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * This determines if the command is invoked when in script mode. + */ + virtual bool IsScriptable() const { return true; } + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual std::string GetName() const { return "cmake_parse_arguments";} + + cmTypeMacro(cmParseArgumentsCommand, cmCommand); + +}; + + +#endif diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index b859e79..8b15394 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -118,7 +118,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(KWSYS_USE_System 1) SET(KWSYS_USE_SystemTools 1) SET(KWSYS_USE_CommandLineArguments 1) - SET(KWSYS_USE_FundamentalType 1) SET(KWSYS_USE_Terminal 1) SET(KWSYS_USE_IOStream 1) SET(KWSYS_USE_FStream 1) @@ -374,61 +373,6 @@ IF(KWSYS_CXX_HAS___INT64) ENDIF() ENDIF() -IF(KWSYS_USE_FundamentalType) - # Look for type size helper macros. - KWSYS_PLATFORM_INFO_TEST(C KWSYS_C_TYPE_MACROS - "Checking for C type size macros") - SET(macro_regex ".*INFO:macro\\[([^]]*)\\].*") - FOREACH(info ${KWSYS_C_TYPE_MACROS}) - IF("${info}" MATCHES "${macro_regex}") - STRING(REGEX REPLACE "${macro_regex}" "\\1" macro "${info}") - SET(KWSYS_C_HAS_MACRO_${macro} 1) - ENDIF() - ENDFOREACH() - - # Determine type sizes at preprocessing time if possible, and - # otherwise fall back to a try-compile. - SET(KWSYS_C_TYPE_NAME_CHAR "char") - SET(KWSYS_C_TYPE_NAME_SHORT "short") - SET(KWSYS_C_TYPE_NAME_INT "int") - SET(KWSYS_C_TYPE_NAME_LONG "long") - SET(KWSYS_C_TYPE_NAME_LONG_LONG "long long") - SET(KWSYS_C_TYPE_NAME___INT64 "__int64") - FOREACH(type CHAR SHORT INT LONG LONG_LONG __INT64) - IF(KWSYS_C_HAS_MACRO___SIZEOF_${type}__) - # Use __SIZEOF_${type}__ macro. - SET(KWSYS_SIZEOF_${type} TRUE) - SET(KWSYS_C_CODE_SIZEOF_${type} "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} __SIZEOF_${type}__") - ELSEIF(KWSYS_C_HAS_MACRO___${type}_MAX__) - # Use __${type}_MAX__ macro. - SET(KWSYS_SIZEOF_${type} TRUE) - SET(KWSYS_C_CODE_SIZEOF_${type} "#if __${type}_MAX__ == 0x7f -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 1 -#elif __${type}_MAX__ == 0x7fff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 2 -#elif __${type}_MAX__ == 0x7fffffff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 4 -#elif __${type}_MAX__>>32 == 0x7fffffff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 8 -#else -# error \"Cannot determine sizeof(${KWSYS_C_TYPE_NAME_${type}}).\" -#endif") - ELSE() - # Configure a hard-coded type size. - CHECK_TYPE_SIZE("${KWSYS_C_TYPE_NAME_${type}}" KWSYS_SIZEOF_${type}) - IF(NOT KWSYS_SIZEOF_${type}) - SET(KWSYS_SIZEOF_${type} 0) - ENDIF() - SET(KWSYS_C_CODE_SIZEOF_${type} - "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} ${KWSYS_SIZEOF_${type}}") - ENDIF() - ENDFOREACH() - - # Check signedness of "char" type. - KWSYS_PLATFORM_CXX_TEST_RUN(KWSYS_CHAR_IS_SIGNED - "Checking whether char is signed" DIRECT) -ENDIF() - IF(KWSYS_USE_Encoding) # Look for type size helper macros. KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING @@ -741,7 +685,7 @@ ENDFOREACH() # Add selected C components. FOREACH(c - Process Base64 Encoding FundamentalType MD5 Terminal System String + Process Base64 Encoding MD5 Terminal System String ) IF(KWSYS_USE_${c}) # Use the corresponding header file. diff --git a/Source/kwsys/FundamentalType.h.in b/Source/kwsys/FundamentalType.h.in deleted file mode 100644 index e702a7a..0000000 --- a/Source/kwsys/FundamentalType.h.in +++ /dev/null @@ -1,139 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_FundamentalType_h -#define @KWSYS_NAMESPACE@_FundamentalType_h - -#include <@KWSYS_NAMESPACE@/Configure.h> - -/* Redefine all public interface symbol names to be in the proper - namespace. These macros are used internally to kwsys only, and are - not visible to user code. Use kwsysHeaderDump.pl to reproduce - these macros after making changes to the interface. */ -#if !defined(KWSYS_NAMESPACE) -# define kwsys_ns(x) @KWSYS_NAMESPACE@##x -# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#endif - -#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# define kwsysFundamentalType kwsys_ns(FundamentalType) -# define kwsysFundamentalType_Int8 kwsys_ns(FundamentalType_Int8) -# define kwsysFundamentalType_UInt8 kwsys_ns(FundamentalType_UInt8) -# define kwsysFundamentalType_Int16 kwsys_ns(FundamentalType_Int16) -# define kwsysFundamentalType_UInt16 kwsys_ns(FundamentalType_UInt16) -# define kwsysFundamentalType_Int32 kwsys_ns(FundamentalType_Int32) -# define kwsysFundamentalType_UInt32 kwsys_ns(FundamentalType_UInt32) -# define kwsysFundamentalType_Int64 kwsys_ns(FundamentalType_Int64) -# define kwsysFundamentalType_UInt64 kwsys_ns(FundamentalType_UInt64) -#endif - -/* The size of fundamental types. Types that do not exist have size 0. */ -@KWSYS_C_CODE_SIZEOF_CHAR@ -@KWSYS_C_CODE_SIZEOF_SHORT@ -@KWSYS_C_CODE_SIZEOF_INT@ -@KWSYS_C_CODE_SIZEOF_LONG@ -@KWSYS_C_CODE_SIZEOF_LONG_LONG@ -@KWSYS_C_CODE_SIZEOF___INT64@ - -/* Whether types "long long" and "__int64" are enabled. If a type is - enabled then it is a unique fundamental type. */ -#define @KWSYS_NAMESPACE@_USE_LONG_LONG @KWSYS_USE_LONG_LONG@ -#define @KWSYS_NAMESPACE@_USE___INT64 @KWSYS_USE___INT64@ - -/* Whether type "char" is signed (it may be signed or unsigned). */ -#define @KWSYS_NAMESPACE@_CHAR_IS_SIGNED @KWSYS_CHAR_IS_SIGNED@ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* Select an 8-bit integer type. */ -#if @KWSYS_NAMESPACE@_SIZEOF_CHAR == 1 -typedef signed char kwsysFundamentalType_Int8; -typedef unsigned char kwsysFundamentalType_UInt8; -#else -# error "No native data type can represent an 8-bit integer." -#endif - -/* Select a 16-bit integer type. */ -#if @KWSYS_NAMESPACE@_SIZEOF_SHORT == 2 -typedef short kwsysFundamentalType_Int16; -typedef unsigned short kwsysFundamentalType_UInt16; -#elif @KWSYS_NAMESPACE@_SIZEOF_INT == 2 -typedef int kwsysFundamentalType_Int16; -typedef unsigned int kwsysFundamentalType_UInt16; -#else -# error "No native data type can represent a 16-bit integer." -#endif - -/* Select a 32-bit integer type. */ -#if @KWSYS_NAMESPACE@_SIZEOF_INT == 4 -typedef int kwsysFundamentalType_Int32; -typedef unsigned int kwsysFundamentalType_UInt32; -#elif @KWSYS_NAMESPACE@_SIZEOF_LONG == 4 -typedef long kwsysFundamentalType_Int32; -typedef unsigned long kwsysFundamentalType_UInt32; -#else -# error "No native data type can represent a 32-bit integer." -#endif - -/* Select a 64-bit integer type. */ -#if @KWSYS_NAMESPACE@_SIZEOF_LONG == 8 -typedef signed long kwsysFundamentalType_Int64; -typedef unsigned long kwsysFundamentalType_UInt64; -#elif @KWSYS_NAMESPACE@_USE_LONG_LONG && @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG == 8 -typedef signed long long kwsysFundamentalType_Int64; -typedef unsigned long long kwsysFundamentalType_UInt64; -#elif @KWSYS_NAMESPACE@_USE___INT64 && @KWSYS_NAMESPACE@_SIZEOF___INT64 == 8 -typedef signed __int64 kwsysFundamentalType_Int64; -typedef unsigned __int64 kwsysFundamentalType_UInt64; -#else -# error "No native data type can represent a 64-bit integer." -#endif - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -/* If we are building a kwsys .c or .cxx file, let it use these macros. - Otherwise, undefine them to keep the namespace clean. */ -#if !defined(KWSYS_NAMESPACE) -# undef kwsys_ns -# undef kwsysEXPORT -# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# undef kwsysFundamentalType -# undef kwsysFundamentalType_Int8 -# undef kwsysFundamentalType_UInt8 -# undef kwsysFundamentalType_Int16 -# undef kwsysFundamentalType_UInt16 -# undef kwsysFundamentalType_Int32 -# undef kwsysFundamentalType_UInt32 -# undef kwsysFundamentalType_Int64 -# undef kwsysFundamentalType_UInt64 -# endif -#endif - -/* If building a C or C++ file in kwsys itself, give the source file - access to the configured macros without a configured namespace. */ -#if defined(KWSYS_NAMESPACE) -# define KWSYS_SIZEOF_CHAR @KWSYS_NAMESPACE@_SIZEOF_CHAR -# define KWSYS_SIZEOF_SHORT @KWSYS_NAMESPACE@_SIZEOF_SHORT -# define KWSYS_SIZEOF_INT @KWSYS_NAMESPACE@_SIZEOF_INT -# define KWSYS_SIZEOF_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG -# define KWSYS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG -# define KWSYS_SIZEOF___INT64 @KWSYS_NAMESPACE@_SIZEOF___INT64 -# define KWSYS_USE_LONG_LONG @KWSYS_NAMESPACE@_USE_LONG_LONG -# define KWSYS_USE___INT64 @KWSYS_NAMESPACE@_USE___INT64 -# define KWSYS_CHAR_IS_SIGNED @KWSYS_NAMESPACE@_CHAR_IS_SIGNED -#endif - -#endif diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index aaa33b8..fc87f91 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -130,15 +130,6 @@ int main() } #endif -#ifdef TEST_KWSYS_CHAR_IS_SIGNED -/* Return 0 for char signed and 1 for char unsigned. */ -int main() -{ - unsigned char uc = 255; - return (*reinterpret_cast<char*>(&uc) < 0)?0:1; -} -#endif - #ifdef TEST_KWSYS_LFS_WORKS /* Return 0 when LFS is available and 1 otherwise. */ #define _LARGEFILE_SOURCE @@ -326,93 +317,6 @@ int main() } #endif -#ifdef TEST_KWSYS_CXX_TYPE_INFO -/* Collect fundamental type information and save it to a CMake script. */ - -/* Include limits.h to get macros indicating long long and __int64. - Note that certain compilers need special macros to define these - macros in limits.h. */ -#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS) -# define _MSC_EXTENSIONS -#endif -#if defined(__GNUC__) && __GNUC__ < 3 -# define _GNU_SOURCE -#endif -#include <limits.h> - -#include <stdio.h> -#include <string.h> - -/* Due to shell differences and limitations of ADD_DEFINITIONS the - KWSYS_CXX_TYPE_INFO_FILE macro will sometimes have double quotes - and sometimes not. This macro will make sure the value is treated - as a double-quoted string. */ -#define TO_STRING(x) TO_STRING0(x) -#define TO_STRING0(x) TO_STRING1(x) -#define TO_STRING1(x) #x - -void f() {} - -int main() -{ - /* Construct the output file name. Some preprocessors will add an - extra level of double quotes, so strip them. */ - char fbuf[] = TO_STRING(KWSYS_CXX_TYPE_INFO_FILE); - char* fname = fbuf; - if(fname[0] == '"') - { - ++fname; - int len = static_cast<int>(strlen(fname)); - if(len > 0 && fname[len-1] == '"') - { - fname[len-1] = 0; - } - } - - /* Try to open the output file. */ - if(FILE* fout = fopen(fname, "w")) - { - /* Set the size of standard types. */ - fprintf(fout, "SET(KWSYS_SIZEOF_CHAR %d)\n", static_cast<int>(sizeof(char))); - fprintf(fout, "SET(KWSYS_SIZEOF_SHORT %d)\n", static_cast<int>(sizeof(short))); - fprintf(fout, "SET(KWSYS_SIZEOF_INT %d)\n", static_cast<int>(sizeof(int))); - fprintf(fout, "SET(KWSYS_SIZEOF_LONG %d)\n", static_cast<int>(sizeof(long))); - - /* Set the size of some non-standard but common types. */ - /* Check for a limits.h macro for long long to see if the type exists. */ -#if defined(LLONG_MAX) || defined(LONG_LONG_MAX) || defined(LONGLONG_MAX) - fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG %d)\n", static_cast<int>(sizeof(long long))); -#else - fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG 0) # No long long available.\n"); -#endif - /* Check for a limits.h macro for __int64 to see if the type exists. */ -#if defined(_I64_MIN) - fprintf(fout, "SET(KWSYS_SIZEOF___INT64 %d)\n", static_cast<int>(sizeof(__int64))); -#else - fprintf(fout, "SET(KWSYS_SIZEOF___INT64 0) # No __int64 available.\n"); -#endif - - /* Set the size of some pointer types. */ - fprintf(fout, "SET(KWSYS_SIZEOF_PDATA %d)\n", static_cast<int>(sizeof(void*))); - fprintf(fout, "SET(KWSYS_SIZEOF_PFUNC %d)\n", static_cast<int>(sizeof(&f))); - - /* Set whether the native type "char" is signed or unsigned. */ - unsigned char uc = 255; - fprintf(fout, "SET(KWSYS_CHAR_IS_SIGNED %d)\n", - (*reinterpret_cast<char*>(&uc) < 0)?1:0); - - fclose(fout); - return 0; - } - else - { - fprintf(stderr, "Failed to write fundamental type info to \"%s\".\n", - fname); - return 1; - } -} -#endif - #ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM int main() { diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a6cbf86..0a388c5 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -177,6 +177,7 @@ add_RunCMake_test(build_command) add_RunCMake_test(execute_process) add_RunCMake_test(export) add_RunCMake_test(cmake_minimum_required) +add_RunCMake_test(cmake_parse_arguments) add_RunCMake_test(continue) add_RunCMake_test(ctest_build) add_RunCMake_test(ctest_configure) diff --git a/Tests/RunCMake/cmake_parse_arguments/CMakeLists.txt b/Tests/RunCMake/cmake_parse_arguments/CMakeLists.txt new file mode 100644 index 0000000..6dd8cdf --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/cmake_parse_arguments/CornerCases.cmake b/Tests/RunCMake/cmake_parse_arguments/CornerCases.cmake new file mode 100644 index 0000000..9a727dd --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/CornerCases.cmake @@ -0,0 +1,15 @@ +include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) + +# example from the documentation +# OPTIONAL is a keyword and therefore terminates the definition of +# the multi-value DEFINITION before even a single value has been added + +set(options OPTIONAL FAST) +set(oneValueArgs DESTINATION RENAME) +set(multiValueArgs TARGETS CONFIGURATIONS) +cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" + "${multiValueArgs}" + TARGETS foo DESTINATION OPTIONAL) + +TEST(MY_INSTALL_DESTINATION UNDEFINED) +TEST(MY_INSTALL_OPTIONAL TRUE) diff --git a/Tests/RunCMake/cmake_parse_arguments/Errors-result.txt b/Tests/RunCMake/cmake_parse_arguments/Errors-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Errors-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt b/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt new file mode 100644 index 0000000..f2ba9b8 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Errors-stderr.txt @@ -0,0 +1,44 @@ +CMake Error at Errors\.cmake:2 \(cmake_parse_arguments\): + cmake_parse_arguments must be called with at least 4 arguments\. +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Error at Errors\.cmake:3 \(cmake_parse_arguments\): + cmake_parse_arguments must be called with at least 4 arguments\. +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Error at Errors\.cmake:4 \(cmake_parse_arguments\): + cmake_parse_arguments must be called with at least 4 arguments\. +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:8 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:9 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:10 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:12 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:13 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) ++ +CMake Warning at Errors\.cmake:14 \(cmake_parse_arguments\): + keyword defined more than once: OPT +Call Stack \(most recent call first\): + CMakeLists\.txt:3 \(include\) diff --git a/Tests/RunCMake/cmake_parse_arguments/Errors.cmake b/Tests/RunCMake/cmake_parse_arguments/Errors.cmake new file mode 100644 index 0000000..6a38081 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Errors.cmake @@ -0,0 +1,14 @@ +# wrong argument count +cmake_parse_arguments() +cmake_parse_arguments(prefix OPT) +cmake_parse_arguments(prefix OPT SINGLE) +cmake_parse_arguments(prefix OPT SINGLE MULTI) # not an error + +# duplicate keywords +cmake_parse_arguments(prefix "OPT;OPT" "" "") +cmake_parse_arguments(prefix "" "OPT;OPT" "") +cmake_parse_arguments(prefix "" "" "OPT;OPT") + +cmake_parse_arguments(prefix "OPT" "OPT" "") +cmake_parse_arguments(prefix "" "OPT" "OPT") +cmake_parse_arguments(prefix "OPT" "" "OPT") diff --git a/Tests/RunCMake/cmake_parse_arguments/Initialization.cmake b/Tests/RunCMake/cmake_parse_arguments/Initialization.cmake new file mode 100644 index 0000000..462f923 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Initialization.cmake @@ -0,0 +1,68 @@ +include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) + +# unparsed arguments +cmake_parse_arguments(pref "" "" "") +TEST(pref_UNPARSED_ARGUMENTS UNDEFINED) + +cmake_parse_arguments(pref "" "" "" FOO) +TEST(pref_UNPARSED_ARGUMENTS "FOO") +cmake_parse_arguments(pref "" "" "" FOO BAR) +TEST(pref_UNPARSED_ARGUMENTS "FOO;BAR") +cmake_parse_arguments(pref "" "" "") +TEST(pref_UNPARSED_ARGUMENTS UNDEFINED) + + +# options +cmake_parse_arguments(pref "OPT1" "" "") +TEST(pref_OPT1 FALSE) + +cmake_parse_arguments(pref "OPT1;OPT2" "" "") +TEST(pref_OPT1 FALSE) +TEST(pref_OPT2 FALSE) + +cmake_parse_arguments(pref "OPT1" "" "" OPT1) +TEST(pref_OPT1 TRUE) +cmake_parse_arguments(pref "OPT1;OPT2" "" "" OPT1 OPT2) +TEST(pref_OPT1 TRUE) +TEST(pref_OPT2 TRUE) +cmake_parse_arguments(pref "OPT1;OPT2" "" "") +TEST(pref_OPT1 FALSE) +TEST(pref_OPT2 FALSE) + + +# single arguments +cmake_parse_arguments(pref "" "SINGLE1" "") +TEST(pref_SINGLE1 UNDEFINED) + +cmake_parse_arguments(pref "" "SINGLE1;SINGLE2" "") +TEST(pref_SINGLE1 UNDEFINED) +TEST(pref_SINGLE2 UNDEFINED) + + +cmake_parse_arguments(pref "" "SINGLE1" "" SINGLE1 foo) +TEST(pref_SINGLE1 foo) +cmake_parse_arguments(pref "" "SINGLE1;SINGLE2" "" SINGLE1 foo SINGLE2 bar) +TEST(pref_SINGLE1 foo) +TEST(pref_SINGLE2 bar) +cmake_parse_arguments(pref "" "SINGLE1;SINGLE2" "") +TEST(pref_SINGLE1 UNDEFINED) +TEST(pref_SINGLE2 UNDEFINED) + + +# multi arguments + +cmake_parse_arguments(pref "" "" "MULTI1") +TEST(pref_MULTI1 UNDEFINED) + +cmake_parse_arguments(pref "" "" "MULTI1;MULTI2") +TEST(pref_MULTI1 UNDEFINED) +TEST(pref_MULTI2 UNDEFINED) + +cmake_parse_arguments(pref "" "" "MULTI1" MULTI1 foo) +TEST(pref_MULTI1 foo) +cmake_parse_arguments(pref "" "" "MULTI1;MULTI2" MULTI1 foo bar MULTI2 bar foo) +TEST(pref_MULTI1 foo bar) +TEST(pref_MULTI2 bar foo) +cmake_parse_arguments(pref "" "" "MULTI1;MULTI2") +TEST(pref_MULTI1 UNDEFINED) +TEST(pref_MULTI2 UNDEFINED) diff --git a/Tests/RunCMake/cmake_parse_arguments/Mix.cmake b/Tests/RunCMake/cmake_parse_arguments/Mix.cmake new file mode 100644 index 0000000..b3eff39 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Mix.cmake @@ -0,0 +1,24 @@ +include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) + +# specify two keywords for each category and set the first keyword of each +# within ARGN +cmake_parse_arguments(pref "OPT1;OPT2" "SINGLE1;SINGLE2" "MULTI1;MULTI2" + OPT1 SINGLE1 foo MULTI1 bar foo bar) +TEST(pref_OPT1 TRUE) +TEST(pref_OPT2 FALSE) +TEST(pref_SINGLE1 foo) +TEST(pref_SINGLE2 UNDEFINED) +TEST(pref_MULTI1 bar foo bar) +TEST(pref_MULTI2 UNDEFINED) +TEST(pref_UNPARSED_ARGUMENTS UNDEFINED) + +# same as above but reversed ARGN +cmake_parse_arguments(pref "OPT1;OPT2" "SINGLE1;SINGLE2" "MULTI1;MULTI2" + MULTI1 bar foo bar SINGLE1 foo OPT1) +TEST(pref_OPT1 TRUE) +TEST(pref_OPT2 FALSE) +TEST(pref_SINGLE1 foo) +TEST(pref_SINGLE2 UNDEFINED) +TEST(pref_MULTI1 bar foo bar) +TEST(pref_MULTI2 UNDEFINED) +TEST(pref_UNPARSED_ARGUMENTS UNDEFINED) diff --git a/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake new file mode 100644 index 0000000..b89f1a5 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/RunCMakeTest.cmake @@ -0,0 +1,7 @@ +include(RunCMake) + +run_cmake(Utils) +run_cmake(Initialization) +run_cmake(Mix) +run_cmake(CornerCases) +run_cmake(Errors) diff --git a/Tests/RunCMake/cmake_parse_arguments/Utils.cmake b/Tests/RunCMake/cmake_parse_arguments/Utils.cmake new file mode 100644 index 0000000..3bbf115 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/Utils.cmake @@ -0,0 +1,20 @@ +include(${CMAKE_CURRENT_LIST_DIR}/test_utils.cmake) + +# test the TEST macro itself + +TEST(asdf UNDEFINED) + +SET (asdf FALSE) +TEST(asdf FALSE) + +SET (asdf TRUE) +TEST(asdf TRUE) + +SET (asdf TRUE) +TEST(asdf TRUE) + +SET (asdf "some value") +TEST(asdf "some value") + +SET (asdf some list) +TEST(asdf "some;list") diff --git a/Tests/RunCMake/cmake_parse_arguments/test_utils.cmake b/Tests/RunCMake/cmake_parse_arguments/test_utils.cmake new file mode 100644 index 0000000..f5425c2 --- /dev/null +++ b/Tests/RunCMake/cmake_parse_arguments/test_utils.cmake @@ -0,0 +1,20 @@ +macro(TEST variable) + SET(expected "${ARGN}") + if ( "${expected}" STREQUAL "UNDEFINED" ) + if (DEFINED ${variable}) + message(FATAL_ERROR "'${variable}' shall be undefined but has value '${${variable}}'") + endif() + elseif( "${expected}" STREQUAL "FALSE" ) + if (NOT ${variable} STREQUAL "FALSE") + message(FATAL_ERROR "'${variable}' shall be FALSE") + endif() + elseif( "${expected}" STREQUAL "TRUE" ) + if (NOT ${variable} STREQUAL "TRUE") + message(FATAL_ERROR "'${variable}' shall be TRUE") + endif() + else() + if (NOT ${variable} STREQUAL "${expected}") + message(FATAL_ERROR "'${variable}' shall be '${expected}'") + endif() + endif() +endmacro() diff --git a/Utilities/Scripts/update-kwsys.bash b/Utilities/Scripts/update-kwsys.bash new file mode 100755 index 0000000..650841f --- /dev/null +++ b/Utilities/Scripts/update-kwsys.bash @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -e +set -x +shopt -s dotglob + +readonly name="KWSys" +readonly ownership="KWSys Upstream <kwrobot@kitware.com>" +readonly subtree="Source/kwsys" +readonly repo="http://public.kitware.com/KWSys.git" +readonly tag="master" +readonly shortlog=true +readonly paths=" +" + +extract_source () { + git_archive +} + +export HOOKS_ALLOW_KWSYS=1 + +. "${BASH_SOURCE%/*}/update-third-party.bash" diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash new file mode 100644 index 0000000..8925296 --- /dev/null +++ b/Utilities/Scripts/update-third-party.bash @@ -0,0 +1,146 @@ +######################################################################## +# Script for updating third party packages. +# +# This script should be sourced in a project-specific script which sets +# the following variables: +# +# name +# The name of the project. +# ownership +# A git author name/email for the commits. +# subtree +# The location of the thirdparty package within the main source +# tree. +# repo +# The git repository to use as upstream. +# tag +# The tag, branch or commit hash to use for upstream. +# shortlog +# Optional. Set to 'true' to get a shortlog in the commit message. +# +# Additionally, an "extract_source" function must be defined. It will be +# run within the checkout of the project on the requested tag. It should +# should place the desired tree into $extractdir/$name-reduced. This +# directory will be used as the newest commit for the project. +# +# For convenience, the function may use the "git_archive" function which +# does a standard "git archive" extraction using the (optional) "paths" +# variable to only extract a subset of the source tree. +######################################################################## + +######################################################################## +# Utility functions +######################################################################## +git_archive () { + git archive --prefix="$name-reduced/" HEAD -- $paths | \ + tar -C "$extractdir" -x +} + +die () { + echo >&2 "$@" + exit 1 +} + +warn () { + echo >&2 "warning: $@" +} + +readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]' +readonly basehash_regex="$name $regex_date ([0-9a-f]*)" +readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )" +readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )" + +######################################################################## +# Sanity checking +######################################################################## +[ -n "$name" ] || \ + die "'name' is empty" +[ -n "$ownership" ] || \ + die "'ownership' is empty" +[ -n "$subtree" ] || \ + die "'subtree' is empty" +[ -n "$repo" ] || \ + die "'repo' is empty" +[ -n "$tag" ] || \ + die "'tag' is empty" +[ -n "$basehash" ] || \ + warn "'basehash' is empty; performing initial import" +readonly do_shortlog="${shortlog-false}" + +readonly workdir="$PWD/work" +readonly upstreamdir="$workdir/upstream" +readonly extractdir="$workdir/extract" + +[ -d "$workdir" ] && \ + die "error: workdir '$workdir' already exists" + +trap "rm -rf '$workdir'" EXIT + +# Get upstream +git clone "$repo" "$upstreamdir" + +if [ -n "$basehash" ]; then + # Use the existing package's history + git worktree add "$extractdir" "$basehash" + # Clear out the working tree + pushd "$extractdir" + git ls-files | xargs rm -v + popd +else + # Create a repo to hold this package's history + mkdir -p "$extractdir" + git -C "$extractdir" init +fi + +# Extract the subset of upstream we care about +pushd "$upstreamdir" +git checkout "$tag" +readonly upstream_hash="$( git rev-parse HEAD )" +readonly upstream_hash_short="$( git rev-parse --short=8 "$upstream_hash" )" +readonly upstream_datetime="$( git rev-list "$upstream_hash" --format='%ci' -n 1 | grep -e "^$regex_date" )" +readonly upstream_date="$( echo "$upstream_datetime" | grep -o -e "$regex_date" )" +if $do_shortlog && [ -n "$basehash" ]; then + readonly commit_shortlog=" + +Upstream Shortlog +----------------- + +$( git shortlog --no-merges --abbrev=8 --format='%h %s' "$upstream_old_short".."$upstream_hash" )" +else + readonly commit_shortlog="" +fi +extract_source || \ + die "failed to extract source" +popd + +[ -d "$extractdir/$name-reduced" ] || \ + die "expected directory to extract does not exist" +readonly commit_summary="$name $upstream_date ($upstream_hash_short)" + +# Commit the subset +pushd "$extractdir" +mv -v "$name-reduced/"* . +rmdir "$name-reduced/" +git add -A . +git commit -n --author="$ownership" --date="$upstream_datetime" -F - <<-EOF +$commit_summary + +Code extracted from: + + $repo + +at commit $upstream_hash ($tag).$commit_shortlog +EOF +git branch -f "upstream-$name" +popd + +# Merge the subset into this repository +if [ -n "$basehash" ]; then + git merge --log -s recursive "-Xsubtree=$subtree/" --no-commit "upstream-$name" +else + git fetch "$extractdir" "upstream-$name:upstream-$name" + git merge --log -s ours --no-commit "upstream-$name" + git read-tree -u --prefix="$subtree/" "upstream-$name" +fi +git commit --no-edit +git branch -d "upstream-$name" |