qt5base-lts/cmake/QtBuildInformation.cmake
Alexandru Croitor 95e1469eb8 CMake: Port most of the configure summary support
Teaches configurejson2cmake about summaries / reports, so things
like enabled features, configure sections, notes, etc.

Add relevant CMake API for adding summary sections and entries,
as well as configure reports. The commands record the passed data,
and the data is later evaluated when the summary needs to be printed.
This is needed, to ensure that all features are evaluated by the
time the summary is printed.

Some report and summary entries are not generated if they mention a
feature that is explicitly exclduded by configurejson2cmake's feature
mapping dictionary. This is to prevent CMake from failing at configure
time when trying to evaluate an unknown feature. We should re-enable
these in the future.

A few custom report types are skipped by configurejson2cmake (like
values of qmake CONFIG or buildParts).
These will have to be addressed a case-by-case basis if still needed.

Change-Id: I95d74ce34734d347681905f15a781f64b5bd5edc
Reviewed-by: Leander Beernaert <leander.beernaert@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2020-03-09 23:08:57 +01:00

363 lines
13 KiB
CMake

function(qt_print_feature_summary)
include(FeatureSummary)
# Show which packages were found.
feature_summary(WHAT PACKAGES_FOUND
REQUIRED_PACKAGES_NOT_FOUND
RECOMMENDED_PACKAGES_NOT_FOUND
OPTIONAL_PACKAGES_NOT_FOUND
RUNTIME_PACKAGES_NOT_FOUND
FATAL_ON_MISSING_REQUIRED_PACKAGES)
qt_configure_print_summary()
endfunction()
function(qt_print_build_instructions)
if((NOT PROJECT_NAME STREQUAL "QtBase" AND
NOT PROJECT_NAME STREQUAL "Qt") OR
QT_BUILD_STANDALONE_TESTS)
return()
endif()
set(build_command "cmake --build . --parallel")
set(install_command "cmake --install .")
message("Qt is now configured for building. Just run '${build_command}'.")
if(QT_WILL_INSTALL)
message("Once everything is built, you must run '${install_command}'.")
message("Qt will be installed into '${CMAKE_INSTALL_PREFIX}'")
else()
message("Once everything is built, Qt is installed.")
message("You should NOT run '${install_command}'")
message("Note that this build cannot be deployed to other machines or devices.")
endif()
message("To configure and build other modules, you can use the following convenience script:
${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qt-cmake")
message("\nIf reconfiguration fails for some reason, try to remove 'CMakeCache.txt' \
from the build directory \n")
endfunction()
function(qt_configure_print_summary)
# Evaluate all recorded commands.
qt_configure_eval_commands()
# Show Qt-specific configure summary and any notes, wranings, etc.
if(__qt_configure_reports)
message("Configure summary:\n${__qt_configure_reports}")
endif()
if(__qt_configure_notes)
message("${__qt_configure_notes}")
endif()
if(__qt_configure_warnings)
message("${__qt_configure_warnings}")
endif()
if(__qt_configure_errors)
message("${__qt_configure_errors}")
endif()
message("")
if(__qt_configure_an_error_occurred)
message(FATAL_ERROR "Check the configuration messages for an error that has occurred.")
endif()
endfunction()
# Takes a list of arguments, and saves them to be evaluated at the end of the configuration
# phase when the configuration summary is shown.
function(qt_configure_record_command)
# Don't record commands when only evaluating features of a configure.cmake file.
if(__QtFeature_only_evaluate_features)
return()
endif()
get_property(command_count GLOBAL PROPERTY qt_configure_command_count)
if(NOT DEFINED command_count)
set(command_count 0)
else()
math(EXPR command_count "${command_count}+1")
endif()
set_property(GLOBAL PROPERTY qt_configure_command_${command_count} "${ARGV}")
set_property(GLOBAL PROPERTY qt_configure_command_count "${command_count}")
endfunction()
function(qt_configure_eval_commands)
get_property(command_count GLOBAL PROPERTY qt_configure_command_count)
if(NOT command_count)
set(command_count 0)
endif()
set(command_index 0)
while(command_index LESS command_count)
get_property(command_args GLOBAL PROPERTY qt_configure_command_${command_index})
if(NOT command_args)
message(FATAL_ERROR
"Empty arguments encountered while processing qt configure reports.")
endif()
list(POP_FRONT command_args command_name)
if(command_name STREQUAL ADD_SUMMARY_SECTION)
qt_configure_process_add_summary_section(${command_args})
elseif(command_name STREQUAL END_SUMMARY_SECTION)
qt_configure_process_end_summary_section(${command_args})
elseif(command_name STREQUAL ADD_REPORT_ENTRY)
qt_configure_process_add_report_entry(${command_args})
elseif(command_name STREQUAL ADD_SUMMARY_ENTRY)
qt_configure_process_add_summary_entry(${command_args})
elseif(command_name STREQUAL ADD_BUILD_TYPE_AND_CONFIG)
qt_configure_process_add_summary_build_type_and_config(${command_args})
elseif(command_name STREQUAL ADD_BUILD_MODE)
qt_configure_process_add_summary_build_mode(${command_args})
endif()
math(EXPR command_index "${command_index}+1")
endwhile()
# Propagate content to parent.
set(__qt_configure_reports "${__qt_configure_reports}" PARENT_SCOPE)
set(__qt_configure_notes "${__qt_configure_notes}" PARENT_SCOPE)
set(__qt_configure_warnings "${__qt_configure_warnings}" PARENT_SCOPE)
set(__qt_configure_errors "${__qt_configure_errors}" PARENT_SCOPE)
set(__qt_configure_an_error_occurred "${__qt_configure_an_error_occurred}" PARENT_SCOPE)
endfunction()
macro(qt_configure_add_report message)
string(APPEND __qt_configure_reports "\n${message}")
set(__qt_configure_reports "${__qt_configure_reports}" PARENT_SCOPE)
endmacro()
macro(qt_configure_add_report_padded label message)
qt_configure_get_padded_string("${__qt_configure_indent}${label}" "${message}" padded_message)
string(APPEND __qt_configure_reports "\n${padded_message}")
set(__qt_configure_reports "${__qt_configure_reports}" PARENT_SCOPE)
endmacro()
function(qt_configure_get_padded_string label value out_var)
set(pad_string "........................................")
string(LENGTH "${label}" label_len)
string(LENGTH "${pad_string}" pad_len)
math(EXPR pad_len "${pad_len}-${label_len}")
if(pad_len LESS "0")
set(pad_len "0")
endif()
string(SUBSTRING "${pad_string}" 0 "${pad_len}" pad_string)
set(output "${label} ${pad_string} ${value}")
set("${out_var}" "${output}" PARENT_SCOPE)
endfunction()
function(qt_configure_add_summary_entry)
qt_configure_record_command(ADD_SUMMARY_ENTRY ${ARGV})
endfunction()
function(qt_configure_process_add_summary_entry)
qt_parse_all_arguments(arg "qt_configure_add_summary_entry"
""
"ARGS;TYPE;MESSAGE" "CONDITION" ${ARGN})
if(NOT arg_TYPE)
set(arg_TYPE "feature")
endif()
if(NOT "${arg_CONDITION}" STREQUAL "")
qt_evaluate_config_expression(condition_result ${arg_CONDITION})
if(NOT condition_result)
return()
endif()
endif()
if(arg_TYPE STREQUAL "firstAvailableFeature")
set(first_feature_found FALSE)
set(message "")
string(REPLACE " " ";" args_list "${arg_ARGS}")
foreach(feature ${args_list})
qt_feature_normalize_name("${feature}" feature)
if(NOT DEFINED QT_FEATURE_${feature})
message(FATAL_ERROR "Asking for a report on undefined feature ${feature}.")
endif()
if(QT_FEATURE_${feature})
set(first_feature_found TRUE)
set(message "${QT_FEATURE_LABEL_${feature}}")
break()
endif()
endforeach()
if(NOT first_feature_found)
set(message "<none>")
endif()
qt_configure_add_report_padded("${arg_MESSAGE}" "${message}")
elseif(arg_TYPE STREQUAL "featureList")
set(available_features "")
string(REPLACE " " ";" args_list "${arg_ARGS}")
foreach(feature ${args_list})
qt_feature_normalize_name("${feature}" feature)
if(NOT DEFINED QT_FEATURE_${feature})
message(FATAL_ERROR "Asking for a report on undefined feature ${feature}.")
endif()
if(QT_FEATURE_${feature})
list(APPEND available_features "${QT_FEATURE_LABEL_${feature}}")
endif()
endforeach()
if(NOT available_features)
set(message "<none>")
else()
list(JOIN available_features " " message)
endif()
qt_configure_add_report_padded("${arg_MESSAGE}" "${message}")
elseif(arg_TYPE STREQUAL "feature")
qt_feature_normalize_name("${arg_ARGS}" feature)
set(label "${QT_FEATURE_LABEL_${feature}}")
if(NOT label)
set(label "${feature}")
endif()
if(QT_FEATURE_${feature})
set(value "yes")
else()
set(value "no")
endif()
qt_configure_add_report_padded("${label}" "${value}")
endif()
endfunction()
function(qt_configure_add_summary_build_type_and_config)
qt_configure_record_command(ADD_BUILD_TYPE_AND_CONFIG ${ARGV})
endfunction()
function(qt_configure_process_add_summary_build_type_and_config)
get_property(subarch_summary GLOBAL PROPERTY qt_configure_subarch_summary)
set(message
"Building for: ${QT_QMAKE_TARGET_MKSPEC} (${TEST_architecture_arch}, CPU features: ${subarch_summary})")
qt_configure_add_report("${message}")
set(message "Compiler: ")
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
string(APPEND message "clang (Apple)")
elseif(CLANG)
string(APPEND message "clang")
elseif(ICC)
string(APPEND message "intel_icc")
elseif(QCC)
string(APPEND message "rim_qcc")
elseif(GCC)
string(APPEND message "gcc")
elseif(MSVC)
string(APPEND message "msvc")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GHS")
string(APPEND message "ghs")
else()
string(APPEND message "unknown (${CMAKE_CXX_COMPILER_ID})")
endif()
string(APPEND message " ${CMAKE_CXX_COMPILER_VERSION}")
qt_configure_add_report("${message}")
endfunction()
function(qt_configure_add_summary_build_mode)
qt_configure_record_command(ADD_BUILD_MODE ${ARGV})
endfunction()
function(qt_configure_process_add_summary_build_mode label)
set(message "")
if(DEFINED CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
string(APPEND message "debug")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
string(APPEND message "release")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
string(APPEND message "release (with debug info)")
else()
string(APPEND message "${CMAKE_BUILD_TYPE}")
endif()
elseif(DEFINED CMAKE_CONFIGURATION_TYPES)
if("Release" IN_LIST CMAKE_CONFIGURATION_TYPES
AND "Debug" IN_LIST CMAKE_CONFIGURATION_TYPES)
string(APPEND message "debug and release")
elseif("RelWithDebInfo" IN_LIST CMAKE_CONFIGURATION_TYPES
AND "Debug" IN_LIST CMAKE_CONFIGURATION_TYPES)
string(APPEND message "debug and release (with debug info)")
else()
string(APPEND message "${CMAKE_CONFIGURATION_TYPES}")
endif()
endif()
qt_configure_add_report_padded("${label}" "${message}")
endfunction()
function(qt_configure_add_summary_section)
qt_configure_record_command(ADD_SUMMARY_SECTION ${ARGV})
endfunction()
function(qt_configure_process_add_summary_section)
qt_parse_all_arguments(arg "qt_configure_add_summary_section"
"" "NAME" "" ${ARGN})
qt_configure_add_report("${__qt_configure_indent}${arg_NAME}:")
if(NOT DEFINED __qt_configure_indent)
set(__qt_configure_indent " " PARENT_SCOPE)
else()
set(__qt_configure_indent "${__qt_configure_indent} " PARENT_SCOPE)
endif()
endfunction()
function(qt_configure_end_summary_section)
qt_configure_record_command(END_SUMMARY_SECTION ${ARGV})
endfunction()
function(qt_configure_process_end_summary_section)
string(LENGTH "${__qt_configure_indent}" indent_len)
if(indent_len GREATER_EQUAL 2)
string(SUBSTRING "${__qt_configure_indent}" 2 -1 __qt_configure_indent)
set(__qt_configure_indent "${__qt_configure_indent}" PARENT_SCOPE)
endif()
endfunction()
function(qt_configure_add_report_entry)
qt_configure_record_command(ADD_REPORT_ENTRY ${ARGV})
endfunction()
function(qt_configure_process_add_report_entry)
qt_parse_all_arguments(arg "qt_configure_add_report_entry"
""
"TYPE;MESSAGE" "CONDITION" ${ARGN})
set(possible_types NOTE WARNING ERROR FATAL_ERROR)
if(NOT "${arg_TYPE}" IN_LIST possible_types)
message(FATAL_ERROR "qt_configure_add_report_entry: '${arg_TYPE}' is not a valid type.")
endif()
if(NOT arg_MESSAGE)
message(FATAL_ERROR "qt_configure_add_report_entry: Empty message given.")
endif()
if(arg_TYPE STREQUAL "NOTE")
set(contents_var "__qt_configure_notes")
set(prefix "Note: ")
elseif(arg_TYPE STREQUAL "WARNING")
set(contents_var "__qt_configure_warnings")
set(prefix "WARNING: ")
elseif(arg_TYPE STREQUAL "ERROR")
set(contents_var "__qt_configure_errors")
set(prefix "ERROR: ")
elseif(arg_TYPE STREQUAL "FATAL_ERROR")
set(contents_var "__qt_configure_errors")
set(prefix "FATAL ERROR: ")
endif()
if(NOT "${arg_CONDITION}" STREQUAL "")
qt_evaluate_config_expression(condition_result ${arg_CONDITION})
endif()
if("${arg_CONDITION}" STREQUAL "" OR condition_result)
set(new_report "${prefix}${arg_MESSAGE}")
string(APPEND "${contents_var}" "\n${new_report}")
if(arg_TYPE STREQUAL "ERROR" OR arg_TYPE STREQUAL "FATAL_ERROR")
set(__qt_configure_an_error_occurred "TRUE" PARENT_SCOPE)
endif()
endif()
set("${contents_var}" "${${contents_var}}" PARENT_SCOPE)
endfunction()