Skip to content

Commit

Permalink
add help_options() function, rework multi_option.cmake to option.cmak… (
Browse files Browse the repository at this point in the history
  • Loading branch information
Risto97 authored Sep 24, 2024
1 parent 2215ce9 commit 41b8425
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 36 deletions.
2 changes: 1 addition & 1 deletion SoCMakeConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/add_subdirs.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/get_all_targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/print_help.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/graphviz.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/multi_option.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/option.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/find_python.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/cmake/utils/print_list.cmake")

Expand Down
30 changes: 0 additions & 30 deletions cmake/utils/multi_option.cmake

This file was deleted.

87 changes: 87 additions & 0 deletions cmake/utils/option.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
function(__define_socmake_option NAME TYPE DESCRIPTION DEFAULT)
cmake_parse_arguments(ARG "" "" "POSSIBLE_VALUES" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}")
endif()

set_property(GLOBAL PROPERTY SOCMAKE_${NAME}_DESCRIPTION "${DESCRIPTION}")
set_property(GLOBAL PROPERTY SOCMAKE_${NAME}_TYPE ${TYPE})
set_property(GLOBAL PROPERTY SOCMAKE_${NAME}_DEFAULT ${DEFAULT})
if(ARG_POSSIBLE_VALUES)
set_property(GLOBAL PROPERTY SOCMAKE_${NAME}_VALUES ${ARG_POSSIBLE_VALUES})
endif()
set_property(GLOBAL APPEND PROPERTY SOCMAKE_OPTIONS ${NAME})
endfunction()

#[[[
# Create a CMake integer option that can be modified through CLI.
# Option defined this way will be visible in `cmake-gui` interface as well as SoCMake `help_options()` help menu.
# To override the variable use `cmake -D<VARIABLE>=<VALUE>`
#
# :param VARIABLE: name of the variable.
# :type VARIABLE: string
# :param DESCRIPTION: short description string for the variable
# :type DESCRIPTION: string
# :param ENUM_VALUES: possible values variable can have
# :type ENUM_VALUES: list[string]
# :param DEFAULT: default value of the variable
# :type DEFAULT: integer
#]]
function(option_enum VARIABLE DESCRIPTION ENUM_VALUES DEFAULT)
__define_socmake_option(${VARIABLE} "Enum" ${DESCRIPTION} ${DEFAULT} POSSIBLE_VALUES "${ENUM_VALUES}")

set(${VARIABLE} ${DEFAULT} CACHE STRING "${DESCRIPTION}")
set_property(CACHE ${VARIABLE} PROPERTY STRINGS "${ENUM_VALUES}")
if(NOT ${VARIABLE})
set(${VARIABLE} ${DEFAULT})
set(${VARIABLE} ${DEFAULT} PARENT_SCOPE)
endif()
if(NOT "${${VARIABLE}}" IN_LIST ENUM_VALUES)
message(FATAL_ERROR "The VARIABLE \"${VARIABLE}\" has an unknown value: ${${VARIABLE}}\nPossible values are: ${ENUM_VALUES}")
endif()
endfunction()

function(option_string VARIABLE DESCRIPTION DEFAULT)
__define_socmake_option(${VARIABLE} "String" ${DESCRIPTION} ${DEFAULT})

set(${VARIABLE} ${DEFAULT} CACHE STRING "${DESCRIPTION}")
endfunction()

#[[[
# Create a CMake integer option that can be modified through CLI.
# Option defined this way will be visible in `cmake-gui` interface as well as SoCMake `help_options()` help menu.
# To override the variable use `cmake -D<VARIABLE>=<VALUE>`
#
# :param VARIABLE: name of the variable.
# :type VARIABLE: string
# :param DESCRIPTION: short description string for the variable
# :type DESCRIPTION: string
# :param DEFAULT: default value of the variable
# :type DEFAULT: integer
#]]
function(option_integer VARIABLE DESCRIPTION DEFAULT)
__define_socmake_option(${VARIABLE} "Integer" ${DESCRIPTION} ${DEFAULT})

set(${VARIABLE} ${DEFAULT} CACHE STRING "${DESCRIPTION}")
if(NOT ${${VARIABLE}} MATCHES "^[0-9]+$")
message(FATAL_ERROR "The value of option \"${VARIABLE}\" must be a non-negative integer.")
endif()
endfunction()

#[[[
# Create a CMake boolean option that can be modified through CLI.
# Option defined this way will be visible in `cmake-gui` interface as well as SoCMake `help_options()` help menu.
# To override the variable use `cmake -D<VARIABLE>=<VALUE>`
#
# :param VARIABLE: name of the variable.
# :type VARIABLE: string
# :param DESCRIPTION: short description string for the variable
# :type DESCRIPTION: string
# :param DEFAULT: default value of the variable
# :type DEFAULT: boolean
#]]
function(option_boolean VARIABLE DESCRIPTION DEFAULT)
__define_socmake_option(${VARIABLE} "Boolean" ${DESCRIPTION} ${DEFAULT} POSSIBLE_VALUES "ON;OFF")

set(${VARIABLE} ${DEFAULT} CACHE STRING "${DESCRIPTION}")
endfunction()
162 changes: 160 additions & 2 deletions cmake/utils/print_help.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ function(__find_longest_target_name TYPE OUTVAR)
set(${OUTVAR} ${__max_length} PARENT_SCOPE)
endfunction()

function(__find_longest_string OUTVAR)
set(__max_length 0)
foreach(var ${ARGN})
string(LENGTH ${var} str_length)
if(${str_length} GREATER ${__max_length})
set(__max_length ${str_length})
endif()
endforeach()
set(${OUTVAR} ${__max_length} PARENT_SCOPE)
endfunction()

function(__get_target_help OUTVAR TARGET DESCRIPTION COL_WIDTH)

# Get the length of the target string
Expand Down Expand Up @@ -140,9 +151,9 @@ function(help_ips)
get_all_targets(ALL_TARGETS)
__find_longest_target_name(INTERFACE_LIBRARY MAX_LEN ${ALL_TARGETS})

math(EXPR padding_length "${MAX_LEN} + 14")
math(EXPR padding_length "${MAX_LEN} + 18")
string(REPEAT " " ${padding_length} padding)
string(APPEND OUT_STRING "${Yellow}Target${padding}Description${ColourReset}\n")
string(APPEND OUT_STRING "${Yellow}IP${padding}Description${ColourReset}\n")
math(EXPR line_length "${MAX_LEN} + 50")
string(REPEAT "-" ${line_length} line)
string(APPEND OUT_STRING "${line}\n")
Expand Down Expand Up @@ -172,6 +183,146 @@ function(help_ips)
set_property(TARGET help_ips PROPERTY DESCRIPTION ${DESCRIPTION})
endfunction()

function(__get_help_option_string OUTSTR VALUE MAX_STR_LEN)
cmake_parse_arguments(ARG "" "COLOUR" "" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}")
endif()

string(LENGTH ${VALUE} option_len)
math(EXPR padding_len "${MAX_STR_LEN} - ${option_len}")
string(REPEAT " " ${padding_len} padding)

set(__out_str ${${ARG_COLOUR}}${VALUE}${ColourReset}${padding})

set(${OUTSTR} ${__out_str} PARENT_SCOPE)
endfunction()

# [[[
# This function creates a help target for printing CMake options information.
# The options need to be added with the SoCMake options_boolean/options_integer/options_string/options_enum functions.
#
# It should be called only once in the build flow.
#
# Preferably at the end of the CMakeLists.txt
#
# In order to run it only once at the top level, following trick can be used.
#```
# if(PROJECT_IS_TOP_LEVEL)
# help_options()
# endif()
#```
#
# **Keyword Arguments**
#
# :keyword PRINT_ON_CONF: Print the help message during configure phase
# :type PRINT_ON_CONF: boolean
# ]]]
function(help_options)
cmake_parse_arguments(ARG "PRINT_ON_CONF" "" "" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} passed unrecognized argument " "${ARG_UNPARSED_ARGUMENTS}")
endif()
include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/colours.cmake)

