aboutsummaryrefslogtreecommitdiffstats
path: root/cmake/QtIRCommandLineHelpers.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/QtIRCommandLineHelpers.cmake')
-rw-r--r--cmake/QtIRCommandLineHelpers.cmake405
1 files changed, 405 insertions, 0 deletions
diff --git a/cmake/QtIRCommandLineHelpers.cmake b/cmake/QtIRCommandLineHelpers.cmake
new file mode 100644
index 00000000..65c5d6aa
--- /dev/null
+++ b/cmake/QtIRCommandLineHelpers.cmake
@@ -0,0 +1,405 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# This file contains a modified subset of the qtbase/QtProcessConfigureArgs.cmake commands
+# with renamed functions, because we need similar logic for init-repository, but
+# we can't access qtbase before we clone it.
+
+# Call a function with the given arguments.
+function(qt_ir_call_function func)
+ set(call_code "${func}(")
+ math(EXPR n "${ARGC} - 1")
+ foreach(i RANGE 1 ${n})
+ string(APPEND call_code "\"${ARGV${i}}\" ")
+ endforeach()
+ string(APPEND call_code ")")
+ string(REPLACE "\\" "\\\\" call_code "${call_code}")
+ if(${CMAKE_VERSION} VERSION_LESS "3.18.0")
+ set(incfile qt_tmp_func_call.cmake)
+ file(WRITE "${incfile}" "${call_code}")
+ include(${incfile})
+ file(REMOVE "${incfile}")
+ else()
+ cmake_language(EVAL CODE "${call_code}")
+ endif()
+endfunction()
+
+# Show an error.
+function(qt_ir_add_error)
+ message(FATAL_ERROR ${ARGV})
+endfunction()
+
+# Check if there are still unhandled command line arguments.
+function(qt_ir_args_has_next_command_line_arg out_var)
+ qt_ir_get_unhandled_args(args)
+
+ list(LENGTH args n)
+ if(n GREATER 0)
+ set(result TRUE)
+ else()
+ set(result FALSE)
+ endif()
+ set(${out_var} ${result} PARENT_SCOPE)
+endfunction()
+
+# Get the next unhandled command line argument without popping it.
+function(qt_ir_args_peek_next_command_line_arg out_var)
+ qt_ir_get_unhandled_args(args)
+ list(GET args 0 result)
+ set(${out_var} ${result} PARENT_SCOPE)
+endfunction()
+
+# Get the next unhandled command line argument.
+function(qt_ir_args_get_next_command_line_arg out_var)
+ qt_ir_get_unhandled_args(args)
+ list(POP_FRONT args result)
+ qt_ir_set_unhandled_args("${args}")
+ set(${out_var} ${result} PARENT_SCOPE)
+endfunction()
+
+# Helper macro to parse the arguments for the command line options.
+macro(qt_ir_commandline_option_parse_arguments)
+ set(options UNSUPPORTED)
+ set(oneValueArgs TYPE NAME SHORT_NAME ALIAS VALUE DEFAULT_VALUE)
+ set(multiValueArgs VALUES MAPPING)
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+endmacro()
+
+# We use this to define the command line options that init-repository accepts.
+# Arguments
+# name - name of the long form option
+# e.g. 'module-subset' will parse '--module-subset'
+# UNSUPPORTED - mark the option as unsupported in the cmake port of init-repository,
+# which means we will fall back to calling the perl script instead
+# TYPE - the type of the option, currently we support boolean, string and void
+# VALUE - the value to be set for a 'void' type option
+# VALUES - the valid values for an option
+# MAPPING - currently unused
+# SHORT_NAME - an alternative short name flag,
+# e.g. 'f' will parse -f for --force
+# ALIAS - mark the option as an alias of another option, both will have the
+# same value when retrieved.
+# DEFAULT_VALUE - the default value to be set for the option when it's not specified
+# on the command line
+#
+# NOTE: Make sure to update the SHORT_NAME code path when adding new options.
+function(qt_ir_commandline_option_helper name)
+ qt_ir_commandline_option_parse_arguments(${ARGN})
+
+ set(unsupported_options "${commandline_known_unsupported_options}")
+ if(arg_UNSUPPORTED)
+ set(commandline_option_${name}_unsupported
+ "${arg_UNSUPPORTED}" PARENT_SCOPE)
+ list(APPEND unsupported_options "${name}")
+ endif()
+ set(commandline_known_unsupported_options "${unsupported_options}" PARENT_SCOPE)
+
+ set(commandline_known_options
+ "${commandline_known_options};${name}" PARENT_SCOPE)
+
+ set(commandline_option_${name}_type "${arg_TYPE}" PARENT_SCOPE)
+
+ if(NOT "${arg_VALUE}" STREQUAL "")
+ set(commandline_option_${name}_value "${arg_VALUE}" PARENT_SCOPE)
+ endif()
+
+ if(arg_VALUES)
+ set(commandline_option_${name}_values ${arg_VALUES} PARENT_SCOPE)
+ elseif(arg_MAPPING)
+ set(commandline_option_${name}_mapping ${arg_MAPPING} PARENT_SCOPE)
+ endif()
+
+ if(NOT "${arg_SHORT_NAME}" STREQUAL "")
+ set(commandline_option_${name}_short_name "${arg_SHORT_NAME}" PARENT_SCOPE)
+ endif()
+
+ if(NOT "${arg_ALIAS}" STREQUAL "")
+ set(commandline_option_${name}_alias "${arg_ALIAS}" PARENT_SCOPE)
+ endif()
+
+ # Should be last, in case alias was specified
+ if(NOT "${arg_DEFAULT_VALUE}" STREQUAL "")
+ set(commandline_option_${name}_default_value "${arg_DEFAULT_VALUE}" PARENT_SCOPE)
+ qt_ir_command_line_set_input("${name}" "${arg_DEFAULT_VALUE}")
+ endif()
+endfunction()
+
+# Defines an option that init-repository understands.
+# Uses qt_ir_commandline_option_helper to define both long and short option names.
+macro(qt_ir_commandline_option name)
+ # Define the main option
+ qt_ir_commandline_option_helper("${name}" ${ARGN})
+
+ qt_ir_commandline_option_parse_arguments(${ARGN})
+
+ # Define the short name option if it's requested
+ if(NOT "${arg_SHORT_NAME}" STREQUAL ""
+ AND "${commandline_option_${arg_SHORT_NAME}_type}" STREQUAL "")
+ set(unsupported "")
+ if(arg_UNSUPPORTED)
+ set(unsupported "${arg_UNSUPPORTED}")
+ endif()
+
+ qt_ir_commandline_option_helper("${arg_SHORT_NAME}"
+ TYPE "${arg_TYPE}"
+ ALIAS "${name}"
+ VALUE "${arg_VALUE}"
+ VALUES ${arg_VALUES}
+ MAPPING ${arg_MAPPING}
+ DEFAULT_VALUE ${arg_DEFAULT_VALUE}
+ ${unsupported}
+ )
+ endif()
+endmacro()
+
+# Saves the value of a command line option into a global property.
+function(qt_ir_command_line_set_input name val)
+ if(NOT "${commandline_option_${name}_alias}" STREQUAL "")
+ set(name "${commandline_option_${name}_alias}")
+ endif()
+
+ set_property(GLOBAL PROPERTY _qt_ir_input_${name} "${val}")
+ set_property(GLOBAL APPEND PROPERTY _qt_ir_inputs ${name})
+endfunction()
+
+# Appends a value of a command line option into a global property.
+# Currently unused
+function(qt_ir_command_line_append_input name val)
+ if(NOT "${commandline_option_${name}_alias}" STREQUAL "")
+ set(name "${commandline_option_${name}_alias}")
+ endif()
+
+ get_property(oldval GLOBAL PROPERTY _qt_ir_input_${name})
+ if(NOT "${oldval}" STREQUAL "")
+ string(PREPEND val "${oldval};")
+ endif()
+ qt_ir_command_line_set_input(${name} "${val}" )
+endfunction()
+
+# Checks if the value of a command line option is valid.
+function(qt_ir_validate_value opt val out_var)
+ set(${out_var} TRUE PARENT_SCOPE)
+
+ set(valid_values ${commandline_option_${arg}_values})
+ list(LENGTH valid_values n)
+ if(n EQUAL 0)
+ return()
+ endif()
+
+ foreach(v ${valid_values})
+ if(val STREQUAL v)
+ return()
+ endif()
+ endforeach()
+
+ set(${out_var} FALSE PARENT_SCOPE)
+ list(JOIN valid_values " " valid_values_str)
+ qt_ir_add_error("Invalid value '${val}' supplied to command line option '${opt}'."
+ "\nAllowed values: ${valid_values_str}\n")
+endfunction()
+
+# Sets / handles the value of a command line boolean option.
+function(qt_ir_commandline_boolean arg val nextok)
+ if("${val}" STREQUAL "")
+ set(val "yes")
+ endif()
+ if(NOT val STREQUAL "yes" AND NOT val STREQUAL "no")
+ message(FATAL_ERROR
+ "Invalid value '${val}' given for boolean command line option '${arg}'.")
+ endif()
+ qt_ir_command_line_set_input("${arg}" "${val}")
+endfunction()
+
+# Sets / handles the value of a command line string option.
+function(qt_ir_commandline_string arg val nextok)
+ if(nextok)
+ qt_ir_args_get_next_command_line_arg(val)
+
+ if("${val}" MATCHES "^-")
+ qt_ir_add_error("No value supplied to command line options '${arg}'.")
+ endif()
+ endif()
+ qt_ir_validate_value("${arg}" "${val}" success)
+ if(success)
+ qt_ir_command_line_set_input("${arg}" "${val}")
+ endif()
+endfunction()
+
+# Sets / handles the value of a command line void option.
+# This is an option like --force, which doesn't take any arguments.
+# Currently unused
+function(qt_ir_commandline_void arg val nextok)
+ if(NOT "${val}" STREQUAL "")
+ qt_i_add_error("Command line option '${arg}' expects no argument ('${val}' given).")
+ endif()
+ if(DEFINED commandline_option_${arg}_value)
+ set(val ${commandline_option_${arg}_value})
+ endif()
+ if("${val}" STREQUAL "")
+ set(val yes)
+ endif()
+ qt_ir_command_line_set_input("${arg}" "${val}")
+endfunction()
+
+# Reads the command line arguments from the optfile_path.
+function(qt_ir_get_raw_args_from_optfile optfile_path out_var)
+ file(STRINGS "${optfile_path}" args)
+ qt_ir_escape_semicolons(args "${args}")
+ set(${out_var} "${args}" PARENT_SCOPE)
+endfunction()
+
+# Reads the optfile_path, iterates over the given command line arguments,
+# sets the input for recongized options.
+#
+# Handles the following styles of CLI arguments:
+# --no-foo / --disable-foo
+# -no-foo / -disable-foo
+# --foo=<values>
+# --foo <values>
+# -foo <values>
+# --foo
+# -foo
+# --f
+# -f
+#
+# Currently handles the following types of CLI arguments:
+# string
+# boolean
+# void
+#
+# IGNORE_UNKNOWN_ARGS tells the function not to fail if it encounters an unknown
+# option, and instead append it to a global list of unknown options.
+# It is needed when the script is called from the configure script with
+# configure-only-known options.
+function(qt_ir_process_args_from_optfile optfile_path)
+ set(options IGNORE_UNKNOWN_ARGS)
+ set(oneValueArgs "")
+ set(multiValueArgs "")
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ qt_ir_get_raw_args_from_optfile("${optfile_path}" configure_args)
+ qt_ir_set_unhandled_args("${configure_args}")
+
+ while(1)
+ qt_ir_args_has_next_command_line_arg(has_next)
+ if(NOT has_next)
+ break()
+ endif()
+ qt_ir_args_get_next_command_line_arg(arg)
+
+ # parse out opt and val
+ set(nextok FALSE)
+ if(arg MATCHES "^--?(disable|no)-(.*)")
+ set(opt "${CMAKE_MATCH_2}")
+ set(val "no")
+ elseif(arg MATCHES "^--([^=]+)=(.*)")
+ set(opt "${CMAKE_MATCH_1}")
+ set(val "${CMAKE_MATCH_2}")
+ elseif(arg MATCHES "^--(.*)")
+ set(nextok TRUE)
+ set(opt "${CMAKE_MATCH_1}")
+ unset(val)
+ elseif(arg MATCHES "^-(.*)")
+ set(nextok TRUE)
+ set(opt "${CMAKE_MATCH_1}")
+ unset(val)
+ else()
+ if(NOT arg_IGNORE_UNKNOWN_ARGS)
+ qt_ir_add_error("Invalid command line parameter '${arg}'.")
+ else()
+ message(DEBUG "Unknown command line parameter '${arg}'. Collecting.")
+ qt_ir_append_unknown_args("${arg}")
+ continue()
+ endif()
+ endif()
+
+ set(type "${commandline_option_${opt}_type}")
+
+ if("${type}" STREQUAL "")
+ if(NOT arg_IGNORE_UNKNOWN_ARGS)
+ qt_ir_add_error("Unknown command line option '${arg}'.")
+ else()
+ message(DEBUG "Unknown command line option '${arg}'. Collecting.")
+ qt_ir_append_unknown_args("${arg}")
+ continue()
+ endif()
+ endif()
+
+ if(NOT COMMAND "qt_ir_commandline_${type}")
+ qt_ir_add_error("Unknown type '${type}' for command line option '${opt}'.")
+ endif()
+ qt_ir_call_function("qt_ir_commandline_${type}" "${opt}" "${val}" "${nextok}")
+ endwhile()
+endfunction()
+
+# Shows help for the command line options.
+function(qt_ir_show_help)
+ set(help_file "${CMAKE_CURRENT_LIST_DIR}/QtIRHelp.txt")
+ if(EXISTS "${help_file}")
+ file(READ "${help_file}" content)
+ message("${content}")
+ endif()
+
+ message([[
+General Options:
+-help, -h ............ Display this help screen
+]])
+endfunction()
+
+# Gets the unhandled command line args.
+function(qt_ir_get_unhandled_args out_var)
+ get_property(args GLOBAL PROPERTY _qt_ir_unhandled_args)
+ set(${out_var} "${args}" PARENT_SCOPE)
+endfunction()
+
+# Sets the unhandled command line args.
+function(qt_ir_set_unhandled_args args)
+ set_property(GLOBAL PROPERTY _qt_ir_unhandled_args "${args}")
+endfunction()
+
+# Adds to the unknown command line args.
+function(qt_ir_append_unknown_args args)
+ set_property(GLOBAL APPEND PROPERTY _qt_ir_unknown_args ${args})
+endfunction()
+
+# Gets the unhandled command line args.
+function(qt_ir_get_unknown_args out_var)
+ get_property(args GLOBAL PROPERTY _qt_ir_unknown_args)
+ set(${out_var} "${args}" PARENT_SCOPE)
+endfunction()
+
+# Gets the unsupported options that init-repository.pl supports, but the cmake port does
+# not support.
+function(qt_ir_get_unsupported_options out_var)
+ set(${out_var} "${commandline_known_unsupported_options}" PARENT_SCOPE)
+endfunction()
+
+# Get the value of a command line option.
+function(qt_ir_get_option_value name out_var)
+ if(NOT "${commandline_option_${name}_alias}" STREQUAL "")
+ set(name "${commandline_option_${name}_alias}")
+ endif()
+
+ get_property(value GLOBAL PROPERTY _qt_ir_input_${name})
+ set(${out_var} "${value}" PARENT_SCOPE)
+endfunction()
+
+# Set the value of a command line option manually.
+function(qt_ir_set_option_value name value)
+ if(NOT "${commandline_option_${name}_alias}" STREQUAL "")
+ set(name "${commandline_option_${name}_alias}")
+ endif()
+
+ qt_ir_command_line_set_input("${name}" "${value}")
+endfunction()
+
+# Get the value of a command line option as a cmakke flag option, to be passed
+# to functions that use cmake_parse_arguments.
+function(qt_ir_get_option_as_cmake_flag_option cli_name cmake_option_name out_var)
+ qt_ir_get_option_value("${cli_name}" bool_value)
+ set(cmake_option "")
+ if(bool_value)
+ set(cmake_option "${cmake_option_name}")
+ endif()
+ set(${out_var} "${cmake_option}" PARENT_SCOPE)
+endfunction()