summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Neundorf <neundorf@kde.org>2010-08-14 20:06:49 (GMT)
committerAlex Neundorf <neundorf@kde.org>2010-08-14 20:06:49 (GMT)
commitb173b879f8c2a3035d826e1cfa1407380b6eb2ee (patch)
treeaa8647af02ea31b5df058317fd76bf0227cba542
parent16168ab0c3549b6953fe95354446508ce3cc945e (diff)
downloadCMake-b173b879f8c2a3035d826e1cfa1407380b6eb2ee.zip
CMake-b173b879f8c2a3035d826e1cfa1407380b6eb2ee.tar.gz
CMake-b173b879f8c2a3035d826e1cfa1407380b6eb2ee.tar.bz2
Add macro CMakeParseArguments() and use it in FPHSA()
This adds a macro cmake_parse_arguments() (as discussed on cmake-devel) which can be used in macros or functions to help with parsing its arguments. Detailled docs are included. find_package_handle_standard_args() is the first user of this new macro. Alex
-rw-r--r--Modules/CMakeParseArguments.cmake137
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake100
2 files changed, 166 insertions, 71 deletions
diff --git a/Modules/CMakeParseArguments.cmake b/Modules/CMakeParseArguments.cmake
new file mode 100644
index 0000000..c7148ae
--- /dev/null
+++ b/Modules/CMakeParseArguments.cmake
@@ -0,0 +1,137 @@
+# 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 the 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.
+
+# Copyright (c) 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.
+#=============================================================================
+# (To distributed 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(arg_name)
+
+ foreach(option ${_optionNames})
+ set(${prefix}_${option} FALSE)
+ endforeach(option)
+
+ 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(insideValues)
+ list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
+ endif(insideValues)
+ 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(currentArg)
+
+ # propagate the result variables to the caller:
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
+ set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
+ endforeach(arg_name)
+ set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
+
+endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs)
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index 37a55b3..c698480 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -68,89 +68,47 @@
# License text for the above reference.)
INCLUDE(FindPackageMessage)
-
-# Checks a list of strings (typically function/macro parameters) whether it contains a keyword
-# (_keyword) and return the value(s) following this keyword in _outputVar.
-# If _multipleValues is true, this can be more than one value.
-# Then end of the values for a keyword is then determined by checking whether the
-# next argument is contained in _allKeywordsList.
-FUNCTION(FPHSA_GET_OPTION_VALUE _keyword _outputVar _allArgsList _allKeywordsList _multipleValues)
- UNSET(${_outputVar})
- UNSET(_removeIndices)
-
- SET(_insideValues FALSE)
- SET(_counter 0)
- FOREACH(_currentArg ${${_allArgsList}})
- IF(NOT _insideValues) # first check that we find the keyword we are currently interested in...
- IF("${_currentArg}" STREQUAL "${_keyword}")
- SET(_insideValues TRUE)
- LIST(APPEND _removeIndices ${_counter})
- ENDIF("${_currentArg}" STREQUAL "${_keyword}")
- ELSE(NOT _insideValues)
-
- LIST(FIND ${_allKeywordsList} "${_currentArg}" _index) # ... then this marks the end of the arguments belonging to this keyword
- IF(${_index} EQUAL -1)
- LIST(APPEND _result ${_currentArg})
- LIST(APPEND _removeIndices ${_counter}) # collect the indices of the strings we found to remove them from the list afterwards
- IF(NOT _multipleValues)
- BREAK()
- ENDIF(NOT _multipleValues)
- ELSE(${_index} EQUAL -1)
- SET(_insideValues FALSE)
- BREAK()
- ENDIF(${_index} EQUAL -1)
- ENDIF(NOT _insideValues)
-
- MATH(EXPR _counter "${_counter} + 1")
-
- ENDFOREACH(_currentArg ${${_allArgsList}})
-
- IF(DEFINED _removeIndices)
- LIST(REMOVE_AT ${_allArgsList} ${_removeIndices})
- ENDIF(DEFINED _removeIndices)
-
- SET(${_outputVar} ${_result} PARENT_SCOPE)
- SET(${_allArgsList} ${${_allArgsList}} PARENT_SCOPE)
-
-ENDFUNCTION(FPHSA_GET_OPTION_VALUE _keyword _outputVar _allArgsList _allKeywordsList _multipleValues)
+INCLUDE(CMakeParseArguments)
FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG _VAR1)
- SET(_KEYWORDS_FOR_EXTENDED_MODE FAIL_MESSAGE REQUIRED_VARS VERSION_VAR )
+# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
+# new extended or in the "old" mode:
+ SET(options) # none
+ SET(oneValueArgs FAIL_MESSAGE VERSION_VAR)
+ SET(multiValueArgs REQUIRED_VARS)
+ SET(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
LIST(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
IF(${INDEX} EQUAL -1)
- SET(_FAIL_MESSAGE ${_FIRST_ARG})
- SET(_REQUIRED_VARS ${_VAR1} ${ARGN})
- SET(_VERSION_VAR)
+ SET(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
+ SET(FPHSA_REQUIRED_VARS ${_VAR1} ${ARGN})
+ SET(FPHSA_VERSION_VAR)
ELSE(${INDEX} EQUAL -1)
- SET(ALL_ARGS ${_FIRST_ARG} ${_VAR1} ${ARGN})
- FPHSA_GET_OPTION_VALUE("FAIL_MESSAGE" _FAIL_MESSAGE ALL_ARGS _KEYWORDS_FOR_EXTENDED_MODE FALSE)
- FPHSA_GET_OPTION_VALUE("REQUIRED_VARS" _REQUIRED_VARS ALL_ARGS _KEYWORDS_FOR_EXTENDED_MODE TRUE)
- FPHSA_GET_OPTION_VALUE("VERSION_VAR" _VERSION_VAR ALL_ARGS _KEYWORDS_FOR_EXTENDED_MODE FALSE)
+ CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${_VAR1} ${ARGN})
- IF(ALL_ARGS)
- MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${ALL_ARGS}\"")
- ENDIF(ALL_ARGS)
+ IF(FPHSA_UNPARSED_ARGUMENTS)
+ MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
+ ENDIF(FPHSA_UNPARSED_ARGUMENTS)
- IF(NOT _FAIL_MESSAGE)
- SET(_FAIL_MESSAGE "DEFAULT_MSG")
- ENDIF(NOT _FAIL_MESSAGE)
+ IF(NOT FPHSA_FAIL_MESSAGE)
+ SET(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
+ ENDIF(NOT FPHSA_FAIL_MESSAGE)
ENDIF(${INDEX} EQUAL -1)
# now that we collected all arguments, process them
- IF("${_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
- SET(_FAIL_MESSAGE "Could NOT find ${_NAME}")
- ENDIF("${_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
+ IF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
+ SET(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
+ ENDIF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG")
- IF(NOT _REQUIRED_VARS)
+ IF(NOT FPHSA_REQUIRED_VARS)
MESSAGE(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
- ENDIF(NOT _REQUIRED_VARS)
+ ENDIF(NOT FPHSA_REQUIRED_VARS)
- LIST(GET _REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
+ LIST(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
STRING(TOUPPER ${_NAME} _NAME_UPPER)
@@ -160,7 +118,7 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG _VAR1)
SET(DETAILS "")
SET(${_NAME_UPPER}_FOUND TRUE)
# check if all passed variables are valid
- FOREACH(_CURRENT_VAR ${_REQUIRED_VARS})
+ FOREACH(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
IF(NOT ${_CURRENT_VAR})
SET(${_NAME_UPPER}_FOUND FALSE)
SET(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
@@ -177,7 +135,7 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG _VAR1)
# if the package was found, check for the version using <NAME>_FIND_VERSION
IF (${_NAME_UPPER}_FOUND)
- SET(VERSION ${${_VERSION_VAR}} )
+ SET(VERSION ${${FPHSA_VERSION_VAR}} )
IF(VERSION)
@@ -227,20 +185,20 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG _VAR1)
IF(NOT VERSION_OK)
IF (${_NAME}_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "${_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
+ MESSAGE(FATAL_ERROR "${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
ELSE (${_NAME}_FIND_REQUIRED)
IF (NOT ${_NAME}_FIND_QUIETLY)
- MESSAGE(STATUS "${_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
+ MESSAGE(STATUS "${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
ENDIF (NOT ${_NAME}_FIND_QUIETLY)
ENDIF (${_NAME}_FIND_REQUIRED)
ELSE(NOT VERSION_OK)
IF (${_NAME}_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "${_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+ MESSAGE(FATAL_ERROR "${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
ELSE (${_NAME}_FIND_REQUIRED)
IF (NOT ${_NAME}_FIND_QUIETLY)
- MESSAGE(STATUS "${_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+ MESSAGE(STATUS "${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
ENDIF (NOT ${_NAME}_FIND_QUIETLY)
ENDIF (${_NAME}_FIND_REQUIRED)
ENDIF(NOT VERSION_OK)