diff --git a/cmake/scripts/GenerateWidget.cmake b/cmake/scripts/GenerateWidget.cmake new file mode 100644 --- /dev/null +++ b/cmake/scripts/GenerateWidget.cmake @@ -0,0 +1,119 @@ +cmake_minimum_required(VERSION 3.5) + +# +# CMake script to automatically generate the enums in script_window.hpp +# +# The file is scanned for @enum tokens, and the placeholder is filled with an enum from a different file. +# +# Example: +# // @enum enumname filename@placeholder@ +# ... content here is replaced ... +# // @endenum +# +# The parameter "enumname" specifies the enumeration to extract. This can also be a regular expression. +# The parameter "filename" specifies the relative path to the file, where the enumeration is extracted from. This can also be a glob expression. +# +# + +if (NOT GENERATE_SOURCE_FILE) + message(FATAL_ERROR "Script needs GENERATE_SOURCE_FILE defined") +endif (NOT GENERATE_SOURCE_FILE) +if (NOT GENERATE_BINARY_FILE) + message(FATAL_ERROR "Script needs GENERATE_BINARY_FILE defined") +endif (NOT GENERATE_BINARY_FILE) + +file(STRINGS ${GENERATE_SOURCE_FILE} ENUM_LINES REGEX "@enum") + +foreach(ENUM IN LISTS ENUM_LINES) + string(REGEX REPLACE "^( )// @enum ([^ ]+) ([^ ]+)@([^ ]+)@" "\\4" PLACE_HOLDER "${ENUM}") + set(ADD_INDENT "${CMAKE_MATCH_1}") + set(ENUM_PATTERN "${CMAKE_MATCH_2}") + + file(GLOB FILENAMES "${CMAKE_MATCH_3}") + list(SORT FILENAMES) + + foreach(FILE IN LISTS FILENAMES) + unset(ACTIVE) + unset(ACTIVE_COMMENT) + unset(COMMENT) + + file(STRINGS ${FILE} SOURCE_LINES) + + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" FILE ${FILE}) + string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}/* automatically generated from ${FILE} */") + + foreach(LINE IN LISTS SOURCE_LINES) + string(REPLACE "${RM_INDENT}" "" LINE "${LINE}") + + # Remember possible doxygen comment before enum declaration + if ((NOT ACTIVE) AND "${LINE}" MATCHES "/\\*\\*") + set(COMMENT "${ADD_INDENT}${LINE}") + set(ACTIVE_COMMENT 1) + elseif (ACTIVE_COMMENT EQUAL 1) + string(APPEND COMMENT "\n${ADD_INDENT}${LINE}") + endif() + + # Check for enum match + if ("${LINE}" MATCHES "^ *enum *${ENUM_PATTERN} *\{") + # REGEX REPLACE does a REGEX MATCHALL and fails if an empty string is matched + string(REGEX MATCH "[^ ]*" RESULT "${LINE}") + string(REPLACE "${RESULT}" "" RM_INDENT "${LINE}") + + set(ACTIVE 1) + if (ACTIVE_COMMENT GREATER 0) + string(APPEND ${PLACE_HOLDER} "\n${COMMENT}") + endif (ACTIVE_COMMENT GREATER 0) + unset(ACTIVE_COMMENT) + unset(COMMENT) + endif ("${LINE}" MATCHES "^ *enum *${ENUM_PATTERN} *\{") + + # Forget doxygen comment, if no enum follows + if (ACTIVE_COMMENT EQUAL 2 AND NOT "${LINE}" STREQUAL "") + unset(ACTIVE_COMMENT) + unset(COMMENT) + endif (ACTIVE_COMMENT EQUAL 2 AND NOT "${LINE}" STREQUAL "") + if (ACTIVE_COMMENT EQUAL 1 AND "${LINE}" MATCHES "\\*/") + set(ACTIVE_COMMENT 2) + endif (ACTIVE_COMMENT EQUAL 1 AND "${LINE}" MATCHES "\\*/") + + if (ACTIVE) + if ("${LINE}" MATCHES "^ *[A-Za-z0-9_]* *[,=]") + # Transform enum values + # REGEX REPLACE does a REGEX MATCHALL and replaces too much + string(REGEX MATCH " *=[^,]*" RESULT "${LINE}") + string(REPLACE "${RESULT}" "" LINE "${LINE}") + + string(REGEX REPLACE " *//" " //" LINE "${LINE}") + + string(REGEX MATCH "^( *)([A-Za-z0-9_]+),(.*)" RESULT "${LINE}") + + string(LENGTH "${CMAKE_MATCH_2}" LEN) + math(EXPR LEN "43 - ${LEN}") + unset(SPACES) + foreach(i RANGE ${LEN}) + string(APPEND SPACES " ") + endforeach(i) + + if (CMAKE_MATCH_3) + string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = ::${CMAKE_MATCH_2},${SPACES}${CMAKE_MATCH_3}") + else (CMAKE_MATCH_3) + string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${CMAKE_MATCH_1}${CMAKE_MATCH_2}${SPACES} = ::${CMAKE_MATCH_2},") + endif (CMAKE_MATCH_3) + elseif ("${LINE}" STREQUAL "") + string(APPEND ${PLACE_HOLDER} "\n") + else () + string(APPEND ${PLACE_HOLDER} "\n${ADD_INDENT}${LINE}") + endif () + endif (ACTIVE) + + if ("${LINE}" MATCHES "^ *\};") + if (ACTIVE) + string(APPEND ${PLACE_HOLDER} "\n") + endif (ACTIVE) + unset(ACTIVE) + endif ("${LINE}" MATCHES "^ *\};") + endforeach(LINE) + endforeach(FILE) + endforeach(ENUM) + +configure_file(${GENERATE_SOURCE_FILE} ${GENERATE_BINARY_FILE})