unset(OUT_STRING)
string(APPEND OUT_STRING "${Yellow}Available Options:${ColourReset}\n")
string(APPEND OUT_STRING "------------------\n")
string(APPEND OUT_STRING "\n")

get_property(ALL_OPTIONS GLOBAL PROPERTY SOCMAKE_OPTIONS)
# get_all_targets(ALL_TARGETS)
__find_longest_string(MAX_OPTIONS_LEN "Option;${ALL_OPTIONS}")

unset(list_defaults)
unset(list_possible_values)
unset(list_curr_values)
foreach(option ${ALL_OPTIONS})
get_property(default GLOBAL PROPERTY SOCMAKE_${option}_DEFAULT)
list(APPEND list_defaults ${default})

get_property(values GLOBAL PROPERTY SOCMAKE_${option}_VALUES)
string(REPLACE ";" "," values "${values}")
list(APPEND list_possible_values ${values})

list(APPEND list_curr_values ${${option}})
endforeach()
__find_longest_string(MAX_DEFAULT_LEN "Default;${list_defaults}")
__find_longest_string(MAX_POSSIBLE_VALUES_LEN "Values;${list_possible_values}")
__find_longest_string(MAX_CURRENT_VALUES_LEN "Current value;${list_curr_values}")

math(EXPR option_str_space "${MAX_OPTIONS_LEN} + 5") # 5 is spacing
math(EXPR option_padding_len "${option_str_space} - 6") # 6 is len of "Option"
string(REPEAT " " ${option_padding_len} padding_option)

