KGC_TEST/KGCAPP/3rdparty/qwindowkit/qmsetup/cmake/modules/Preprocess.cmake

513 lines
16 KiB
CMake

#[[
Warning: This module depends on `qmcorecmd` after installation.
]] #
if(NOT QMSETUP_CORECMD_EXECUTABLE)
message(FATAL_ERROR "QMSETUP_CORECMD_EXECUTABLE not defined. Add find_package(qmsetup) to CMake first.")
endif()
if(NOT DEFINED QMSETUP_DEFINITION_NUMERICAL)
set(QMSETUP_DEFINITION_NUMERICAL off)
endif()
if(NOT DEFINED QMSETUP_DEFINITION_SCOPE)
set(QMSETUP_DEFINITION_SCOPE)
endif()
if(NOT DEFINED QMSETUP_DEFINITION_PROPERTY)
set(QMSETUP_DEFINITION_PROPERTY)
endif()
if(NOT DEFINED QMSETUP_SYNC_INCLUDE_STANDARD)
set(QMSETUP_SYNC_INCLUDE_STANDARD on)
endif()
include_guard(DIRECTORY)
#[[
Generate indirect reference files for header files to make the include statements more orderly.
The generated file has the same timestamp as the source file.
qm_sync_include(<src> <dest>
[STANDARD] [NO_STANDARD] [NO_ALL]
[INCLUDE <expr> <sub> ...]
[EXCLUDE <expr...>]
[INSTALL_DIR <dir>]
[FORCE] [VERBOSE]
)
STANDARD: Enable standard public-private pattern, can be forced to enable by enabling `QMSETUP_SYNC_INCLUDE_STANDARD`
NO_STANDARD: Disable standard public-private pattern, enable it to override `QMSETUP_SYNC_INCLUDE_STANDARD`
#]]
function(qm_sync_include _src_dir _dest_dir)
set(options FORCE VERBOSE NO_STANDARD NO_ALL)
set(oneValueArgs INSTALL_DIR)
set(multiValueArgs INCLUDE EXCLUDE)
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# Check tool
if(NOT QMSETUP_CORECMD_EXECUTABLE)
message(FATAL_ERROR "qm_sync_include: corecmd tool not found.")
endif()
if(NOT IS_ABSOLUTE ${_src_dir})
get_filename_component(_src_dir ${_src_dir} ABSOLUTE)
else()
string(REPLACE "\\" "/" _src_dir ${_src_dir})
endif()
if(NOT IS_ABSOLUTE ${_dest_dir})
get_filename_component(_dest_dir ${_dest_dir} ABSOLUTE)
else()
string(REPLACE "\\" "/" _dest_dir ${_dest_dir})
endif()
if(IS_DIRECTORY ${_src_dir})
file(GLOB_RECURSE header_files ${_src_dir}/*.h ${_src_dir}/*.hpp)
set(_args)
if(FUNC_STANDARD OR(QMSETUP_SYNC_INCLUDE_STANDARD AND NOT FUNC_NO_STANDARD))
list(APPEND _args -s)
endif()
if(FUNC_NO_ALL)
list(APPEND _args -n)
endif()
set(_even off)
foreach(_item IN LISTS FUNC_INCLUDE)
if(_even)
set(_even off)
list(APPEND _args ${_item})
else()
set(_even on)
list(APPEND _args -i ${_item})
endif()
endforeach()
foreach(_item IN LISTS FUNC_EXCLUDE)
list(APPEND _args -e ${_item})
endforeach()
if(FUNC_VERBOSE)
list(APPEND _args -V)
endif()
if(FUNC_FORCE OR NOT EXISTS ${_dest_dir})
if(EXISTS ${_dest_dir})
file(REMOVE_RECURSE ${_dest_dir})
endif()
execute_process(
COMMAND ${QMSETUP_CORECMD_EXECUTABLE} incsync ${_args} ${_src_dir} ${_dest_dir}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY
)
endif()
if(FUNC_INSTALL_DIR)
set(_install_dir ${FUNC_INSTALL_DIR})
set(_args_quoted)
foreach(_item IN LISTS _args)
set(_args_quoted "${_args_quoted}\"${_item}\" ")
endforeach()
# Get command output only and use file(INSTALL) to install files
install(CODE "
get_filename_component(_install_dir \"${_install_dir}\" ABSOLUTE BASE_DIR \${CMAKE_INSTALL_PREFIX})
execute_process(
COMMAND \"${QMSETUP_CORECMD_EXECUTABLE}\" incsync -d
${_args_quoted} \"${_src_dir}\" \${_install_dir}
WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"
OUTPUT_VARIABLE _output_contents
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
string(REPLACE \"\\n\" \";\" _lines \"\${_output_contents}\")
foreach(_line IN LISTS _lines)
string(REGEX MATCH \"from \\\"([^\\\"]*)\\\" to \\\"([^\\\"]*)\\\"\" _ \${_line})
get_filename_component(_target_path \${CMAKE_MATCH_2} DIRECTORY)
file(INSTALL \${CMAKE_MATCH_1} DESTINATION \${_target_path})
endforeach()
")
endif()
else()
message(FATAL_ERROR "qm_sync_include: source directory doesn't exist.")
endif()
endfunction()
#[[
Add a definition to a property scope.
qm_add_definition( <key | key=value> | <key> <value>
[GLOBAL | TARGET <target> | SOURCE <file> | DIRECTORY <dir>]
[PROPERTY <prop>]
[CONDITION <cond...>]
[STRING_LITERAL] [NO_KEYWORD]
[NUMERICAL] [CLASSICAL]
)
STRING_LITERAL: Force quotes on values
NO_KEYWORD: Treat any keyword as string
NUMERICAL: Use 1/-1 as defined/undefined, can be forced to enable by enabling `QMSETUP_DEFINITION_NUMERICAL`
CLASSICAL: Use classical definition, enable it to override `QMSETUP_DEFINITION_NUMERICAL`
]] #
function(qm_add_definition _first)
set(options STRING_LITERAL NO_KEYWORD NUMERICAL CLASSICAL)
set(oneValueArgs TARGET SOURCE DIRECTORY PROPERTY)
set(multiValueArgs CONDITION)
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(_result)
set(_is_pair off)
set(_defined off)
set(_list ${_first} ${FUNC_UNPARSED_ARGUMENTS})
list(LENGTH _list _len)
set(_cond on)
set(_numerical off)
if(NOT FUNC_CLASSICAL AND(QMSETUP_DEFINITION_NUMERICAL OR FUNC_NUMERICAL))
set(_numerical on)
endif()
if(FUNC_CONDITION)
if(NOT(${FUNC_CONDITION}))
set(_cond off)
endif()
elseif(DEFINED FUNC_CONDITION)
set(_cond off)
endif()
if(${_len} EQUAL 1)
set(_result ${_list})
set(_defined on)
if(NOT _cond)
set(_defined off)
endif()
elseif(${_len} EQUAL 2)
# Get key
list(POP_FRONT _list _key)
list(POP_FRONT _list _val)
if(FUNC_STRING_LITERAL AND NOT ${_val} MATCHES "\".+\"")
set(_val "\"${_val}\"")
endif()
# Boolean
string(TOLOWER ${_val} _val_lower)
if(NOT FUNC_NO_KEYWORD AND(${_val_lower} STREQUAL "off" OR ${_val_lower} STREQUAL "false"))
set(_result ${_key})
set(_defined off)
if(NOT _cond)
set(_defined on)
endif()
elseif(NOT FUNC_NO_KEYWORD AND(${_val_lower} STREQUAL "on" OR ${_val_lower} STREQUAL "true"))
set(_result ${_key})
set(_defined on)
if(NOT _cond)
set(_defined off)
endif()
else()
set(_result "${_key}=${_val}")
set(_is_pair on)
set(_defined on)
if(NOT _cond)
set(_defined off)
endif()
endif()
else()
message(FATAL_ERROR "qm_add_definition: called with incorrect number of arguments")
endif()
if(_numerical AND NOT _is_pair)
if(_defined)
set(_result "${_result}=1")
else()
set(_result "${_result}=-1")
endif()
elseif(NOT _defined)
return()
endif()
_qm_calc_property_scope_helper(_scope _prop)
set_property(${_scope} APPEND PROPERTY ${_prop} "${_result}")
endfunction()
#[[
Remove a definition from a property scope.
qm_remove_definition(<key>
[GLOBAL | TARGET <target> | SOURCE <file> | DIRECTORY <dir>]
[PROPERTY <prop>]
)
]] #
function(qm_remove_definition _key)
set(options)
set(oneValueArgs TARGET PROPERTY)
set(multiValueArgs)
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(FUNC_TARGET)
get_target_property(_definitions ${FUNC_TARGET} ${_prop})
else()
get_property(_definitions GLOBAL PROPERTY ${_prop})
endif()
# Filter
list(FILTER _definitions EXCLUDE REGEX "^${_key}(=.*)?$")
_qm_calc_property_scope_helper(_scope _prop)
set_property(${_scope} PROPERTY ${_prop} "${_definitions}")
endfunction()
#[[
Generate a configuration header of a property scope. If the configuration has not changed,
the generated file's timestemp will not be updated when you reconfigure it.
qm_generate_config(<file>
[GLOBAL | TARGET <target> | SOURCE <file> | DIRECTORY <dir>]
[PROPERTY <prop>]
[PROJECT_NAME <name>]
[WARNING_FILE <file>]
[NO_WARNING]
[NO_HASH]
)
]] #
function(qm_generate_config _file)
set(options NO_WARNING NO_HASH)
set(oneValueArgs TARGET PROPERTY PROJECT_NAME WARNING_FILE)
set(multiValueArgs)
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
_qm_calc_property_scope_helper(_scope _prop)
get_property(_definitions ${_scope} PROPERTY ${_prop})
if(NOT _definitions)
set(_definitions) # May be _-NOTFOUND
endif()
_qm_generate_config_helper()
endfunction()
#[[
Generate build info information header.
qm_generate_build_info(<file>
[ROOT_DIRECTORY <dir>]
[PREFIX <prefix>]
[YEAR] [TIME]
[PROJECT_NAME <name>]
[WARNING_FILE <file>]
[NO_WARNING]
[NO_HASH]
[REQUIRED]
)
file: Output file
ROOT_DIRECTORY: Repository root directory (CMake will try to run `git` at this directory)
PREFIX: Macros prefix, default to `PROJECT_NAME`
REQUIRED: Abort if there's any error with git
]] #
function(qm_generate_build_info _file)
set(options NO_WARNING NO_HASH YEAR TIME REQUIRED)
set(oneValueArgs ROOT_DIRECTORY PREFIX PROJECT_NAME WARNING_FILE)
set(multiValueArgs)
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(FUNC_PREFIX)
set(_prefix ${FUNC_PREFIX})
else()
string(TOUPPER "${PROJECT_NAME}" _prefix)
endif()
set(_dir)
qm_set_value(_dir FUNC_ROOT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(_git_branch "unknown")
set(_git_hash "unknown")
set(_git_commit_time "unknown")
set(_git_commit_author "unknown")
set(_git_commit_email "unknown")
find_package(Git QUIET)
if(Git_FOUND)
# Branch
execute_process(
COMMAND ${GIT_EXECUTABLE} symbolic-ref --short -q HEAD
OUTPUT_VARIABLE _temp
ERROR_VARIABLE _err
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY ${_dir}
RESULT_VARIABLE _code
)
if(${_code} EQUAL 0)
set(_git_branch ${_temp})
elseif(FUNC_REQUIRED)
message(FATAL_ERROR "${_err}")
endif()
# Hash
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 "--pretty=format:%H;%aI;%aN;%aE" # Use `;` as separator
OUTPUT_VARIABLE _temp
ERROR_VARIABLE _err
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY ${_dir}
RESULT_VARIABLE _code
)
if(${_code} EQUAL 0)
list(GET _temp 0 _git_hash)
list(GET _temp 1 _git_commit_time)
list(GET _temp 2 _git_commit_author)
list(GET _temp 3 _git_commit_email)
elseif(FUNC_REQUIRED)
message(FATAL_ERROR "${_err}")
endif()
elseif(FUNC_REQUIRED)
message(FATAL_ERROR "Git not found")
endif()
qm_set_value(_system_name CMAKE_SYSTEM_NAME unknown)
qm_set_value(_system_version CMAKE_SYSTEM_VERSION unknown)
qm_set_value(_system_processor CMAKE_SYSTEM_PROCESSOR unknown)
qm_set_value(_host_system_name CMAKE_HOST_SYSTEM_NAME unknown)
qm_set_value(_host_system_version CMAKE_HOST_SYSTEM_VERSION unknown)
qm_set_value(_host_system_processor CMAKE_HOST_SYSTEM_PROCESSOR unknown)
qm_set_value(_compiler_name CMAKE_CXX_COMPILER_ID unknown)
qm_set_value(_compiler_version CMAKE_CXX_COMPILER_VERSION unknown)
qm_set_value(_compiler_arch CMAKE_CXX_COMPILER_ARCHITECTURE_ID unknown)
qm_set_value(_compiler_abi CMAKE_CXX_COMPILER_ABI unknown)
set(_definitions)
set(_has_time off)
# year
if(FUNC_YEAR)
string(TIMESTAMP _build_year "%Y")
list(APPEND _definitions ${_prefix}_BUILD_YEAR=\"${_build_year}\")
set(_has_time on)
endif()
# time
if(FUNC_TIME)
string(TIMESTAMP _build_time "%Y/%m/%d %H:%M:%S")
list(APPEND _definitions ${_prefix}_BUILD_TIME=\"${_build_time}\")
set(_has_time on)
endif()
if(_has_time)
list(APPEND _definitions "%")
endif()
# system
list(APPEND _definitions ${_prefix}_SYSTEM_NAME=\"${_system_name}\")
list(APPEND _definitions ${_prefix}_SYSTEM_VERSION=\"${_system_version}\")
list(APPEND _definitions ${_prefix}_SYSTEM_PROCESSOR=\"${_system_processor}\")
list(APPEND _definitions ${_prefix}_HOST_SYSTEM_NAME=\"${_host_system_name}\")
list(APPEND _definitions ${_prefix}_HOST_SYSTEM_VERSION=\"${_host_system_version}\")
list(APPEND _definitions ${_prefix}_HOST_SYSTEM_PROCESSOR=\"${_host_system_processor}\")
list(APPEND _definitions "%")
# compiler
list(APPEND _definitions ${_prefix}_COMPILER_ID=\"${_compiler_name}\")
list(APPEND _definitions ${_prefix}_COMPILER_VERSION=\"${_compiler_version}\")
list(APPEND _definitions ${_prefix}_COMPILER_ARCH=\"${_compiler_arch}\")
list(APPEND _definitions ${_prefix}_COMPILER_ABI=\"${_compiler_abi}\")
list(APPEND _definitions "%")
# build time (deprecated)
# list(APPEND _definitions ${_prefix}_BUILD_DATE_TIME=\"${_build_time}\")
# list(APPEND _definitions ${_prefix}_BUILD_YEAR=\"${_build_year}\")
# list(APPEND _definitions "%")
# git info
list(APPEND _definitions ${_prefix}_GIT_BRANCH=\"${_git_branch}\")
list(APPEND _definitions ${_prefix}_GIT_LAST_COMMIT_HASH=\"${_git_hash}\")
list(APPEND _definitions ${_prefix}_GIT_LAST_COMMIT_TIME=\"${_git_commit_time}\")
list(APPEND _definitions ${_prefix}_GIT_LAST_COMMIT_AUTHOR=\"${_git_commit_author}\")
list(APPEND _definitions ${_prefix}_GIT_LAST_COMMIT_EMAIL=\"${_git_commit_email}\")
_qm_generate_config_helper()
endfunction()
# ----------------------------------
# Private functions
# ----------------------------------
function(_qm_calc_property_scope_helper _scope _prop)
if(FUNC_TARGET)
set(_scope TARGET ${FUNC_TARGET})
elseif(FUNC_SOURCE)
set(_scope SOURCE ${FUNC__SOURCE})
elseif(FUNC_DIRECTORY)
set(_scope DIRECTORY ${FUNC_DIRECTORY})
elseif(FUNC_GLOBAL)
set(_scope GLOBAL)
elseif(QMSETUP_DEFINITION_SCOPE)
set(_scope ${QMSETUP_DEFINITION_SCOPE})
else()
set(_scope GLOBAL)
endif()
qm_set_value(_prop FUNC_PROPERTY QMSETUP_DEFINITION_PROPERTY "CONFIG_DEFINITIONS")
set(_scope ${_scope} PARENT_SCOPE)
set(_prop ${_prop} PARENT_SCOPE)
endfunction()
function(_qm_generate_config_helper)
set(_args)
foreach(_item IN LISTS _definitions)
list(APPEND _args "-D${_item}")
endforeach()
list(APPEND _args ${_file})
if(NOT FUNC_NO_WARNING)
list(APPEND _args "-w" ${FUNC_WARNING_FILE})
endif()
if(FUNC_PROJECT_NAME)
list(APPEND _args "-p" ${FUNC_PROJECT_NAME})
endif()
if(FUNC_NO_HASH)
list(APPEND _args "-f")
endif()
execute_process(COMMAND ${QMSETUP_CORECMD_EXECUTABLE} configure ${_args}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY
)
endfunction()