This commit is contained in:
Yuhang Zhao 2023-09-08 18:12:27 +08:00
parent a0d72f177e
commit 583c07ad29
1 changed files with 400 additions and 1 deletions

View File

@ -106,7 +106,7 @@ function(compute_install_dir)
endfunction()
function(setup_project)
cmake_parse_arguments(PROJ_ARGS "QT_PROJECT;ENABLE_LTO;WARNINGS_ARE_ERRORS;MAX_WARNING;NO_WARNING;RTTI;EXCEPTIONS" "QML_IMPORT_DIR" "LANGUAGES" ${ARGN})
cmake_parse_arguments(PROJ_ARGS "QT_PROJECT;ENABLE_LTO;WARNINGS_ARE_ERRORS;MAX_WARNING;NO_WARNING;RTTI;EXCEPTIONS" "QML_IMPORT_DIR;LICENSE_HEADER;MODIFY_LOST_WARNING;CONFIG_PREFIX;VERSION_PREFIX" "LANGUAGES" ${ARGN})
if(NOT PROJ_ARGS_LANGUAGES)
message(AUTHOR_WARNING "setup_project: You need to specify at least one language for this function!")
return()
@ -524,6 +524,22 @@ function(setup_project)
endif()
endif()
endforeach()
set(__meta_target ${PROJECT_NAME}_METADATA)
if(NOT TARGET ${__meta_target})
add_custom_target(${__meta_target})
endif()
if(arg_LICENSE_HEADER)
set_target_properties(${__meta_target} PROPERTIES __PROJECT_LICENSE_HEADER "${arg_LICENSE_HEADER}")
endif()
if(arg_MODIFY_LOST_WARNING)
set_target_properties(${__meta_target} PROPERTIES __PROJECT_MODIFY_LOST_WARNING "${arg_MODIFY_LOST_WARNING}")
endif()
if(arg_CONFIG_PREFIX)
set_target_properties(${__meta_target} PROPERTIES __PROJECT_CONFIG_PREFIX "${arg_CONFIG_PREFIX}")
endif()
if(arg_VERSION_PREFIX)
set_target_properties(${__meta_target} PROPERTIES __PROJECT_VERSION_PREFIX "${arg_VERSION_PREFIX}")
endif()
endfunction()
function(get_commit_hash)
@ -1913,3 +1929,386 @@ function(setup_target_rpaths)
endif()
endforeach()
endfunction()
function(add_project_config)
set(__target ${PROJECT_NAME}_METADATA)
if(NOT TARGET ${__target})
message(AUTHOR_WARNING "add_project_config: You need to call setup_project() first!")
return()
endif()
cmake_parse_arguments(arg "" "KEY;VALUE" "" ${ARGN})
if(NOT arg_KEY)
message(AUTHOR_WARNING "add_project_config: You need to specify the KEY name!")
return()
endif()
if(NOT arg_VALUE)
message(AUTHOR_WARNING "add_project_config: You need to specify the VALUE value!")
return()
endif()
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "add_project_config: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
set(__prefix "")
get_target_property(__prefix ${__target} __PROJECT_CONFIG_PREFIX)
if("x${__prefix}" STREQUAL "x")
set(__prefix "${PROJECT_NAME}_FEATURE")
message(AUTHOR_WARNING "add_project_config: config prefix is not set, using ${__prefix} as default.")
endif()
set_property(TARGET ${__target} APPEND PROPERTY __PROJECT_CONFIG_OPTIONS "${__prefix}_${arg_KEY}=${arg_VALUE}")
endfunction()
function(enable_project_config)
cmake_parse_arguments(arg "" "KEY" "" ${ARGN})
if(NOT arg_KEY)
message(AUTHOR_WARNING "enable_project_config: You need to specify the KEY name!")
return()
endif()
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "enable_project_config: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
add_project_config(KEY "${arg_KEY}" TRUE)
endfunction()
function(disable_project_config)
cmake_parse_arguments(arg "" "KEY" "" ${ARGN})
if(NOT arg_KEY)
message(AUTHOR_WARNING "disable_project_config: You need to specify the KEY name!")
return()
endif()
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "disable_project_config: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
add_project_config(KEY "${arg_KEY}" FALSE)
endfunction()
function(generate_project_config)
set(__target ${PROJECT_NAME}_METADATA)
if(NOT TARGET ${__target})
message(AUTHOR_WARNING "generate_project_config: You need to call setup_project() first!")
return()
endif()
cmake_parse_arguments(arg "OVERWRITE" "PATH" "" ${ARGN})
if(NOT arg_PATH)
message(AUTHOR_WARNING "generate_project_config: You need to specify the file path!")
return()
endif()
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "generate_project_config: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
if(EXISTS "${arg_PATH}" AND NOT arg_OVERWRITE)
return()
endif()
set(__raw_options "")
get_target_property(__raw_options ${__target} __PROJECT_CONFIG_OPTIONS)
if("x${__raw_options}" STREQUAL "x")
message(AUTHOR_WARNING "generate_project_config: You need to specify at least one configuration option!")
return()
endif()
set(__license_header "")
get_target_property(__license_header ${__target} __PROJECT_LICENSE_HEADER)
if("x${__license_header}" STREQUAL "x")
message(AUTHOR_WARNING "generate_project_config: The license header is not set.")
endif()
set(__modify_lost_warning "")
get_target_property(__modify_lost_warning ${__target} __PROJECT_MODIFY_LOST_WARNING)
if("x${__modify_lost_warning}" STREQUAL "x")
message(AUTHOR_WARNING "generate_project_config: The modification lost warning is not set.")
endif()
set(__inc_guard "_${PROJECT_NAME}_CONFIG_INCLUDE_GUARD_")
set(__options "")
foreach(__raw_option ${__raw_options})
set(__length -1)
string(LENGTH "${__raw_option}" __length)
if(__length LESS_EQUAL 0)
continue()
endif()
set(__index -1)
string(FIND "${__raw_option}" "=" __index)
if(__index LESS_EQUAL 0)
continue()
endif()
set(__option "")
string(SUBSTRING "${__raw_option}" 0 ${__index} __option)
if("x${__option}" STREQUAL "x")
continue()
endif()
math(EXPR __value_index "${__index} + 1")
math(EXPR __value_length "${__length} - ${__value_index}")
set(__value "")
string(SUBSTRING "${__raw_option}" ${__value_index} ${__value_length} __value)
if("x${__value}" STREQUAL "TRUE" OR "x${__value}" STREQUAL "ENABLE" OR "x${__value}" STREQUAL "ON" OR "x${__value}" STREQUAL "YES" OR "x${__value}" STREQUAL "WANT" OR "x${__value}" STREQUAL "1")
set(__value 1)
else()
set(__value -1)
endif()
string(APPEND __options "#define ${__option} ${__value}\n")
endforeach()
set(__config_content "${__license_header}
${__modify_lost_warning}
#pragma once
#ifndef ${__inc_guard}
#define ${__inc_guard}
${__options}
#endif // ${__inc_guard}
")
file(WRITE "${arg_PATH}" "${__config_content}")
endfunction()
function(query_git_information)
cmake_parse_arguments(arg "" "HASH;SUBJECT;AUTHOR;DATETIME;BRANCH" "" ${ARGN})
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "query_git_information: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
if(NOT Git_FOUND)
find_package(Git QUIET)
endif()
if(NOT Git_FOUND)
message(AUTHOR_WARNING "query_git_information: Can't find the Git package!")
return()
endif()
#message(STATUS "Git found: ${GIT_EXECUTABLE} (version ${GIT_VERSION_STRING})")
if(arg_HASH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --pretty=format:%H
OUTPUT_VARIABLE ${arg_HASH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
RESULT_VARIABLE __result_code
)
endif()
if(arg_SUBJECT)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --pretty=format:%s
OUTPUT_VARIABLE ${arg_SUBJECT}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
RESULT_VARIABLE __result_code
)
endif()
if(arg_AUTHOR)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --pretty=format:"%aN (%aE)"
OUTPUT_VARIABLE ${arg_AUTHOR}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
RESULT_VARIABLE __result_code
)
endif()
if(arg_DATETIME)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --pretty=format:%aI
OUTPUT_VARIABLE ${arg_DATETIME}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
RESULT_VARIABLE __result_code
)
endif()
if(arg_BRANCH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" symbolic-ref --quiet --short HEAD
OUTPUT_VARIABLE ${arg_BRANCH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
RESULT_VARIABLE __result_code
)
endif()
endfunction()
function(query_compiler_information)
cmake_parse_arguments(arg "" "NAME;VENDOR;VERSION;HOMEPAGE" "" ${ARGN})
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "query_compiler_information: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
set(__lang "C")
set(__id "${CMAKE_${__lang}_COMPILER_ID}")
if("x${__id}" STREQUAL "x")
set(__lang "CXX")
set(__id "${CMAKE_${__lang}_COMPILER_ID}")
endif()
if("x${__id}" STREQUAL "x")
message(AUTHOR_WARNING "query_compiler_information: Can't find a valid C/C++ toolchain!")
return()
endif()
if(arg_VERSION)
set(${arg_VERSION} "${CMAKE_${__lang}_COMPILER_VERSION}" PARENT_SCOPE)
endif()
if(__id MATCHES "Clang")
if(arg_NAME)
set(${arg_NAME} "Clang" PARENT_SCOPE)
endif()
if(__id STREQUAL "AppleClang")
if(arg_VENDOR)
set(${arg_VENDOR} "Apple" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://opensource.apple.com/source/clang/" PARENT_SCOPE)
endif()
elseif(__id STREQUAL "ARMClang")
if(arg_VENDOR)
set(${arg_VENDOR} "Arm" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://developer.arm.com/documentation/100748/latest/" PARENT_SCOPE)
endif()
elseif(__id STREQUAL "IBMClang" OR __id STREQUAL "XLClang")
if(arg_VENDOR)
set(${arg_VENDOR} "IBM" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://www.ibm.com/docs/en/openxl-c-and-cpp-aix" PARENT_SCOPE)
endif()
elseif(__id STREQUAL "Clang")
if(arg_VENDOR)
set(${arg_VENDOR} "LLVM" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://clang.llvm.org/" PARENT_SCOPE)
endif()
else()
if(arg_VENDOR)
set(${arg_VENDOR} "UNKNOWN" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "UNKNOWN" PARENT_SCOPE)
endif()
endif()
elseif(__id STREQUAL "GNU")
if(arg_VENDOR)
set(${arg_VENDOR} "GNU Compiler Collection" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://gcc.gnu.org/" PARENT_SCOPE)
endif()
elseif(__id STREQUAL "MSVC")
if(arg_VENDOR)
set(${arg_VENDOR} "Microsoft" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "https://visualstudio.microsoft.com/" PARENT_SCOPE)
endif()
elseif(__id MATCHES "Intel")
else()
if(arg_VENDOR)
set(${arg_VENDOR} "UNKNOWN" PARENT_SCOPE)
endif()
if(arg_HOMEPAGE)
set(${arg_HOMEPAGE} "UNKNOWN" PARENT_SCOPE)
endif()
endif()
endfunction()
function(generate_project_version)
set(__target ${PROJECT_NAME}_METADATA)
if(NOT TARGET ${__target})
message(AUTHOR_WARNING "generate_project_version: You need to call setup_project() first!")
return()
endif()
cmake_parse_arguments(arg "OVERWRITE;COMMIT_HASH;COMMIT_SUBJECT;COMMIT_AUTHOR;COMMIT_DATETIME;COMMIT_BRANCH;COMPILER_NAME;COMPILER_VENDOR;COMPILER_VERSION;COMPILER_HOMEPAGE" "PATH" "" ${ARGN})
if(NOT arg_PATH)
message(AUTHOR_WARNING "generate_project_version: You need to specify the file path!")
return()
endif()
if(arg_UNPARSED_ARGUMENTS)
message(AUTHOR_WARNING "generate_project_version: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}")
endif()
if(EXISTS "${arg_PATH}" AND NOT arg_OVERWRITE)
return()
endif()
set(__license_header "")
get_target_property(__license_header ${__target} __PROJECT_LICENSE_HEADER)
if("x${__license_header}" STREQUAL "x")
message(AUTHOR_WARNING "generate_project_version: The license header is not set.")
endif()
set(__modify_lost_warning "")
get_target_property(__modify_lost_warning ${__target} __PROJECT_MODIFY_LOST_WARNING)
if("x${__modify_lost_warning}" STREQUAL "x")
message(AUTHOR_WARNING "generate_project_version: The modification lost warning is not set.")
endif()
set(__prefix "")
get_target_property(__prefix ${__target} __PROJECT_VERSION_PREFIX)
if("x${__prefix}" STREQUAL "x")
set(__prefix "${PROJECT_NAME}_FEATURE")
message(AUTHOR_WARNING "generate_project_version: config prefix is not set, using ${__prefix} as default.")
endif()
set(__inc_guard "_${PROJECT_NAME}_VERSION_INCLUDE_GUARD_")
set(__versions "")
set(__common_num "[[maybe_unused]] inline constexpr const unsigned long")
set(__common_str "[[maybe_unused]] inline constexpr const char")
string(APPEND __versions "${__common_num} ${__prefix}_VERSION_MAJOR = ${PROJECT_VERSION_MAJOR};\n")
string(APPEND __versions "${__common_num} ${__prefix}_VERSION_MINOR = ${PROJECT_VERSION_MINOR};\n")
string(APPEND __versions "${__common_num} ${__prefix}_VERSION_PATCH = ${PROJECT_VERSION_PATCH};\n")
string(APPEND __versions "${__common_num} ${__prefix}_VERSION_TWEAK = ${PROJECT_VERSION_TWEAK};\n")
string(APPEND __versions "${__common_str} ${__prefix}_VERSION_STR[] = \"${PROJECT_VERSION}\";\n")
string(APPEND __versions "#define __${__prefix}_VERSION_MAJOR__ ${PROJECT_VERSION_MAJOR}\n")
string(APPEND __versions "#define __${__prefix}_VERSION_MINOR__ ${PROJECT_VERSION_MINOR}\n")
string(APPEND __versions "#define __${__prefix}_VERSION_PATCH__ ${PROJECT_VERSION_PATCH}\n")
string(APPEND __versions "#define __${__prefix}_VERSION_TWEAK__ ${PROJECT_VERSION_TWEAK}\n")
string(APPEND __versions "#define __${__prefix}_VERSION__ ${PROJECT_VERSION_MINOR}\n")
if(arg_COMMIT_HASH)
set(__hash "")
query_git_information(HASH __hash)
string(APPEND __versions "${__common_str} ${__prefix}_COMMIT_HASH_STR[] = \"${__hash}\";\n")
endif()
if(arg_COMMIT_SUBJECT)
set(__subject "")
query_git_information(SUBJECT __subject)
string(APPEND __versions "${__common_str} ${__prefix}_COMMIT_SUBJECT_STR[] = \"${__subject}\";\n")
endif()
if(arg_COMMIT_AUTHOR)
set(__author "")
query_git_information(AUTHOR __author)
string(APPEND __versions "${__common_str} ${__prefix}_COMMIT_AUTHOR_STR[] = \"${__author}\";\n")
endif()
if(arg_COMMIT_DATETIME)
set(__datetime "")
query_git_information(DATETIME __datetime)
string(APPEND __versions "${__common_str} ${__prefix}_COMMIT_DATETIME_STR[] = \"${__datetime}\";\n")
endif()
if(arg_COMMIT_BRANCH)
set(__branch "")
query_git_information(BRANCH __branch)
string(APPEND __versions "${__common_str} ${__prefix}_COMMIT_BRANCH_STR[] = \"${__branch}\";\n")
endif()
if(arg_COMPILER_NAME)
set(__name "")
query_compiler_information(NAME __name)
string(APPEND __versions "${__common_str} ${__prefix}_COMPILER_NAME_STR[] = \"${__name}\";\n")
endif()
if(arg_COMPILER_VERSION)
set(__version "")
query_compiler_information(VERSION __version)
string(APPEND __versions "${__common_str} ${__prefix}_COMPILER_VERSION_STR[] = \"${__version}\";\n")
endif()
if(arg_COMPILER_VENDOR)
set(__vendor "")
query_compiler_information(VENDOR __vendor)
string(APPEND __versions "${__common_str} ${__prefix}_COMPILER_VENDOR_STR[] = \"${__vendor}\";\n")
endif()
if(arg_COMPILER_HOMEPAGE)
set(__homepage "")
query_compiler_information(NAME __homepage)
string(APPEND __versions "${__common_str} ${__prefix}_COMPILER_HOMEPAGE_STR[] = \"${__homepage}\";\n")
endif()
set(__version_content "${__license_header}
${__modify_lost_warning}
#pragma once
#ifndef ${__inc_guard}
#define ${__inc_guard}
${__versions}
#endif // ${__inc_guard}
")
file(WRITE "${arg_PATH}" "${__version_content}")
endfunction()