__find_longest_string(MAX_TYPE_LEN "Type;Boolean;String;Integer;Enum")
math(EXPR type_str_space "${MAX_TYPE_LEN} + 5")
math(EXPR type_padding_len "${type_str_space} - 4") # 4 is len of "Type"
string(REPEAT " " ${type_padding_len} padding_type)

math(EXPR current_value_str_space "${MAX_CURRENT_VALUES_LEN} + 5")
math(EXPR current_value_padding_len "${current_value_str_space} - 13") # 7 is len of "Current Value"
string(REPEAT " " ${current_value_padding_len} padding_current_value)

math(EXPR default_str_space "${MAX_DEFAULT_LEN} + 5")
math(EXPR default_padding_len "${default_str_space} - 7") # 7 is len of "Default"
string(REPEAT " " ${default_padding_len} padding_default)

math(EXPR possible_values_str_space "${MAX_POSSIBLE_VALUES_LEN} + 7")
math(EXPR possible_values_padding_len "${possible_values_str_space} - 6") # 6 is len of "Values"
string(REPEAT " " ${possible_values_padding_len} padding_possible_values)

string(APPEND OUT_STRING "${Yellow}Option${padding_option}Type${padding_type}Current value${padding_current_value}Default${padding_default}Values${padding_possible_values}Description${ColourReset}\n")
math(EXPR line_length "${MAX_OPTIONS_LEN} + 100")
string(REPEAT "-" ${line_length} line)
string(APPEND OUT_STRING "${line}\n")

foreach(option ${ALL_OPTIONS})
get_property(type GLOBAL PROPERTY SOCMAKE_${option}_TYPE)
get_property(description GLOBAL PROPERTY SOCMAKE_${option}_DESCRIPTION)
get_property(default GLOBAL PROPERTY SOCMAKE_${option}_DEFAULT)
get_property(values GLOBAL PROPERTY SOCMAKE_${option}_VALUES)

__get_help_option_string(__out_str ${option} ${option_str_space} COLOUR Cyan)
string(APPEND OUT_STRING ${__out_str})

__get_help_option_string(__out_str ${type} ${type_str_space})
string(APPEND OUT_STRING ${__out_str})

__get_help_option_string(__out_str ${${option}} ${current_value_str_space})
string(APPEND OUT_STRING ${__out_str})

__get_help_option_string(__out_str ${default} ${default_str_space})
string(APPEND OUT_STRING ${__out_str})

if(values)
set(values "[${values}]")
string(REPLACE ";" "," values "${values}")
else()
set(values " ")
endif()

__get_help_option_string(__out_str ${values} ${possible_values_str_space})
string(APPEND OUT_STRING ${__out_str})

string(APPEND OUT_STRING "${description}\n")

endforeach()
string(APPEND OUT_STRING "${line}\n")

if(ARG_PRINT_ON_CONF)
message("${OUT_STRING}")
endif()

set(DESCRIPTION "Print Options help")
file(WRITE ${PROJECT_BINARY_DIR}/help_options.txt ${OUT_STRING})
add_custom_target(help_options
COMMAND cat ${PROJECT_BINARY_DIR}/help_options.txt
COMMENT ${DESCRIPTION}
)
set_property(TARGET help_options PROPERTY DESCRIPTION ${DESCRIPTION})
endfunction()

# [[[
# This function creates a help target for printing target and IPs information.
#
Expand Down Expand Up @@ -202,11 +353,18 @@ function(help)
set(ARG_PRINT_ON_CONF PRINT_ON_CONF)
endif()

get_property(ALL_OPTIONS GLOBAL PROPERTY SOCMAKE_OPTIONS)

help_ips(${ARG_PRINT_ON_CONF})
help_targets(${ARG_PRINT_ON_CONF})

add_custom_target(help_all
DEPENDS help_targets help_ips
)

if(ALL_OPTIONS)
help_options(${ARG_PRINT_ON_CONF})
add_dependencies(help_all help_options)
endif()

endfunction()
1 change: 0 additions & 1 deletion tests/add_ip/add_ip_fail_3_tokens.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,3 @@ ct_add_test(NAME ${TEST_NAME} EXPECTFAIL)
function(${${TEST_NAME}})
add_ip(vendor::::)
endfunction()

2 changes: 0 additions & 2 deletions tests/add_ip/add_ip_fail_4_tokens.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,3 @@ ct_add_test(NAME ${TEST_NAME} EXPECTFAIL)
function(${${TEST_NAME}})
add_ip(vendor::lib::ip::)
endfunction()


0 comments on commit 41b8425

Please sign in to comment.