mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-11-22 19:49:59 +08:00
commit
2c121a6f62
@ -5,10 +5,9 @@
|
||||
# (directly by qtbase) we actually add the extra definitions
|
||||
if (NOT DEFINED QT_SUPERBUILD OR DEFINED QT_REPO_MODULE_VERSION)
|
||||
set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_LEAN_HEADERS=1")
|
||||
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
|
||||
endif()
|
||||
|
||||
set(QT_REPO_MODULE_VERSION "6.5.3")
|
||||
set(QT_REPO_MODULE_VERSION "6.6.0")
|
||||
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
|
||||
|
||||
set(QT_COPYRIGHT_YEAR "2023")
|
||||
@ -17,12 +16,14 @@ set(QT_COPYRIGHT "Copyright (C) ${QT_COPYRIGHT_YEAR} The Qt Company Ltd and othe
|
||||
# Minimum requirement for building Qt
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_SHARED "3.16")
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_STATIC "3.21")
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_APPLE "3.21")
|
||||
|
||||
# Minimum requirement for consuming Qt in a user project.
|
||||
# This might be different in the future, e.g. be lower than the requirement for
|
||||
# building Qt.
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_SHARED "3.16")
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_STATIC "3.21")
|
||||
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_APPLE "3.21")
|
||||
|
||||
# Policy settings for commands defined by qtbase. These will also be injected
|
||||
# into the top level policy scope of each Qt module when building Qt so that
|
||||
|
@ -1 +1 @@
|
||||
QT_PACKAGEDATE_STR=2023-09-25
|
||||
QT_PACKAGEDATE_STR=2023-10-04
|
2
.tag
2
.tag
@ -1 +1 @@
|
||||
372eaedc5b8c771c46acc4c96e91bbade4ca3624
|
||||
33f5e985e480283bb0ca9dea5f82643e825ba87c
|
||||
|
@ -1,8 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# special case skip regeneration
|
||||
|
||||
# Need an explicit call at the top level. This is the absolute minimum version
|
||||
# needed to configure the project with any combination of enabled features.
|
||||
# The call to qt_build_repo_begin() will upgrade policies further.
|
||||
|
18
bin/qt-cmake-create.bat.in
Normal file
18
bin/qt-cmake-create.bat.in
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
:: The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory.
|
||||
set script_dir_path=%~dp0
|
||||
|
||||
:: Try to use original cmake, otherwise to make it relocatable, use any cmake found in PATH.
|
||||
set cmake_path=@CMAKE_COMMAND@
|
||||
if not exist "%cmake_path%" set cmake_path=cmake
|
||||
|
||||
if NOT "%~2" == "" goto :showhelp
|
||||
if NOT "%~1" == "" (set PROJECT_DIR=%~1) else (set PROJECT_DIR=%cd%)
|
||||
|
||||
"%cmake_path%" -DPROJECT_DIR="%PROJECT_DIR%" -P "%script_dir_path%\@__GlobalConfig_relative_path_from_bin_dir_to_cmake_config_dir@\QtInitProject.cmake"
|
||||
exit /b %errorlevel%
|
||||
|
||||
:showhelp
|
||||
echo Usage
|
||||
echo. qt-cmake-create <path/to/project>
|
||||
exit /b 1
|
29
bin/qt-cmake-create.in
Normal file
29
bin/qt-cmake-create.in
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
HELP_MESSAGE="Usage
|
||||
qt-cmake-create <path/to/project>"
|
||||
|
||||
# The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory.
|
||||
script_dir_path=`dirname $0`
|
||||
script_dir_path=`(cd "$script_dir_path"; /bin/pwd)`
|
||||
|
||||
# Try to use original cmake, otherwise to make it relocatable, use any cmake found in PATH.
|
||||
original_cmake_path="@CMAKE_COMMAND@"
|
||||
cmake_path=$original_cmake_path
|
||||
if ! test -f "$cmake_path"; then
|
||||
cmake_path="cmake"
|
||||
fi
|
||||
|
||||
if [ "$#" -gt 1 ]; then
|
||||
echo "Invalid number of arguments"
|
||||
echo "$HELP_MESSAGE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
PROJECT_DIR=$1
|
||||
else
|
||||
PROJECT_DIR=$PWD
|
||||
fi
|
||||
exec "$cmake_path" -DPROJECT_DIR="$PROJECT_DIR" -P \
|
||||
"$script_dir_path/@__GlobalConfig_relative_path_from_bin_dir_to_cmake_config_dir@/QtInitProject.cmake"
|
98
cmake/FindMimer.cmake
Normal file
98
cmake/FindMimer.cmake
Normal file
@ -0,0 +1,98 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# Copyright (C) 2022 Mimer Information Technology
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# FindMimer
|
||||
# ---------
|
||||
# Try to locate the Mimer SQL client library
|
||||
if(NOT DEFINED MimerSQL_ROOT)
|
||||
if(DEFINED ENV{MIMERSQL_DEV_ROOT})
|
||||
set(MimerSQL_ROOT "$ENV{MIMERSQL_DEV_ROOT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED MimerSQL_ROOT)
|
||||
find_package(PkgConfig QUIET)
|
||||
endif()
|
||||
if(PkgConfig_FOUND AND NOT DEFINED MimerSQL_ROOT)
|
||||
pkg_check_modules(PC_Mimer QUIET mimcontrol)
|
||||
set(MimerSQL_include_dir_hints "${PC_MimerSQL_INCLUDEDIR}")
|
||||
set(MimerSQL_library_hints "${PC_MimerSQL_LIBDIR}")
|
||||
else()
|
||||
if(DEFINED MimerSQL_ROOT)
|
||||
if(WIN32)
|
||||
set(MimerSQL_include_dir_hints "${MimerSQL_ROOT}\\include")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
|
||||
set(MimerSQL_library_hints "${MimerSQL_ROOT}\\lib\\x86")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
|
||||
set(MimerSQL_library_hints "${MimerSQL_ROOT}\\lib\\amd64")
|
||||
else()
|
||||
set(MimerSQL_library_hints "")
|
||||
endif()
|
||||
else()
|
||||
set(MimerSQL_include_dir_hints "${MimerSQL_ROOT}/include")
|
||||
set(MimerSQL_library_hints "${MimerSQL_ROOT}/lib")
|
||||
endif()
|
||||
else()
|
||||
if(WIN32)
|
||||
set(MimerSQL_include_dir_hints "C:\\MimerSQLDev\\include")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
|
||||
set(MimerSQL_library_hints "C:\\MimerSQLDev\\lib\\x86")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
|
||||
set(MimerSQL_library_hints "C:\\MimerSQLDev\\lib\\amd64")
|
||||
else()
|
||||
set(MimerSQL_library_hints "")
|
||||
endif()
|
||||
elseif(APPLE AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(MimerSQL_library_hints "/usr/local/lib")
|
||||
set(MimerSQL_include_dir_hints "/usr/local/include")
|
||||
else()
|
||||
set(MimerSQL_include_dir_hints "")
|
||||
set(MimerSQL_library_hints "")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_path(Mimer_INCLUDE_DIR
|
||||
NAMES mimerapi.h
|
||||
HINTS ${MimerSQL_include_dir_hints})
|
||||
|
||||
if(WIN32)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
|
||||
set(MIMER_LIBS_NAMES mimapi32)
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
|
||||
set(MIMER_LIBS_NAMES mimapi64)
|
||||
endif()
|
||||
else()
|
||||
set(MIMER_LIBS_NAMES mimerapi)
|
||||
endif()
|
||||
|
||||
find_library(Mimer_LIBRARIES
|
||||
NAMES ${MIMER_LIBS_NAMES}
|
||||
HINTS ${MimerSQL_library_hints})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(Mimer
|
||||
REQUIRED_VARS Mimer_LIBRARIES Mimer_INCLUDE_DIR)
|
||||
|
||||
|
||||
|
||||
# Now try to get the include and library path.
|
||||
if(Mimer_FOUND)
|
||||
set(Mimer_INCLUDE_DIRS ${Mimer_INCLUDE_DIR})
|
||||
set(Mimer_LIBRARY_DIRS ${Mimer_LIBRARIES})
|
||||
if (NOT TARGET MimerSQL::MimerSQL)
|
||||
add_library(MimerSQL::MimerSQL UNKNOWN IMPORTED)
|
||||
set_target_properties(MimerSQL::MimerSQL PROPERTIES
|
||||
IMPORTED_LOCATION "${Mimer_LIBRARY_DIRS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Mimer_INCLUDE_DIRS}")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Mimer_INCLUDE_DIR Mimer_LIBRARIES)
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(MimerSQL PROPERTIES
|
||||
URL "https://www.mimer.com"
|
||||
DESCRIPTION "Mimer client library")
|
53
cmake/FindWrapResolv.cmake
Normal file
53
cmake/FindWrapResolv.cmake
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# Copyright (C) 2023 Intel Corpotation.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# We can't create the same interface imported target multiple times, CMake will complain if we do
|
||||
# that. This can happen if the find_package call is done in multiple different subdirectories.
|
||||
if(TARGET WrapResolv::WrapResolv)
|
||||
set(WrapResolv_FOUND ON)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(WrapResolv_FOUND OFF)
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
if(QNX)
|
||||
find_library(LIBRESOLV socket)
|
||||
else()
|
||||
find_library(LIBRESOLV resolv)
|
||||
endif()
|
||||
|
||||
cmake_push_check_state()
|
||||
if(LIBRESOLV)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBRESOLV}")
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <netinet/in.h>
|
||||
#include <resolv.h>
|
||||
|
||||
int main(int, char **argv)
|
||||
{
|
||||
res_state statep;
|
||||
int n = res_nmkquery(statep, 0, argv[1], 0, 0, NULL, 0, NULL, NULL, 0);
|
||||
n = res_nsend(statep, NULL, 0, NULL, 0);
|
||||
n = dn_expand(NULL, NULL, NULL, NULL, 0);
|
||||
return n;
|
||||
}
|
||||
" HAVE_LIBRESOLV_FUNCTIONS)
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
if(HAVE_LIBRESOLV_FUNCTIONS)
|
||||
set(WrapResolv_FOUND ON)
|
||||
add_library(WrapResolv::WrapResolv INTERFACE IMPORTED)
|
||||
if(LIBRESOLV)
|
||||
target_link_libraries(WrapResolv::WrapResolv INTERFACE "${LIBRESOLV}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(WrapResolv DEFAULT_MSG WrapResolv_FOUND)
|
@ -21,17 +21,31 @@ if(LIBRT)
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int, char **) {
|
||||
timespec ts; clock_gettime(CLOCK_REALTIME, &ts);
|
||||
}" HAVE_GETTIME)
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_GETTIME)
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main(int, char **) {
|
||||
shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);
|
||||
shm_unlink(\"test\");
|
||||
return 0;
|
||||
}
|
||||
" HAVE_SHM_OPEN_SHM_UNLINK)
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
|
||||
if(HAVE_GETTIME)
|
||||
if(HAVE_GETTIME OR HAVE_SHM_OPEN_SHM_UNLINK)
|
||||
set(WrapRt_FOUND ON)
|
||||
add_library(WrapRt::WrapRt INTERFACE IMPORTED)
|
||||
if (LIBRT)
|
||||
|
@ -48,6 +48,26 @@ if(Vulkan_INCLUDE_DIR)
|
||||
target_include_directories(WrapVulkanHeaders::WrapVulkanHeaders INTERFACE
|
||||
${__qt_molten_vk_homebrew_include_path})
|
||||
endif()
|
||||
|
||||
# Check for homebrew vulkan-headers folder structure
|
||||
# If instead of molten-vk folder, CMAKE_PREFIX_PATH points to Homebrew's
|
||||
# vulkan-headers installation, then we will not be able to find molten-vk
|
||||
# headers. If we assume that user has installed the molten-vk formula as
|
||||
# well, then we might have a chance to pick it up like this.
|
||||
if(Vulkan_INCLUDE_DIR MATCHES "/homebrew/Cellar/")
|
||||
set(__qt_standalone_molten_vk_homebrew_include_path
|
||||
"${Vulkan_INCLUDE_DIR}/../../../../opt/molten-vk/include")
|
||||
else()
|
||||
set(__qt_standalone_molten_vk_homebrew_include_path
|
||||
"${Vulkan_INCLUDE_DIR}/../../molten-vk/include")
|
||||
endif()
|
||||
get_filename_component(
|
||||
__qt_standalone_molten_vk_homebrew_include_path
|
||||
"${__qt_standalone_molten_vk_homebrew_include_path}" ABSOLUTE)
|
||||
if(EXISTS "${__qt_standalone_molten_vk_homebrew_include_path}")
|
||||
target_include_directories(WrapVulkanHeaders::WrapVulkanHeaders INTERFACE
|
||||
${__qt_standalone_molten_vk_homebrew_include_path})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -28,10 +28,10 @@ include(FindPackageHandleStandardArgs)
|
||||
if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared)
|
||||
find_package_handle_standard_args(WrapZSTD
|
||||
REQUIRED_VARS zstd_VERSION VERSION_VAR zstd_VERSION)
|
||||
if(TARGET zstd::libzstd_static)
|
||||
set(zstdtargetsuffix "_static")
|
||||
else()
|
||||
if(TARGET zstd::libzstd_shared)
|
||||
set(zstdtargetsuffix "_shared")
|
||||
else()
|
||||
set(zstdtargetsuffix "_static")
|
||||
endif()
|
||||
if(NOT TARGET WrapZSTD::WrapZSTD)
|
||||
add_library(WrapZSTD::WrapZSTD INTERFACE IMPORTED)
|
||||
|
@ -7,6 +7,7 @@
|
||||
"compiler_target": "${CMAKE_CXX_COMPILER_TARGET}",
|
||||
"compiler_version": "${CMAKE_CXX_COMPILER_VERSION}",
|
||||
"cross_compiled": ${cross_compilation},
|
||||
"target_system": "${CMAKE_SYSTEM_NAME}"
|
||||
"target_system": "${CMAKE_SYSTEM_NAME}",
|
||||
"architecture": "${TEST_architecture_arch}"
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,9 @@
|
||||
# Make sure to not run detection when building standalone tests, because the detection was already
|
||||
# done when initially configuring qtbase.
|
||||
|
||||
# This needs to be here because QtAutoDetect loads before any other modules
|
||||
option(QT_USE_VCPKG "Enable the use of vcpkg" ON)
|
||||
|
||||
function(qt_internal_ensure_static_qt_config)
|
||||
if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Qt statically or dynamically" FORCE)
|
||||
@ -161,7 +164,7 @@ function(qt_auto_detect_android)
|
||||
endfunction()
|
||||
|
||||
function(qt_auto_detect_vcpkg)
|
||||
if(DEFINED ENV{VCPKG_ROOT})
|
||||
if(QT_USE_VCPKG AND DEFINED ENV{VCPKG_ROOT})
|
||||
set(vcpkg_toolchain_file "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
|
||||
get_filename_component(vcpkg_toolchain_file "${vcpkg_toolchain_file}" ABSOLUTE)
|
||||
|
||||
@ -174,8 +177,8 @@ function(qt_auto_detect_vcpkg)
|
||||
endif()
|
||||
set(CMAKE_TOOLCHAIN_FILE "${vcpkg_toolchain_file}" CACHE STRING "" FORCE)
|
||||
message(STATUS "Using vcpkg from $ENV{VCPKG_ROOT}")
|
||||
if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
|
||||
if(DEFINED ENV{QT_VCPKG_TARGET_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
set(VCPKG_TARGET_TRIPLET "$ENV{QT_VCPKG_TARGET_TRIPLET}" CACHE STRING "")
|
||||
message(STATUS "Using vcpkg triplet ${VCPKG_TARGET_TRIPLET}")
|
||||
endif()
|
||||
unset(vcpkg_toolchain_file)
|
||||
@ -229,7 +232,9 @@ function(qt_auto_detect_ios)
|
||||
endif()
|
||||
set(CMAKE_OSX_ARCHITECTURES "${osx_architectures}" CACHE STRING "")
|
||||
|
||||
if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
qt_internal_ensure_static_qt_config()
|
||||
endif()
|
||||
|
||||
# Disable qt rpaths for iOS, just like mkspecs/common/uikit.conf does, due to those
|
||||
# bundles not being able to use paths outside the app bundle. Not sure this is strictly
|
||||
@ -239,7 +244,15 @@ function(qt_auto_detect_ios)
|
||||
endfunction()
|
||||
|
||||
function(qt_auto_detect_cmake_config)
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
# If CMAKE_CONFIGURATION_TYPES are not set for the multi-config generator use Release and
|
||||
# Debug configurations by default, instead of those are proposed by the CMake internal logic.
|
||||
get_property(is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(is_multi)
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_CONFIGURATION_TYPES Release Debug)
|
||||
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
# Allow users to specify this option.
|
||||
if(NOT QT_MULTI_CONFIG_FIRST_CONFIG)
|
||||
list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
|
||||
@ -476,6 +489,12 @@ function(qt_auto_detect_integrity)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Save the build type before project() might set one.
|
||||
# This allows us to determine if the user has set an explicit build type that we should use.
|
||||
function(qt_auto_detect_cmake_build_type)
|
||||
set(__qt_auto_detect_cmake_build_type_before_project_call "${CMAKE_BUILD_TYPE}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Let CMake load our custom platform modules.
|
||||
# CMake-provided platform modules take precedence.
|
||||
if(NOT QT_AVOID_CUSTOM_PLATFORM_MODULES)
|
||||
@ -495,3 +514,4 @@ qt_auto_detect_wasm()
|
||||
qt_auto_detect_win32_arm()
|
||||
qt_auto_detect_linux_x86()
|
||||
qt_auto_detect_integrity()
|
||||
qt_auto_detect_cmake_build_type()
|
||||
|
@ -216,6 +216,7 @@ qt_copy_or_install(FILES
|
||||
cmake/QtAndroidHelpers.cmake
|
||||
cmake/QtAppHelpers.cmake
|
||||
cmake/QtAutogenHelpers.cmake
|
||||
cmake/QtBaseTopLevelHelpers.cmake
|
||||
cmake/QtBuild.cmake
|
||||
cmake/QtBuildInformation.cmake
|
||||
cmake/QtCMakeHelpers.cmake
|
||||
@ -332,6 +333,7 @@ set(__public_cmake_helpers
|
||||
cmake/QtCopyFileIfDifferent.cmake
|
||||
cmake/QtFeature.cmake
|
||||
cmake/QtFeatureCommon.cmake
|
||||
cmake/QtInitProject.cmake
|
||||
cmake/QtPublicAppleHelpers.cmake
|
||||
cmake/QtPublicCMakeHelpers.cmake
|
||||
cmake/QtPublicCMakeVersionHelpers.cmake
|
||||
@ -395,17 +397,30 @@ if(QT_WILL_INSTALL)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(MACOS)
|
||||
qt_copy_or_install(FILES
|
||||
cmake/macos/MacOSXBundleInfo.plist.in
|
||||
DESTINATION "${__GlobalConfig_install_dir}/macos"
|
||||
)
|
||||
set(platform_shortname "macos")
|
||||
elseif(IOS)
|
||||
qt_copy_or_install(FILES
|
||||
cmake/ios/Info.plist.app.in
|
||||
cmake/ios/LaunchScreen.storyboard
|
||||
set(platform_shortname "ios")
|
||||
endif()
|
||||
|
||||
qt_copy_or_install(FILES "cmake/${platform_shortname}/Info.plist.app.in"
|
||||
DESTINATION "${__GlobalConfig_install_dir}/${platform_shortname}"
|
||||
)
|
||||
# For examples built as part of prefix build before install
|
||||
file(COPY "cmake/${platform_shortname}/Info.plist.app.in"
|
||||
DESTINATION "${__GlobalConfig_build_dir}/${platform_shortname}"
|
||||
)
|
||||
|
||||
if(IOS)
|
||||
qt_copy_or_install(FILES "cmake/ios/LaunchScreen.storyboard"
|
||||
DESTINATION "${__GlobalConfig_install_dir}/ios"
|
||||
)
|
||||
# For examples built as part of prefix build before install
|
||||
file(COPY "cmake/ios/LaunchScreen.storyboard"
|
||||
DESTINATION "${__GlobalConfig_build_dir}/ios"
|
||||
)
|
||||
endif()
|
||||
elseif(WASM)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/util/wasm/wasmtestrunner/qt-wasmtestrunner.py"
|
||||
"${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-wasmtestrunner.py" @ONLY)
|
||||
|
85
cmake/QtBaseTopLevelHelpers.cmake
Normal file
85
cmake/QtBaseTopLevelHelpers.cmake
Normal file
@ -0,0 +1,85 @@
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Depends on __qt6_qtbase_src_path being set in the top-level dir.
|
||||
macro(qt_internal_top_level_setup_autodetect)
|
||||
# Run platform auto-detection /before/ the first project() call and thus
|
||||
# before the toolchain file is loaded.
|
||||
# Don't run auto-detection when doing standalone tests. In that case, the detection
|
||||
# results are taken from either QtBuildInternals or the qt.toolchain.cmake file.
|
||||
|
||||
if(NOT QT_BUILD_STANDALONE_TESTS)
|
||||
set(__qt6_auto_detect_path "${__qt6_qtbase_src_path}/cmake/QtAutoDetect.cmake")
|
||||
if(NOT EXISTS "${__qt6_auto_detect_path}")
|
||||
message(FATAL_ERROR "Required file does not exist: '${__qt6_auto_detect_path}'")
|
||||
endif()
|
||||
include("${__qt6_auto_detect_path}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(qt_internal_top_level_setup_after_project)
|
||||
# TODO: Remove this variable once the top-level calls this function and
|
||||
# qt_internal_qt_configure_end is not called in qt_print_build_instructions anymore.
|
||||
set(__qt6_top_level_after_project_called TRUE)
|
||||
|
||||
qt_internal_top_level_setup_testing()
|
||||
endmacro()
|
||||
|
||||
macro(qt_internal_top_level_setup_testing)
|
||||
# Required so we can call ctest from the root build directory
|
||||
enable_testing()
|
||||
endmacro()
|
||||
|
||||
# Depends on __qt6_qtbase_src_path being set in the top-level dir.
|
||||
macro(qt_internal_top_level_setup_cmake_module_path)
|
||||
if (NOT QT_BUILD_STANDALONE_TESTS)
|
||||
set(__qt6_cmake_module_path "${__qt6_qtbase_src_path}/cmake")
|
||||
if(NOT EXISTS "${__qt6_cmake_module_path}")
|
||||
message(FATAL_ERROR "Required directory does not exist: '${__qt6_cmake_module_path}'")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${__qt6_cmake_module_path}")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${__qt6_cmake_module_path}/3rdparty/extra-cmake-modules/find-modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${__qt6_cmake_module_path}/3rdparty/kwin")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(qt_internal_top_level_before_build_submodules)
|
||||
qt_internal_top_level_setup_no_create_targets()
|
||||
endmacro()
|
||||
|
||||
macro(qt_internal_top_level_setup_no_create_targets)
|
||||
# Also make sure the CMake config files do not recreate the already-existing targets
|
||||
if (NOT QT_BUILD_STANDALONE_TESTS)
|
||||
set(QT_NO_CREATE_TARGETS TRUE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(qt_internal_top_level_end)
|
||||
qt_internal_print_top_level_info()
|
||||
|
||||
# Depends on QtBuildInternalsConfig being included, which is the case whenver any repo is
|
||||
# configured.
|
||||
qt_internal_qt_configure_end()
|
||||
endmacro()
|
||||
|
||||
function(qt_internal_print_top_level_info)
|
||||
if(NOT QT_BUILD_STANDALONE_TESTS)
|
||||
# Display a summary of everything
|
||||
include(QtBuildInformation)
|
||||
include(QtPlatformSupport)
|
||||
qt_print_feature_summary()
|
||||
qt_print_build_instructions()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(qt_internal_top_level_after_add_subdirectory)
|
||||
if(module STREQUAL "qtbase")
|
||||
if (NOT QT_BUILD_STANDALONE_TESTS)
|
||||
list(APPEND CMAKE_PREFIX_PATH "${QtBase_BINARY_DIR}/${INSTALL_LIBDIR}/cmake")
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH "${QtBase_BINARY_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
@ -281,7 +281,7 @@ qt_setup_tool_path_command()
|
||||
# Platform define path, etc.
|
||||
if(WIN32)
|
||||
set(QT_DEFAULT_PLATFORM_DEFINITIONS WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if(QT_64BIT)
|
||||
list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64)
|
||||
endif()
|
||||
|
||||
@ -434,7 +434,7 @@ set(QT_TOP_LEVEL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
# Prevent warnings about object files without any symbols. This is a common
|
||||
# thing in Qt as we tend to build files unconditionally, and then use ifdefs
|
||||
# to compile out parts that are not relevant.
|
||||
if(CMAKE_HOST_APPLE AND APPLE)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
|
||||
foreach(lang ASM C CXX)
|
||||
# We have to tell 'ar' to not run ranlib by itself, by passing the 'S' option
|
||||
set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
@ -577,11 +577,6 @@ endif()
|
||||
_qt_internal_determine_if_host_info_package_needed(__qt_build_requires_host_info_package)
|
||||
_qt_internal_find_host_info_package("${__qt_build_requires_host_info_package}")
|
||||
|
||||
# Create tool script wrapper if necessary.
|
||||
# TODO: Remove once all direct usages of QT_TOOL_COMMAND_WRAPPER_PATH are replaced with function
|
||||
# calls.
|
||||
_qt_internal_generate_tool_command_wrapper()
|
||||
|
||||
# This sets up the poor man's scope finalizer mechanism.
|
||||
# For newer CMake versions, we use cmake_language(DEFER CALL) instead.
|
||||
if(CMAKE_VERSION VERSION_LESS "3.19.0")
|
||||
|
@ -111,6 +111,13 @@ from the build directory")
|
||||
if(QT_SUPERBUILD)
|
||||
qt_internal_save_previously_visited_packages()
|
||||
endif()
|
||||
|
||||
# TODO: Abuse qt_print_build_instructions being called as the last command in a top-level build.
|
||||
# Instead we should call this explicitly at the end of the top-level project.
|
||||
# TODO: Remove this once the top-level calls qt_internal_top_level_setup_after_project
|
||||
if(QT_SUPERBUILD AND NOT __qt6_top_level_after_project_called)
|
||||
qt_internal_qt_configure_end()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_configure_print_summary_helper summary_reports force_show)
|
||||
|
@ -105,6 +105,30 @@ endif()
|
||||
# build.
|
||||
include(QtPlatformSupport)
|
||||
|
||||
# Set FEATURE_${feature} if INPUT_${feature} is set in certain circumstances.
|
||||
#
|
||||
# Needs to be in QtBuildInternalsConfig.cmake instead of QtFeature.cmake because it's used in
|
||||
# qt_build_internals_disable_pkg_config_if_needed.
|
||||
function(qt_internal_compute_feature_value_from_possible_input feature)
|
||||
# If FEATURE_ is not defined try to use the INPUT_ variable to enable/disable feature.
|
||||
# If FEATURE_ is defined and the configure script is being used (so
|
||||
# QT_INTERNAL_CALLED_FROM_CONFIGURE is TRUE), ignore the FEATURE_ variable, and take into
|
||||
# account the INPUT_ variable instead, because a command line argument takes priority over
|
||||
# a pre-cached FEATURE_ variable.
|
||||
if((NOT DEFINED FEATURE_${feature} OR QT_INTERNAL_CALLED_FROM_CONFIGURE)
|
||||
AND DEFINED INPUT_${feature}
|
||||
AND NOT "${INPUT_${feature}}" STREQUAL "undefined"
|
||||
AND NOT "${INPUT_${feature}}" STREQUAL "")
|
||||
if(INPUT_${feature})
|
||||
set(FEATURE_${feature} ON)
|
||||
else()
|
||||
set(FEATURE_${feature} OFF)
|
||||
endif()
|
||||
|
||||
set(FEATURE_${feature} "${FEATURE_${feature}}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_build_internals_disable_pkg_config_if_needed)
|
||||
# pkg-config should not be used by default on Darwin and Windows platforms (and QNX), as defined
|
||||
# in the qtbase/configure.json. Unfortunately by the time the feature is evaluated there are
|
||||
@ -131,15 +155,7 @@ function(qt_build_internals_disable_pkg_config_if_needed)
|
||||
endif()
|
||||
|
||||
# Features won't have been evaluated yet if this is the first run, have to evaluate this here
|
||||
if ((NOT DEFINED "FEATURE_pkg_config") AND (DEFINED "INPUT_pkg_config")
|
||||
AND (NOT "${INPUT_pkg_config}" STREQUAL "undefined")
|
||||
AND (NOT "${INPUT_pkg_config}" STREQUAL ""))
|
||||
if(INPUT_pkg_config)
|
||||
set(FEATURE_pkg_config ON)
|
||||
else()
|
||||
set(FEATURE_pkg_config OFF)
|
||||
endif()
|
||||
endif()
|
||||
qt_internal_compute_feature_value_from_possible_input(pkg_config)
|
||||
|
||||
# If user explicitly specified a value for the feature, honor it, even if it might break
|
||||
# the build.
|
||||
@ -296,7 +312,27 @@ function(qt_build_internals_add_toplevel_targets)
|
||||
COMMENT "Building everything in ${qt_repo_targets_name}/${qt_repo_target_basename}")
|
||||
add_dependencies("${qt_repo_target_name}" ${qt_repo_targets})
|
||||
list(APPEND qt_repo_target_all "${qt_repo_target_name}")
|
||||
|
||||
# Create special dependency target for External Project examples excluding targets
|
||||
# marked as skipped.
|
||||
set(qt_repo_target_name
|
||||
"${qt_repo_targets_name}_${qt_repo_target_basename}_for_examples")
|
||||
add_custom_target("${qt_repo_target_name}")
|
||||
|
||||
set(unskipped_targets "")
|
||||
foreach(target IN LISTS qt_repo_targets)
|
||||
if(TARGET "${target}")
|
||||
qt_internal_is_target_skipped_for_examples("${target}" is_skipped)
|
||||
if(NOT is_skipped)
|
||||
list(APPEND unskipped_targets "${target}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
if(unskipped_targets)
|
||||
add_dependencies("${qt_repo_target_name}" ${unskipped_targets})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
if (qt_repo_target_all)
|
||||
# Note qt_repo_targets_name is different from qt_repo_target_name that is used above.
|
||||
@ -570,9 +606,27 @@ macro(qt_build_repo_end)
|
||||
set(QT_INTERNAL_FRESH_REQUESTED "FALSE" CACHE INTERNAL "")
|
||||
endif()
|
||||
|
||||
if(NOT QT_SUPERBUILD)
|
||||
qt_internal_qt_configure_end()
|
||||
endif()
|
||||
|
||||
list(POP_BACK CMAKE_MESSAGE_CONTEXT)
|
||||
endmacro()
|
||||
|
||||
# Function called either at the end of per-repo configuration, or at the end of configuration of
|
||||
# a super build.
|
||||
# At the moment it is called before examples are configured in a per-repo build. We might want
|
||||
# to change that at some point if needed.
|
||||
function(qt_internal_qt_configure_end)
|
||||
# If Qt is configued via the configure script, remove the marker variable, so that any future
|
||||
# reconfigurations that are done by calling cmake directly don't trigger configure specific
|
||||
# logic.
|
||||
unset(QT_INTERNAL_CALLED_FROM_CONFIGURE CACHE)
|
||||
|
||||
# Clean up stale feature input values.
|
||||
qt_internal_clean_feature_inputs()
|
||||
endfunction()
|
||||
|
||||
macro(qt_build_repo)
|
||||
qt_build_repo_begin(${ARGN})
|
||||
|
||||
@ -856,7 +910,7 @@ macro(qt_examples_build_begin)
|
||||
set(QT_EXAMPLE_DEPENDENCIES ${qt_repo_plugins_recursive} ${arg_DEPENDS})
|
||||
|
||||
if(TARGET ${qt_repo_targets_name}_src)
|
||||
list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_src)
|
||||
list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_src_for_examples)
|
||||
endif()
|
||||
|
||||
if(TARGET ${qt_repo_targets_name}_tools)
|
||||
@ -980,19 +1034,118 @@ set(CMAKE_INSTALL_PREFIX \"\${_qt_internal_examples_cmake_install_prefix_backup}
|
||||
set(CMAKE_UNITY_BUILD ${QT_UNITY_BUILD})
|
||||
endmacro()
|
||||
|
||||
# Allows building an example either as an ExternalProject or in-tree with the Qt build.
|
||||
# Also allows installing the example sources.
|
||||
function(qt_internal_add_example subdir)
|
||||
# Pre-compute unique example name based on the subdir, in case of target name clashes.
|
||||
qt_internal_get_example_unique_name(unique_example_name "${subdir}")
|
||||
|
||||
# QT_INTERNAL_NO_CONFIGURE_EXAMPLES is not meant to be used by Qt builders, it's here for faster
|
||||
# testing of the source installation code path for build system engineers.
|
||||
if(NOT QT_INTERNAL_NO_CONFIGURE_EXAMPLES)
|
||||
if(NOT QT_IS_EXTERNAL_EXAMPLES_BUILD)
|
||||
qt_internal_add_example_in_tree(${ARGV})
|
||||
qt_internal_add_example_in_tree("${subdir}")
|
||||
else()
|
||||
qt_internal_add_example_external_project(${ARGV})
|
||||
qt_internal_add_example_external_project("${subdir}"
|
||||
NAME "${unique_example_name}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(QT_INSTALL_EXAMPLES_SOURCES)
|
||||
string(TOLOWER ${PROJECT_NAME} project_name_lower)
|
||||
|
||||
qt_internal_install_example_sources("${subdir}"
|
||||
NAME "${unique_example_name}"
|
||||
REPO_NAME "${project_name_lower}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Gets the install prefix where an example should be installed.
|
||||
# Used for computing the final installation path.
|
||||
function(qt_internal_get_example_install_prefix out_var)
|
||||
# Allow customizing the installation path of the examples. Will be used in CI.
|
||||
if(QT_INTERNAL_EXAMPLES_INSTALL_PREFIX)
|
||||
set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_INSTALL_PREFIX}")
|
||||
else()
|
||||
set(qt_example_install_prefix "${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLESDIR}")
|
||||
endif()
|
||||
file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
|
||||
set(${out_var} "${qt_example_install_prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Gets the install prefix where an example's sources should be installed.
|
||||
# Used for computing the final installation path.
|
||||
function(qt_internal_get_examples_sources_install_prefix out_var)
|
||||
# Allow customizing the installation path of the examples source specifically.
|
||||
if(QT_INTERNAL_EXAMPLES_SOURCES_INSTALL_PREFIX)
|
||||
set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_SOURCES_INSTALL_PREFIX}")
|
||||
else()
|
||||
qt_internal_get_example_install_prefix(qt_example_install_prefix)
|
||||
endif()
|
||||
file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
|
||||
set(${out_var} "${qt_example_install_prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Gets the relative path of an example, relative to the current repo's examples source dir.
|
||||
# QT_EXAMPLE_BASE_DIR is meant to be already set in a parent scope.
|
||||
function(qt_internal_get_example_rel_path out_var subdir)
|
||||
file(RELATIVE_PATH example_rel_path
|
||||
"${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
|
||||
set(${out_var} "${example_rel_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Gets the install path where an example should be installed.
|
||||
function(qt_internal_get_example_install_path out_var subdir)
|
||||
qt_internal_get_example_install_prefix(qt_example_install_prefix)
|
||||
qt_internal_get_example_rel_path(example_rel_path "${subdir}")
|
||||
set(example_install_path "${qt_example_install_prefix}/${example_rel_path}")
|
||||
|
||||
set(${out_var} "${example_install_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Gets the install path where an example's sources should be installed.
|
||||
function(qt_internal_get_examples_sources_install_path out_var subdir)
|
||||
qt_internal_get_examples_sources_install_prefix(qt_example_install_prefix)
|
||||
qt_internal_get_example_rel_path(example_rel_path "${subdir}")
|
||||
set(example_install_path "${qt_example_install_prefix}/${example_rel_path}")
|
||||
|
||||
set(${out_var} "${example_install_path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Get the unique name of an example project based on its subdir or explicitly given name.
|
||||
# Makes the name unique by appending a short sha1 hash of the relative path of the example
|
||||
# if a target of the same name already exist.
|
||||
function(qt_internal_get_example_unique_name out_var subdir)
|
||||
qt_internal_get_example_rel_path(example_rel_path "${subdir}")
|
||||
|
||||
set(name "${subdir}")
|
||||
|
||||
# qtdeclarative has calls like qt_internal_add_example(imagine/automotive)
|
||||
# so passing a nested subdirectory. Custom targets (and thus ExternalProjects) can't contain
|
||||
# slashes, so extract the last part of the path to be used as a name.
|
||||
if(name MATCHES "/")
|
||||
string(REPLACE "/" ";" exploded_path "${name}")
|
||||
list(POP_BACK exploded_path last_dir)
|
||||
if(NOT last_dir)
|
||||
message(FATAL_ERROR "Example subdirectory must have a name.")
|
||||
else()
|
||||
set(name "${last_dir}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Likely a clash with an example subdir ExternalProject custom target of the same name in a
|
||||
# top-level build.
|
||||
if(TARGET "${name}")
|
||||
string(SHA1 rel_path_hash "${example_rel_path}")
|
||||
string(SUBSTRING "${rel_path_hash}" 0 4 short_hash)
|
||||
set(name "${name}-${short_hash}")
|
||||
endif()
|
||||
|
||||
set(${out_var} "${name}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Use old non-ExternalProject approach, aka build in-tree with the Qt build.
|
||||
function(qt_internal_add_example_in_tree subdir)
|
||||
file(RELATIVE_PATH example_rel_path
|
||||
"${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
|
||||
|
||||
# Unset the default CMAKE_INSTALL_PREFIX that's generated in
|
||||
# ${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
|
||||
# so we can override it with a different value in
|
||||
@ -1006,15 +1159,8 @@ unset(CMAKE_INSTALL_PREFIX)
|
||||
|
||||
# Override the install prefix in the subdir cmake_install.cmake, so that
|
||||
# relative install(TARGETS DESTINATION) calls in example projects install where we tell them to.
|
||||
# Allow customizing the installation path of the examples. Will be used in CI.
|
||||
if(QT_INTERNAL_EXAMPLES_INSTALL_PREFIX)
|
||||
set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_INSTALL_PREFIX}")
|
||||
else()
|
||||
set(qt_example_install_prefix "${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLESDIR}")
|
||||
endif()
|
||||
file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "${qt_example_install_prefix}/${example_rel_path}")
|
||||
qt_internal_get_example_install_path(example_install_path "${subdir}")
|
||||
set(CMAKE_INSTALL_PREFIX "${example_install_path}")
|
||||
|
||||
# Make sure unclean example projects have their INSTALL_EXAMPLEDIR set to "."
|
||||
# Won't have any effect on example projects that don't use INSTALL_EXAMPLEDIR.
|
||||
@ -1024,7 +1170,7 @@ unset(CMAKE_INSTALL_PREFIX)
|
||||
# TODO: Remove once all repositories use qt_internal_add_example instead of add_subdirectory.
|
||||
set(QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT ON)
|
||||
|
||||
add_subdirectory(${subdir} ${ARGN})
|
||||
add_subdirectory(${subdir})
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_add_example_external_project subdir)
|
||||
@ -1034,33 +1180,6 @@ function(qt_internal_add_example_external_project subdir)
|
||||
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${singleOpts}" "${multiOpts}")
|
||||
|
||||
file(RELATIVE_PATH example_rel_path
|
||||
"${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
|
||||
|
||||
if(NOT arg_NAME)
|
||||
set(arg_NAME "${subdir}")
|
||||
|
||||
# qtdeclarative has calls like qt_internal_add_example(imagine/automotive)
|
||||
# so passing a nested subdirectory. Custom targets (and thus ExternalProjects) can't contain
|
||||
# slashes, so extract the last part of the path to be used as a name.
|
||||
if(arg_NAME MATCHES "/")
|
||||
string(REPLACE "/" ";" exploded_path "${arg_NAME}")
|
||||
list(POP_BACK exploded_path last_dir)
|
||||
if(NOT last_dir)
|
||||
message(FATAL_ERROR "Example subdirectory must have a name.")
|
||||
else()
|
||||
set(arg_NAME "${last_dir}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Likely a clash with an example subdir ExternalProject custom target of the same name.
|
||||
if(TARGET "${arg_NAME}")
|
||||
string(SHA1 rel_path_hash "${example_rel_path}")
|
||||
string(SUBSTRING "${rel_path_hash}" 0 4 short_hash)
|
||||
set(arg_NAME "${arg_NAME}-${short_hash}")
|
||||
endif()
|
||||
|
||||
# TODO: Fix example builds when using Conan / install prefixes are different for each repo.
|
||||
if(QT_SUPERBUILD OR QtBase_BINARY_DIR)
|
||||
# When doing a top-level build or when building qtbase,
|
||||
@ -1281,15 +1400,7 @@ function(qt_internal_add_example_external_project subdir)
|
||||
# example_source_dir, use _qt_internal_override_example_install_dir_to_dot to ensure
|
||||
# INSTALL_EXAMPLEDIR does not interfere.
|
||||
|
||||
# Allow customizing the installation path of the examples. Will be used in CI.
|
||||
if(QT_INTERNAL_EXAMPLES_INSTALL_PREFIX)
|
||||
set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_INSTALL_PREFIX}")
|
||||
else()
|
||||
set(qt_example_install_prefix "${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLESDIR}")
|
||||
endif()
|
||||
file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
|
||||
|
||||
set(example_install_prefix "${qt_example_install_prefix}/${example_rel_path}")
|
||||
qt_internal_get_example_install_path(example_install_path "${subdir}")
|
||||
|
||||
set(ep_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}")
|
||||
|
||||
@ -1304,7 +1415,7 @@ function(qt_internal_add_example_external_project subdir)
|
||||
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${subdir}-ep"
|
||||
STAMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/${subdir}-ep/stamp"
|
||||
BINARY_DIR "${ep_binary_dir}"
|
||||
INSTALL_DIR "${example_install_prefix}"
|
||||
INSTALL_DIR "${example_install_path}"
|
||||
INSTALL_COMMAND ""
|
||||
${build_command}
|
||||
TEST_COMMAND ""
|
||||
@ -1358,6 +1469,54 @@ execute_process(
|
||||
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_install_example_sources subdir)
|
||||
set(options "")
|
||||
set(single_args NAME REPO_NAME)
|
||||
set(multi_args "")
|
||||
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${single_args}" "${multi_args}")
|
||||
|
||||
qt_internal_get_examples_sources_install_path(example_install_path "${subdir}")
|
||||
|
||||
# The trailing slash is important to avoid duplicate nested directory names.
|
||||
set(example_source_dir "${subdir}/")
|
||||
|
||||
# Allow controlling whether sources should be part of the default install target.
|
||||
if(QT_INSTALL_EXAMPLES_SOURCES_BY_DEFAULT)
|
||||
set(exclude_from_all "")
|
||||
else()
|
||||
set(exclude_from_all "EXCLUDE_FROM_ALL")
|
||||
endif()
|
||||
|
||||
# Create an install component for all example sources. Can also be part of the default
|
||||
# install target if EXCLUDE_FROM_ALL is not passed.
|
||||
install(
|
||||
DIRECTORY "${example_source_dir}"
|
||||
DESTINATION "${example_install_path}"
|
||||
COMPONENT "examples_sources"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
${exclude_from_all}
|
||||
)
|
||||
|
||||
# Also create a specific install component just for this repo's examples.
|
||||
install(
|
||||
DIRECTORY "${example_source_dir}"
|
||||
DESTINATION "${example_install_path}"
|
||||
COMPONENT "examples_sources_${arg_REPO_NAME}"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
# Also create a specific install component just for the current example's sources.
|
||||
install(
|
||||
DIRECTORY "${example_source_dir}"
|
||||
DESTINATION "${example_install_path}"
|
||||
COMPONENT "examples_sources_${arg_NAME}"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
endfunction()
|
||||
|
||||
if ("STANDALONE_TEST" IN_LIST Qt6BuildInternals_FIND_COMPONENTS)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/QtStandaloneTestTemplateProject/Main.cmake)
|
||||
if (NOT PROJECT_VERSION_MAJOR)
|
||||
|
@ -103,6 +103,9 @@ set(QT_BUILD_EXAMPLES_AS_EXTERNAL "@QT_BUILD_EXAMPLES_AS_EXTERNAL@" CACHE BOOL
|
||||
# Propagate usage of ccache.
|
||||
set(QT_USE_CCACHE @QT_USE_CCACHE@ CACHE BOOL "Enable the use of ccache")
|
||||
|
||||
# Propagate usage of vcpkg, ON by default.
|
||||
set(QT_USE_VCPKG @QT_USE_VCPKG@ CACHE BOOL "Enable the use of vcpkg")
|
||||
|
||||
# Propagate usage of unity build.
|
||||
set(QT_UNITY_BUILD @QT_UNITY_BUILD@ CACHE BOOL "Enable unity (jumbo) build")
|
||||
set(QT_UNITY_BUILD_BATCH_SIZE "@QT_UNITY_BUILD_BATCH_SIZE@" CACHE STRING "Unity build batch size")
|
||||
@ -163,6 +166,7 @@ function(qt_internal_force_set_cmake_build_type_conditionally value)
|
||||
AND NOT QT_NO_FORCE_SET_CMAKE_BUILD_TYPE
|
||||
AND NOT __qt_internal_extras_is_multi_config)
|
||||
set(CMAKE_BUILD_TYPE "${value}" CACHE STRING "Choose the type of build." FORCE)
|
||||
set(__qt_build_internals_cmake_build_type "${value}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
@ -14,6 +14,8 @@ function(qt_internal_get_supported_min_cmake_version_for_building_qt out_var)
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT}")
|
||||
|
||||
# We're building qtbase so the values come from .cmake.conf.
|
||||
elseif(APPLE)
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_APPLE}")
|
||||
elseif(BUILD_SHARED_LIBS)
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_SHARED}")
|
||||
else()
|
||||
@ -30,7 +32,9 @@ function(qt_internal_get_supported_min_cmake_version_for_using_qt out_var)
|
||||
"It should have been set by this point.")
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(APPLE)
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_APPLE}")
|
||||
elseif(BUILD_SHARED_LIBS)
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_SHARED}")
|
||||
else()
|
||||
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_STATIC}")
|
||||
|
@ -92,10 +92,10 @@ endif()
|
||||
|
||||
# Windows MSVC
|
||||
if(MSVC)
|
||||
set(QT_CFLAGS_OPTIMIZE "-O2")
|
||||
set(QT_CFLAGS_OPTIMIZE "-O2 -Ob3") # -Ob3 was introduced in Visual Studio 2019 version 16.0
|
||||
set(QT_CFLAGS_OPTIMIZE_DEBUG "-Od")
|
||||
set(QT_CFLAGS_OPTIMIZE_SIZE "-O1")
|
||||
set(QT_CFLAGS_OPTIMIZE_VALID_VALUES "/O2" "/O1" "/Od" "/Ob0" "/Ob1" "/Ob2" "/O0" "-O0")
|
||||
set(QT_CFLAGS_OPTIMIZE_VALID_VALUES "/O2" "/O1" "/Od" "/Ob0" "/Ob1" "/Ob2" "/Ob3" "/O0" "-O0")
|
||||
|
||||
if(CLANG)
|
||||
set(QT_CFLAGS_OPTIMIZE_FULL "/clang:-O3")
|
||||
|
@ -29,13 +29,12 @@ list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}")
|
||||
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/3rdparty/extra-cmake-modules/find-modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/3rdparty/kwin")
|
||||
|
||||
if(APPLE AND (NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
|
||||
# Add module directory to pick up custom Info.plist template for macOS
|
||||
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/macos")
|
||||
elseif(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
# Add module directory to pick up custom Info.plist template for iOS
|
||||
set(__qt_internal_cmake_ios_support_files_path "${_qt_import_prefix}/ios")
|
||||
list(APPEND CMAKE_MODULE_PATH "${__qt_internal_cmake_ios_support_files_path}")
|
||||
if(APPLE)
|
||||
if(NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(__qt_internal_cmake_apple_support_files_path "${_qt_import_prefix}/macos")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
set(__qt_internal_cmake_apple_support_files_path "${_qt_import_prefix}/ios")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Public helpers available to all Qt packages.
|
||||
|
@ -148,7 +148,7 @@ function(qt_internal_add_executable name)
|
||||
|
||||
if(WASM)
|
||||
# WASM unconditionally sets DISABLE_EXCEPTION_CATCHING=1
|
||||
qt_internal_set_exceptions_flags("${name}" NO_EXCEPTIONS)
|
||||
qt_internal_set_exceptions_flags("${name}" FALSE)
|
||||
else()
|
||||
qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS})
|
||||
endif()
|
||||
@ -422,7 +422,7 @@ function(qt_internal_add_configure_time_executable target)
|
||||
)
|
||||
|
||||
set(should_build_at_configure_time TRUE)
|
||||
if(EXISTS "${target_binary_path}")
|
||||
if(EXISTS "${target_binary_path}" AND EXISTS "${timestamp_file}")
|
||||
set(last_ts 0)
|
||||
foreach(source IN LISTS sources)
|
||||
file(TIMESTAMP "${source}" ts "%s")
|
||||
|
@ -177,15 +177,20 @@ function(qt_evaluate_config_expression resultVar)
|
||||
set(${resultVar} ${result} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_get_feature_condition_keywords out_var)
|
||||
set(keywords "EQUAL" "LESS" "LESS_EQUAL" "GREATER" "GREATER_EQUAL" "STREQUAL" "STRLESS"
|
||||
"STRLESS_EQUAL" "STRGREATER" "STRGREATER_EQUAL" "VERSION_EQUAL" "VERSION_LESS"
|
||||
"VERSION_LESS_EQUAL" "VERSION_GREATER" "VERSION_GREATER_EQUAL" "MATCHES"
|
||||
"EXISTS" "COMMAND" "DEFINED" "NOT" "AND" "OR" "TARGET" "EXISTS" "IN_LIST" "(" ")")
|
||||
set(${out_var} "${keywords}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_dump_expression_values expression_dump expression)
|
||||
set(dump "")
|
||||
set(skipNext FALSE)
|
||||
set(isTargetExpression FALSE)
|
||||
|
||||
set(keywords "EQUAL" "LESS" "LESS_EQUAL" "GREATER" "GREATER_EQUAL" "STREQUAL" "STRLESS"
|
||||
"STRLESS_EQUAL" "STRGREATER" "STRGREATER_EQUAL" "VERSION_EQUAL" "VERSION_LESS"
|
||||
"VERSION_LESS_EQUAL" "VERSION_GREATER" "VERSION_GREATER_EQUAL" "MATCHES"
|
||||
"EXISTS" "COMMAND" "DEFINED" "NOT" "AND" "OR" "TARGET" "EXISTS" "IN_LIST" "(" ")")
|
||||
_qt_internal_get_feature_condition_keywords(keywords)
|
||||
|
||||
list(LENGTH expression length)
|
||||
math(EXPR length "${length}-1")
|
||||
@ -239,19 +244,44 @@ endfunction()
|
||||
# ${computed} is also stored when reconfiguring and the condition does not align with the user
|
||||
# provided value.
|
||||
#
|
||||
function(qt_feature_check_and_save_user_provided_value resultVar feature condition computed label)
|
||||
function(qt_feature_check_and_save_user_provided_value
|
||||
resultVar feature condition condition_expression computed label)
|
||||
if (DEFINED "FEATURE_${feature}")
|
||||
# Revisit new user provided value
|
||||
set(user_value "${FEATURE_${feature}}")
|
||||
string(TOUPPER "${user_value}" result)
|
||||
string(TOUPPER "${user_value}" user_value_upper)
|
||||
set(result "${user_value_upper}")
|
||||
|
||||
# If the build is marked as dirty and the user_value doesn't meet the new condition,
|
||||
# reset it to the computed one.
|
||||
# If ${feature} depends on another dirty feature, reset the ${feature} value to
|
||||
# ${computed}.
|
||||
get_property(dirty_build GLOBAL PROPERTY _qt_dirty_build)
|
||||
if(NOT condition AND result AND dirty_build)
|
||||
if(dirty_build)
|
||||
_qt_internal_feature_compute_feature_dependencies(deps "${feature}")
|
||||
if(deps)
|
||||
get_property(dirty_features GLOBAL PROPERTY _qt_dirty_features)
|
||||
foreach(dirty_feature ${dirty_features})
|
||||
if(dirty_feature IN_LIST deps AND NOT "${result}" STREQUAL "${computed}")
|
||||
set(result "${computed}")
|
||||
message(WARNING "Reset FEATURE_${feature} value to ${result}, because it doesn't \
|
||||
meet its condition after reconfiguration.")
|
||||
message(WARNING
|
||||
"Auto-resetting 'FEATURE_${feature}' from '${user_value_upper}' to "
|
||||
"'${computed}', "
|
||||
"because the dependent feature '${dirty_feature}' was marked dirty.")
|
||||
|
||||
# Append ${feature} as a new dirty feature.
|
||||
set_property(GLOBAL APPEND PROPERTY _qt_dirty_features "${feature}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# If the build is marked as dirty and the feature doesn't meet its condition,
|
||||
# reset its value to the computed one, which is likely OFF.
|
||||
if(NOT condition AND result)
|
||||
set(result "${computed}")
|
||||
message(WARNING "Resetting 'FEATURE_${feature}' from '${user_value_upper}' to "
|
||||
"'${computed}' because it doesn't meet its condition after reconfiguration. "
|
||||
"Condition expression is: '${condition_expression}'")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(bool_values OFF NO FALSE N ON YES TRUE Y)
|
||||
@ -299,6 +329,14 @@ condition:\n ${conditionString}\nCondition values dump:\n ${conditionDump}
|
||||
set(QT_KNOWN_FEATURES "${QT_KNOWN_FEATURES}" CACHE INTERNAL "" FORCE)
|
||||
endmacro()
|
||||
|
||||
macro(_qt_internal_parse_feature_definition feature)
|
||||
cmake_parse_arguments(arg
|
||||
"PRIVATE;PUBLIC"
|
||||
"LABEL;PURPOSE;SECTION;"
|
||||
"AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF"
|
||||
${_QT_FEATURE_DEFINITION_${feature}})
|
||||
endmacro()
|
||||
|
||||
|
||||
# The build system stores 2 CMake cache variables for each feature, to allow detecting value changes
|
||||
# during subsequent reconfigurations.
|
||||
@ -334,9 +372,7 @@ function(qt_evaluate_feature feature)
|
||||
message(FATAL_ERROR "Attempting to evaluate feature ${feature} but its definition is missing. Either the feature does not exist or a dependency to the module that defines it is missing")
|
||||
endif()
|
||||
|
||||
cmake_parse_arguments(arg
|
||||
"PRIVATE;PUBLIC"
|
||||
"LABEL;PURPOSE;SECTION;" "AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF" ${_QT_FEATURE_DEFINITION_${feature}})
|
||||
_qt_internal_parse_feature_definition("${feature}")
|
||||
|
||||
if("${arg_ENABLE}" STREQUAL "")
|
||||
set(arg_ENABLE OFF)
|
||||
@ -374,16 +410,7 @@ function(qt_evaluate_feature feature)
|
||||
qt_evaluate_config_expression(emit_if ${arg_EMIT_IF})
|
||||
endif()
|
||||
|
||||
# If FEATURE_ is not defined trying to use INPUT_ variable to enable/disable feature.
|
||||
if ((NOT DEFINED "FEATURE_${feature}") AND (DEFINED "INPUT_${feature}")
|
||||
AND (NOT "${INPUT_${feature}}" STREQUAL "undefined")
|
||||
AND (NOT "${INPUT_${feature}}" STREQUAL ""))
|
||||
if(INPUT_${feature})
|
||||
set(FEATURE_${feature} ON)
|
||||
else()
|
||||
set(FEATURE_${feature} OFF)
|
||||
endif()
|
||||
endif()
|
||||
qt_internal_compute_feature_value_from_possible_input("${feature}")
|
||||
|
||||
# Warn about a feature which is not emitted, but the user explicitly provided a value for it.
|
||||
if(NOT emit_if AND DEFINED FEATURE_${feature})
|
||||
@ -401,7 +428,8 @@ function(qt_evaluate_feature feature)
|
||||
# Only save the user provided value if the feature was emitted.
|
||||
if(emit_if)
|
||||
qt_feature_check_and_save_user_provided_value(
|
||||
saved_user_value "${feature}" "${condition}" "${computed}" "${arg_LABEL}")
|
||||
saved_user_value
|
||||
"${feature}" "${condition}" "${arg_CONDITION}" "${computed}" "${arg_LABEL}")
|
||||
else()
|
||||
# Make sure the feature internal value is OFF if not emitted.
|
||||
set(saved_user_value OFF)
|
||||
@ -414,6 +442,60 @@ function(qt_evaluate_feature feature)
|
||||
set(QT_FEATURE_LABEL_${feature} "${arg_LABEL}" CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
||||
# Collect feature names that ${feature} depends on, by inspecting the given expression.
|
||||
function(_qt_internal_feature_extract_feature_dependencies_from_expression out_var expression)
|
||||
list(LENGTH expression length)
|
||||
math(EXPR length "${length}-1")
|
||||
|
||||
if(length LESS 0)
|
||||
set(${out_var} "" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(deps "")
|
||||
|
||||
foreach(memberIdx RANGE ${length})
|
||||
list(GET expression ${memberIdx} member)
|
||||
if(member MATCHES "^QT_FEATURE_(.+)")
|
||||
list(APPEND deps "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${out_var} "${deps}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Collect feature names that ${feature} depends on, based on feature names that appear
|
||||
# in the ${feature}'s condition expressions.
|
||||
function(_qt_internal_feature_compute_feature_dependencies out_var feature)
|
||||
# Only compute the deps once per feature.
|
||||
get_property(deps_computed GLOBAL PROPERTY _qt_feature_deps_computed_${feature})
|
||||
if(deps_computed)
|
||||
get_property(deps GLOBAL PROPERTY _qt_feature_deps_${feature})
|
||||
set(${out_var} "${deps}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
_qt_internal_parse_feature_definition("${feature}")
|
||||
|
||||
set(options_to_check AUTODETECT CONDITION ENABLE DISABLE EMIT_IF)
|
||||
set(deps "")
|
||||
|
||||
# Go through each option that takes condition expressions and collect the feature names.
|
||||
foreach(option ${options_to_check})
|
||||
set(option_value "${arg_${option}}")
|
||||
if(option_value)
|
||||
_qt_internal_feature_extract_feature_dependencies_from_expression(
|
||||
option_deps "${option_value}")
|
||||
if(option_deps)
|
||||
list(APPEND deps ${option_deps})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set_property(GLOBAL PROPERTY _qt_feature_deps_computed_${feature} TRUE)
|
||||
set_property(GLOBAL PROPERTY _qt_feature_deps_${feature} "${deps}")
|
||||
set(${out_var} "${deps}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_feature_config feature config_var_name)
|
||||
qt_feature_normalize_name("${feature}" feature)
|
||||
cmake_parse_arguments(PARSE_ARGV 2 arg
|
||||
@ -786,6 +868,49 @@ function(qt_feature_copy_global_config_features_to_core target)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_detect_dirty_features)
|
||||
# We need to clean up QT_FEATURE_*, but only once per configuration cycle
|
||||
get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
|
||||
if(NOT qt_feature_clean AND NOT QT_NO_FEATURE_AUTO_RESET)
|
||||
message(STATUS "Checking for feature set changes")
|
||||
set_property(GLOBAL PROPERTY _qt_feature_clean TRUE)
|
||||
foreach(feature ${QT_KNOWN_FEATURES})
|
||||
qt_internal_compute_feature_value_from_possible_input("${feature}")
|
||||
|
||||
if(DEFINED "FEATURE_${feature}" AND
|
||||
NOT "${QT_FEATURE_${feature}}" STREQUAL "${FEATURE_${feature}}")
|
||||
message(" '${feature}' was changed from ${QT_FEATURE_${feature}} "
|
||||
"to ${FEATURE_${feature}}")
|
||||
set(dirty_build TRUE)
|
||||
set_property(GLOBAL APPEND PROPERTY _qt_dirty_features "${feature}")
|
||||
endif()
|
||||
unset("QT_FEATURE_${feature}" CACHE)
|
||||
endforeach()
|
||||
|
||||
set(QT_KNOWN_FEATURES "" CACHE INTERNAL "" FORCE)
|
||||
|
||||
if(dirty_build)
|
||||
set_property(GLOBAL PROPERTY _qt_dirty_build TRUE)
|
||||
message(WARNING
|
||||
"Due to detected feature set changes, dependent features "
|
||||
"will be re-computed automatically. This might cause a lot of files to be rebuilt. "
|
||||
"To disable this behavior, configure with -DQT_NO_FEATURE_AUTO_RESET=ON")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_clean_feature_inputs)
|
||||
foreach(feature IN LISTS QT_KNOWN_FEATURES)
|
||||
# Unset the INPUT_foo cache variables after they were used in feature evaluation, to
|
||||
# ensure stale values don't influence features upon reconfiguration when
|
||||
# QT_INTERNAL_CALLED_FROM_CONFIGURE is TRUE and the INPUT_foo variable is not passed.
|
||||
# e.g. first configure -no-gui, then manually toggle FEATURE_gui to ON in
|
||||
# CMakeCache.txt, then reconfigure (with the configure script) without -no-gui.
|
||||
# Without this unset(), we'd have switched FEATURE_gui to OFF again.
|
||||
unset(INPUT_${feature} CACHE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(qt_config_compile_test name)
|
||||
if(DEFINED "TEST_${name}")
|
||||
return()
|
||||
@ -924,6 +1049,7 @@ function(qt_config_compile_test name)
|
||||
# fail instead of cmake abort later via CMAKE_REQUIRED_LIBRARIES.
|
||||
string(FIND "${library}" "::" cmake_target_namespace_separator)
|
||||
if(NOT cmake_target_namespace_separator EQUAL -1)
|
||||
message(STATUS "Performing Test ${arg_LABEL} - Failed because ${library} not found")
|
||||
set(HAVE_${name} FALSE)
|
||||
break()
|
||||
endif()
|
||||
|
@ -16,6 +16,15 @@ function(qt_find_package_promote_targets_to_global_scope target)
|
||||
"qt_find_package_targets_dict" "promote_global")
|
||||
endfunction()
|
||||
|
||||
# As an optimization when using -developer-build, qt_find_package records which
|
||||
# packages were found during the initial configuration. Then on subsequent
|
||||
# reconfigurations it skips looking for packages that were not found on the
|
||||
# initial run.
|
||||
# For the build system to pick up a newly added qt_find_package call, you need to:
|
||||
# - Start with a clean build dir
|
||||
# - Or remove the <builddir>/CMakeCache.txt file and configure from scratch
|
||||
# - Or remove the QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES cache variable (by
|
||||
# editing CMakeCache.txt) and reconfigure.
|
||||
macro(qt_find_package)
|
||||
# Get the target names we expect to be provided by the package.
|
||||
set(find_package_options CONFIG NO_MODULE MODULE REQUIRED)
|
||||
|
@ -4,6 +4,7 @@
|
||||
macro(qt_find_apple_system_frameworks)
|
||||
if(APPLE)
|
||||
qt_internal_find_apple_system_framework(FWAppKit AppKit)
|
||||
qt_internal_find_apple_system_framework(FWCFNetwork CFNetwork)
|
||||
qt_internal_find_apple_system_framework(FWAssetsLibrary AssetsLibrary)
|
||||
qt_internal_find_apple_system_framework(FWPhotos Photos)
|
||||
qt_internal_find_apple_system_framework(FWAudioToolbox AudioToolbox)
|
||||
@ -58,7 +59,7 @@ function(qt_internal_find_apple_system_framework out_var framework_name)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Copy header files to QtXYZ.framework/Versions/A/Headers/
|
||||
# Copy header files to the framework's Headers directory
|
||||
# Use this function for header files that
|
||||
# - are not added as source files to the target
|
||||
# - are not marked as PUBLIC_HEADER
|
||||
@ -71,7 +72,7 @@ function(qt_copy_framework_headers target)
|
||||
|
||||
set(options)
|
||||
set(oneValueArgs)
|
||||
set(multiValueArgs PUBLIC PRIVATE QPA)
|
||||
set(multiValueArgs PUBLIC PRIVATE QPA RHI)
|
||||
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
qt_internal_get_framework_info(fw ${target})
|
||||
@ -79,10 +80,11 @@ function(qt_copy_framework_headers target)
|
||||
set(output_dir_PUBLIC "${output_dir}/${fw_versioned_header_dir}")
|
||||
set(output_dir_PRIVATE "${output_dir}/${fw_private_module_header_dir}/private")
|
||||
set(output_dir_QPA "${output_dir}/${fw_private_module_header_dir}/qpa")
|
||||
set(output_dir_RHI "${output_dir}/${fw_private_module_header_dir}/rhi")
|
||||
|
||||
|
||||
set(out_files)
|
||||
foreach(type IN ITEMS PUBLIC PRIVATE QPA)
|
||||
foreach(type IN ITEMS PUBLIC PRIVATE QPA RHI)
|
||||
set(fw_output_header_dir "${output_dir_${type}}")
|
||||
foreach(hdr IN LISTS arg_${type})
|
||||
get_filename_component(in_file_path ${hdr} ABSOLUTE)
|
||||
@ -164,8 +166,13 @@ function(qt_internal_get_framework_info out_var target)
|
||||
set(${out_var}_name "${module}")
|
||||
set(${out_var}_dir "${${out_var}_name}.framework")
|
||||
set(${out_var}_header_dir "${${out_var}_dir}/Headers")
|
||||
if(UIKIT)
|
||||
# iOS frameworks do not version their headers
|
||||
set(${out_var}_versioned_header_dir "${${out_var}_header_dir}")
|
||||
else()
|
||||
set(${out_var}_versioned_header_dir "${${out_var}_dir}/Versions/${${out_var}_version}/Headers")
|
||||
set(${out_var}_private_header_dir "${${out_var}_header_dir}/${${out_var}_bundle_version}")
|
||||
endif()
|
||||
set(${out_var}_private_header_dir "${${out_var}_versioned_header_dir}/${${out_var}_bundle_version}")
|
||||
set(${out_var}_private_module_header_dir "${${out_var}_private_header_dir}/${module}")
|
||||
|
||||
set(${out_var}_name "${${out_var}_name}" PARENT_SCOPE)
|
||||
|
@ -104,6 +104,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
|
||||
|
||||
set(hcleanFLAGS -Wall -Wextra -Werror -Woverloaded-virtual -Wshadow -Wundef -Wfloat-equal
|
||||
-Wnon-virtual-dtor -Wpointer-arith -Wformat-security -Wno-long-long -Wno-variadic-macros
|
||||
-fno-operator-names
|
||||
-pedantic-errors)
|
||||
|
||||
if(QT_FEATURE_reduce_relocations AND UNIX)
|
||||
@ -181,9 +182,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
|
||||
)
|
||||
set(input_header_path_type ABSOLUTE)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# -Za would enable strict standards behavior, but we can't add it because
|
||||
# <windows.h> and <GL.h> violate the standards.
|
||||
set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -WX -W3)
|
||||
set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -WX -W3 -EHsc)
|
||||
|
||||
# Because we now add `-DNOMINMAX` to `PlatformCommonInternal`.
|
||||
set(hcleanUDEFS -UNOMINMAX)
|
||||
|
214
cmake/QtInitProject.cmake
Normal file
214
cmake/QtInitProject.cmake
Normal file
@ -0,0 +1,214 @@
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
if(NOT PROJECT_DIR)
|
||||
set(PROJECT_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
get_filename_component(project_name "${PROJECT_DIR}" NAME)
|
||||
|
||||
get_filename_component(project_abs_dir "${PROJECT_DIR}" ABSOLUTE)
|
||||
if(NOT IS_DIRECTORY "${project_abs_dir}")
|
||||
message(FATAL_ERROR "Unable to scan ${project_abs_dir}. The directory doesn't exist.")
|
||||
endif()
|
||||
|
||||
set(known_extensions "")
|
||||
set(types "")
|
||||
|
||||
# The function allows extending the capabilities of this script and establishes simple relation
|
||||
# chains between the file types.
|
||||
# Option Arguments:
|
||||
# EXPERIMENTAL
|
||||
# Marks that the support of the following files is experimental and the required Qt modules
|
||||
# are in Technical preview state.
|
||||
# DEPRECATED
|
||||
# Marks that the support of the following files will be discontinued soon and the required
|
||||
# Qt modules are deprecated.
|
||||
# One-value Arguments:
|
||||
# TEMPLATE
|
||||
# The CMake code template. Use the '@files@' string for the files substitution.
|
||||
# Multi-value Arguments:
|
||||
# EXTENSIONS
|
||||
# List of the file extensions treated as this source 'type'.
|
||||
# MODULES
|
||||
# List of Qt modules required for these file types.
|
||||
# DEPENDS
|
||||
# The prerequisite source 'type' needed by this source 'type'
|
||||
macro(handle_type type)
|
||||
cmake_parse_arguments(arg
|
||||
"EXPERIMENTAL;DEPRECATED"
|
||||
"TEMPLATE"
|
||||
"EXTENSIONS;MODULES;DEPENDS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if(NOT arg_EXTENSIONS)
|
||||
message(FATAL_ERROR "Unexpected call handle_type of with no EXTENSIONS specified."
|
||||
" This is the Qt issue, please report a bug at https://bugreports.qt.io.")
|
||||
endif()
|
||||
set(unique_extensions_subset "${known_extensions}")
|
||||
list(REMOVE_ITEM unique_extensions_subset ${arg_EXTENSIONS})
|
||||
if(NOT "${known_extensions}" STREQUAL "${unique_extensions_subset}")
|
||||
message(FATAL_ERROR "${type} contains duplicated extensions, this is not supported."
|
||||
" This is the Qt issue, please report a bug at https://bugreports.qt.io.")
|
||||
endif()
|
||||
set(${type}_file_extensions "${arg_EXTENSIONS}")
|
||||
|
||||
if(NOT arg_TEMPLATE)
|
||||
message(FATAL_ERROR "Unexpected call handle_type of with no TEMPLATE specified."
|
||||
" This is the Qt issue, please report a bug at https://bugreports.qt.io.")
|
||||
endif()
|
||||
set(${type}_template "${arg_TEMPLATE}")
|
||||
|
||||
if(arg_MODULES)
|
||||
set(${type}_required_modules "${arg_MODULES}")
|
||||
endif()
|
||||
|
||||
list(APPEND types ${type})
|
||||
|
||||
if(arg_EXPERIMENTAL)
|
||||
set(${type}_is_experimental TRUE)
|
||||
else()
|
||||
set(${type}_is_experimental FALSE)
|
||||
endif()
|
||||
|
||||
if(arg_DEPRECATED)
|
||||
set(${type}_is_deprecated TRUE)
|
||||
else()
|
||||
set(${type}_is_deprecated FALSE)
|
||||
endif()
|
||||
|
||||
if(arg_DEPENDS)
|
||||
set(${type}_dependencies ${arg_DEPENDS})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
handle_type(cpp EXTENSIONS .c .cc .cpp .cxx .h .hh .hxx .hpp MODULES Core TEMPLATE
|
||||
"\n\nqt_add_executable(${project_name}
|
||||
@files@
|
||||
)"
|
||||
)
|
||||
|
||||
handle_type(qml EXTENSIONS .qml .js .mjs MODULES Gui Qml Quick TEMPLATE
|
||||
"\n\nqt_add_qml_module(${project_name}
|
||||
URI ${project_name}
|
||||
OUTPUT_DIRECTORY qml
|
||||
VERSION 1.0
|
||||
RESOURCE_PREFIX /qt/qml
|
||||
QML_FILES
|
||||
@files@
|
||||
)"
|
||||
)
|
||||
|
||||
handle_type(ui EXTENSIONS .ui MODULES Gui Widgets DEPENDS cpp TEMPLATE
|
||||
"\n\ntarget_sources(${project_name}
|
||||
PRIVATE
|
||||
@files@
|
||||
)"
|
||||
)
|
||||
|
||||
handle_type(qrc EXTENSIONS .qrc DEPENDS cpp TEMPLATE
|
||||
"\n\nqt_add_resources(${project_name}_resources @files@)
|
||||
target_sources(${project_name}
|
||||
PRIVATE
|
||||
\\\${${project_name}_resources}
|
||||
)"
|
||||
)
|
||||
|
||||
handle_type(protobuf EXPERIMENTAL EXTENSIONS .proto MODULES Protobuf Grpc TEMPLATE
|
||||
"\n\nqt_add_protobuf(${project_name}
|
||||
GENERATE_PACKAGE_SUBFOLDERS
|
||||
PROTO_FILES
|
||||
@files@
|
||||
)"
|
||||
)
|
||||
|
||||
set(extra_packages "")
|
||||
file(GLOB_RECURSE files RELATIVE "${project_abs_dir}" "${project_abs_dir}/*")
|
||||
foreach(f IN LISTS files)
|
||||
get_filename_component(file_extension "${f}" LAST_EXT)
|
||||
string(TOLOWER "${file_extension}" file_extension)
|
||||
|
||||
foreach(type IN LISTS types)
|
||||
if(file_extension IN_LIST ${type}_file_extensions)
|
||||
list(APPEND ${type}_sources "${f}")
|
||||
list(APPEND packages ${${type}_required_modules})
|
||||
if(${type}_is_experimental)
|
||||
message("We found files with the following extensions in your directory:"
|
||||
" ${${type}_file_extensions}\n"
|
||||
"Note that the modules ${${type}_required_modules} are"
|
||||
" in the technical preview state.")
|
||||
endif()
|
||||
if(${type}_is_deprecated)
|
||||
message("We found files with the following extensions in your directory:"
|
||||
" ${${type}_file_extensions}\n"
|
||||
"Note that the modules ${${type}_required_modules} are deprecated.")
|
||||
endif()
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(packages)
|
||||
list(REMOVE_DUPLICATES packages)
|
||||
list(JOIN packages " " packages_string)
|
||||
list(JOIN packages "\n Qt::" deps_string)
|
||||
set(deps_string "Qt::${deps_string}")
|
||||
endif()
|
||||
|
||||
set(content
|
||||
"cmake_minimum_required(VERSION 3.16)
|
||||
project(${project_name} LANGUAGES CXX)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS ${packages_string})
|
||||
qt_standard_project_setup()"
|
||||
)
|
||||
|
||||
set(has_useful_sources FALSE)
|
||||
foreach(type IN LISTS types)
|
||||
if(${type}_sources)
|
||||
set(skip FALSE)
|
||||
foreach(dep IN LISTS ${type}_dependencies)
|
||||
if(NOT ${dep}_sources)
|
||||
set(skip TRUE)
|
||||
message("Sources of type ${${type}_file_extensions} cannot live in the project"
|
||||
" without ${${dep}_file_extensions} files. Skipping.")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(skip)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
set(has_useful_sources TRUE)
|
||||
string(REGEX MATCH "( +)@files@" unused "${${type}_template}")
|
||||
list(JOIN ${type}_sources "\n${CMAKE_MATCH_1}" ${type}_sources)
|
||||
string(REPLACE "@files@" "${${type}_sources}" ${type}_content
|
||||
"${${type}_template}")
|
||||
string(APPEND content "${${type}_content}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
string(APPEND content "\n\ntarget_link_libraries(${project_name}
|
||||
PRIVATE
|
||||
${deps_string}
|
||||
)\n"
|
||||
)
|
||||
|
||||
if(EXISTS "${project_abs_dir}/CMakeLists.txt")
|
||||
message(FATAL_ERROR "Project is already initialized in current directory."
|
||||
" Please remove CMakeLists.txt if you want to regenerate the project.")
|
||||
endif()
|
||||
|
||||
if(NOT has_useful_sources)
|
||||
message(FATAL_ERROR "Could not find any files to generate the project.")
|
||||
endif()
|
||||
file(WRITE "${project_abs_dir}/CMakeLists.txt" "${content}")
|
||||
|
||||
message("The project file is successfully generated. To build the project run:"
|
||||
"\nmkdir build"
|
||||
"\ncd build"
|
||||
"\nqt-cmake ${project_abs_dir}"
|
||||
"\ncmake --build ${project_abs_dir}"
|
||||
)
|
@ -156,6 +156,8 @@ qt_internal_add_target_aliases(PlatformToolInternal)
|
||||
target_link_libraries(PlatformToolInternal INTERFACE PlatformAppInternal)
|
||||
|
||||
qt_internal_add_global_definition(QT_NO_JAVA_STYLE_ITERATORS)
|
||||
qt_internal_add_global_definition(QT_NO_AS_CONST)
|
||||
qt_internal_add_global_definition(QT_NO_QEXCHANGE)
|
||||
qt_internal_add_global_definition(QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
|
||||
qt_internal_add_global_definition(QT_EXPLICIT_QFILE_CONSTRUCTION_FROM_PATH)
|
||||
|
||||
|
@ -35,6 +35,15 @@ function(qt_process_qlalr consuming_target input_file_list flags)
|
||||
return()
|
||||
endif()
|
||||
|
||||
qt_internal_is_skipped_test(skipped ${consuming_target})
|
||||
if(skipped)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_is_in_test_batch(in_batch ${consuming_target})
|
||||
if(in_batch)
|
||||
_qt_internal_test_batch_target_name(consuming_target)
|
||||
endif()
|
||||
|
||||
foreach(input_file ${input_file_list})
|
||||
file(STRINGS ${input_file} input_file_lines)
|
||||
qt_qlalr_find_option_in_list("${input_file_lines}" "^%parser(.+)" "parser")
|
||||
|
@ -27,6 +27,8 @@ endif()
|
||||
if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Targets.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@AdditionalTargetInfo.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@ExtraProperties.cmake"
|
||||
OPTIONAL)
|
||||
if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake")
|
||||
endif()
|
||||
|
@ -30,6 +30,7 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
|
||||
EXTERNAL_HEADERS_DIR
|
||||
PRIVATE_HEADER_FILTERS
|
||||
QPA_HEADER_FILTERS
|
||||
RHI_HEADER_FILTERS
|
||||
HEADER_SYNC_SOURCE_DIRECTORY
|
||||
${__default_target_info_args}
|
||||
)
|
||||
@ -114,6 +115,10 @@ endfunction()
|
||||
# The regular expressions that filter QPA header files out of target sources.
|
||||
# The value must use the following format 'regex1|regex2|regex3'.
|
||||
#
|
||||
# RHI_HEADER_FILTERS
|
||||
# The regular expressions that filter RHI header files out of target sources.
|
||||
# The value must use the following format 'regex1|regex2|regex3'.
|
||||
#
|
||||
# HEADER_SYNC_SOURCE_DIRECTORY
|
||||
# The source directory for header sync procedure. Header files outside this directory will be
|
||||
# ignored by syncqt. The specifying this directory allows to skip the parsing of the whole
|
||||
@ -326,13 +331,23 @@ function(qt_internal_add_module target)
|
||||
EXPORT_PROPERTIES "${export_properties}")
|
||||
endif()
|
||||
|
||||
# FIXME: This workaround is needed because the deployment logic
|
||||
# for iOS and WASM just copies/embeds the directly linked library,
|
||||
# which will just be a versioned symlink to the actual library.
|
||||
if((UIKIT OR WASM) AND BUILD_SHARED_LIBS)
|
||||
set(version_args "")
|
||||
else()
|
||||
set(version_args
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
if(NOT arg_HEADER_MODULE)
|
||||
set_target_properties(${target} PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
${version_args}
|
||||
)
|
||||
qt_set_target_info_properties(${target} ${ARGN})
|
||||
qt_handle_multi_config_output_dirs("${target}")
|
||||
@ -436,6 +451,13 @@ function(qt_internal_add_module target)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES _qt_module_qpa_headers_filter_regex "${qpa_filter_regex}")
|
||||
|
||||
set(rhi_filter_regex "")
|
||||
if(arg_RHI_HEADER_FILTERS)
|
||||
set(rhi_filter_regex "${arg_RHI_HEADER_FILTERS}")
|
||||
endif()
|
||||
set_target_properties(${target}
|
||||
PROPERTIES _qt_module_rhi_headers_filter_regex "${rhi_filter_regex}")
|
||||
|
||||
set(private_filter_regex ".+_p(ch)?\\.h")
|
||||
if(arg_PRIVATE_HEADER_FILTERS)
|
||||
set(private_filter_regex "${private_filter_regex}|${arg_PRIVATE_HEADER_FILTERS}")
|
||||
@ -793,6 +815,11 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
|
||||
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
|
||||
CONFIG_INSTALL_DIR "${config_install_dir}")
|
||||
|
||||
qt_internal_export_genex_properties(TARGETS ${target}
|
||||
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
|
||||
CONFIG_INSTALL_DIR "${config_install_dir}"
|
||||
)
|
||||
|
||||
### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins
|
||||
# that belong to Qt.
|
||||
if(NOT arg_HEADER_MODULE)
|
||||
@ -878,6 +905,7 @@ function(qt_finalize_module target)
|
||||
PUBLIC ${module_headers_public} "${module_depends_header}"
|
||||
PRIVATE ${module_headers_private}
|
||||
QPA ${module_headers_qpa}
|
||||
RHI ${module_headers_rhi}
|
||||
)
|
||||
|
||||
qt_finalize_framework_headers_copy(${target})
|
||||
@ -910,6 +938,7 @@ endfunction()
|
||||
# * foo_versioned_inner_include_dir with the value "QtCore/6.2.0/QtCore"
|
||||
# * foo_private_include_dir with the value "QtCore/6.2.0/QtCore/private"
|
||||
# * foo_qpa_include_dir with the value "QtCore/6.2.0/QtCore/qpa"
|
||||
# * foo_rhi_include_dir with the value "QtCore/6.2.0/QtCore/rhi"
|
||||
# * foo_interface_name the interface name of the module stored in _qt_module_interface_name
|
||||
# property, e.g. Core.
|
||||
#
|
||||
@ -932,6 +961,9 @@ endfunction()
|
||||
# * foo_<build|install>_qpa_include_dir with
|
||||
# qtbase_build_dir/include/QtCore/6.2.0/QtCore/qpa for build interface and
|
||||
# include/QtCore/6.2.0/QtCore/qpa for install interface.
|
||||
# * foo_<build|install>_rhi_include_dir with
|
||||
# qtbase_build_dir/include/QtCore/6.2.0/QtCore/rhi for build interface and
|
||||
# include/QtCore/6.2.0/QtCore/rhi for install interface.
|
||||
# The following values are set by the function and might be useful in caller's scope:
|
||||
# * repo_install_interface_include_dir contains path to the top-level repository include directory,
|
||||
# e.g. qtbase_build_dir/include
|
||||
@ -966,6 +998,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_versioned_inner_include_dir}/private")
|
||||
set("${result}_qpa_include_dir"
|
||||
"${${result}_versioned_inner_include_dir}/qpa")
|
||||
set("${result}_rhi_include_dir"
|
||||
"${${result}_versioned_inner_include_dir}/rhi")
|
||||
|
||||
# Module build interface directories
|
||||
set(repo_build_interface_include_dir "${QT_BUILD_DIR}/include")
|
||||
@ -979,6 +1013,8 @@ the different base name for the module info variables.")
|
||||
"${repo_build_interface_include_dir}/${${result}_private_include_dir}")
|
||||
set("${result}_build_interface_qpa_include_dir"
|
||||
"${repo_build_interface_include_dir}/${${result}_qpa_include_dir}")
|
||||
set("${result}_build_interface_rhi_include_dir"
|
||||
"${repo_build_interface_include_dir}/${${result}_rhi_include_dir}")
|
||||
|
||||
# Module install interface directories
|
||||
set(repo_install_interface_include_dir "${INSTALL_INCLUDEDIR}")
|
||||
@ -992,6 +1028,8 @@ the different base name for the module info variables.")
|
||||
"${repo_install_interface_include_dir}/${${result}_private_include_dir}")
|
||||
set("${result}_install_interface_qpa_include_dir"
|
||||
"${repo_install_interface_include_dir}/${${result}_qpa_include_dir}")
|
||||
set("${result}_install_interface_rhi_include_dir"
|
||||
"${repo_install_interface_include_dir}/${${result}_rhi_include_dir}")
|
||||
|
||||
set("${result}" "${module}" PARENT_SCOPE)
|
||||
set("${result}_versioned" "${module_versioned}" PARENT_SCOPE)
|
||||
@ -1005,6 +1043,7 @@ the different base name for the module info variables.")
|
||||
"${${result}_versioned_inner_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_private_include_dir" "${${result}_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_qpa_include_dir" "${${result}_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_rhi_include_dir" "${${result}_rhi_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_interface_name" "${module_interface_name}" PARENT_SCOPE)
|
||||
|
||||
# Setting module build interface directories in parent scope
|
||||
@ -1019,6 +1058,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_build_interface_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_build_interface_qpa_include_dir"
|
||||
"${${result}_build_interface_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_build_interface_rhi_include_dir"
|
||||
"${${result}_build_interface_rhi_include_dir}" PARENT_SCOPE)
|
||||
|
||||
# Setting module install interface directories in parent scope
|
||||
set(repo_install_interface_include_dir "${repo_install_interface_include_dir}" PARENT_SCOPE)
|
||||
@ -1032,6 +1073,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_install_interface_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_install_interface_qpa_include_dir"
|
||||
"${${result}_install_interface_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_install_interface_rhi_include_dir"
|
||||
"${${result}_install_interface_rhi_include_dir}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_list_to_json_array out_var list_var)
|
||||
@ -1075,6 +1118,10 @@ function(qt_describe_module target)
|
||||
endif()
|
||||
|
||||
set(extra_build_information "")
|
||||
if(NOT QT_NAMESPACE STREQUAL "")
|
||||
string(APPEND extra_build_information "
|
||||
\"namespace\": \"${QT_NAMESPACE}\",")
|
||||
endif()
|
||||
if(ANDROID)
|
||||
string(APPEND extra_build_information "
|
||||
\"android\": {
|
||||
@ -1135,7 +1182,7 @@ endfunction()
|
||||
function(qt_internal_install_module_headers target)
|
||||
set(options)
|
||||
set(one_value_args)
|
||||
set(multi_value_args PUBLIC PRIVATE QPA)
|
||||
set(multi_value_args PUBLIC PRIVATE QPA RHI)
|
||||
cmake_parse_arguments(arg "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
qt_internal_module_info(module ${target})
|
||||
@ -1160,6 +1207,7 @@ function(qt_internal_install_module_headers target)
|
||||
PUBLIC ${arg_PUBLIC}
|
||||
PRIVATE ${arg_PRIVATE}
|
||||
QPA ${arg_QPA}
|
||||
RHI ${arg_RHI}
|
||||
)
|
||||
else()
|
||||
if(arg_PUBLIC)
|
||||
@ -1173,6 +1221,9 @@ function(qt_internal_install_module_headers target)
|
||||
if(arg_QPA)
|
||||
qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}")
|
||||
endif()
|
||||
if(arg_RHI)
|
||||
qt_install(FILES ${arg_RHI} DESTINATION "${module_install_interface_rhi_include_dir}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@ -1180,6 +1231,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
set(${out_var}_public "")
|
||||
set(${out_var}_private "")
|
||||
set(${out_var}_qpa "")
|
||||
set(${out_var}_rhi "")
|
||||
set(${out_var}_all "")
|
||||
|
||||
qt_internal_get_target_sources(sources ${target})
|
||||
@ -1200,6 +1252,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
get_target_property(public_filter ${target} _qt_module_public_headers_filter_regex)
|
||||
get_target_property(private_filter ${target} _qt_module_private_headers_filter_regex)
|
||||
get_target_property(qpa_filter ${target} _qt_module_qpa_headers_filter_regex)
|
||||
get_target_property(rhi_filter ${target} _qt_module_rhi_headers_filter_regex)
|
||||
|
||||
set(condition_independent_headers_warning "")
|
||||
foreach(file_path IN LISTS sources)
|
||||
@ -1251,6 +1304,8 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
list(APPEND ${out_var}_all "${file_path}")
|
||||
if(qpa_filter AND file_name MATCHES "${qpa_filter}")
|
||||
list(APPEND ${out_var}_qpa "${file_path}")
|
||||
elseif(rhi_filter AND file_name MATCHES "${rhi_filter}")
|
||||
list(APPEND ${out_var}_rhi "${file_path}")
|
||||
elseif(private_filter AND file_name MATCHES "${private_filter}")
|
||||
list(APPEND ${out_var}_private "${file_path}")
|
||||
elseif((NOT public_filter OR file_name MATCHES "${public_filter}")
|
||||
@ -1274,7 +1329,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
endif()
|
||||
|
||||
|
||||
set(header_types public private qpa)
|
||||
set(header_types public private qpa rhi)
|
||||
set(has_header_types_properties "")
|
||||
foreach(header_type IN LISTS header_types)
|
||||
get_target_property(current_propety_value ${target} _qt_module_has_${header_type}_headers)
|
||||
@ -1296,5 +1351,6 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
_qt_module_has_public_headers
|
||||
_qt_module_has_private_headers
|
||||
_qt_module_has_qpa_headers
|
||||
_qt_module_has_rhi_headers
|
||||
)
|
||||
endfunction()
|
||||
|
@ -148,6 +148,41 @@ while(NOT "${configure_args}" STREQUAL "")
|
||||
endif()
|
||||
endwhile()
|
||||
|
||||
# Read the specified manually generator value from CMake command line.
|
||||
# The '-cmake-generator' argument has higher priority than CMake command line.
|
||||
if(NOT generator)
|
||||
set(is_next_arg_generator_name FALSE)
|
||||
foreach(arg IN LISTS cmake_args)
|
||||
if(is_next_arg_generator_name)
|
||||
set(is_next_arg_generator_name FALSE)
|
||||
if(NOT arg MATCHES "^-.*")
|
||||
set(generator "${arg}")
|
||||
set(auto_detect_generator FALSE)
|
||||
endif()
|
||||
elseif(arg MATCHES "^-G(.*)")
|
||||
set(generator "${CMAKE_MATCH_1}")
|
||||
if(generator)
|
||||
set(auto_detect_generator FALSE)
|
||||
else()
|
||||
set(is_next_arg_generator_name TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Attempt to detect the generator type, either single or multi-config
|
||||
if("${generator}" STREQUAL "Xcode"
|
||||
OR "${generator}" STREQUAL "Ninja Multi-Config"
|
||||
OR "${generator}" MATCHES "^Visual Studio")
|
||||
set(multi_config ON)
|
||||
else()
|
||||
set(multi_config OFF)
|
||||
endif()
|
||||
|
||||
# Tell the build system we are configuring via the configure script so we can act on that.
|
||||
# The cache variable is unset at the end of configuration.
|
||||
push("-DQT_INTERNAL_CALLED_FROM_CONFIGURE:BOOL=TRUE")
|
||||
|
||||
if(FRESH_REQUESTED)
|
||||
push("-DQT_INTERNAL_FRESH_REQUESTED:BOOL=TRUE")
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
|
||||
@ -826,6 +861,7 @@ translate_boolean_input(precompile_header BUILD_WITH_PCH)
|
||||
translate_boolean_input(unity_build QT_UNITY_BUILD)
|
||||
translate_string_input(unity_build_batch_size QT_UNITY_BUILD_BATCH_SIZE)
|
||||
translate_boolean_input(ccache QT_USE_CCACHE)
|
||||
translate_boolean_input(vcpkg QT_USE_VCPKG)
|
||||
translate_boolean_input(shared BUILD_SHARED_LIBS)
|
||||
translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS)
|
||||
translate_string_input(qt_namespace QT_NAMESPACE)
|
||||
@ -875,6 +911,7 @@ endif()
|
||||
|
||||
drop_input(make)
|
||||
drop_input(nomake)
|
||||
translate_boolean_input(install-examples-sources QT_INSTALL_EXAMPLES_SOURCES)
|
||||
|
||||
check_qt_build_parts(nomake)
|
||||
check_qt_build_parts(make)
|
||||
@ -896,9 +933,9 @@ if(INPUT_force_debug_info)
|
||||
endif()
|
||||
|
||||
list(LENGTH build_configs nr_of_build_configs)
|
||||
if(nr_of_build_configs EQUAL 1)
|
||||
if(nr_of_build_configs EQUAL 1 AND NOT multi_config)
|
||||
push("-DCMAKE_BUILD_TYPE=${build_configs}")
|
||||
elseif(nr_of_build_configs GREATER 1)
|
||||
elseif(nr_of_build_configs GREATER 1 OR multi_config)
|
||||
set(multi_config ON)
|
||||
string(REPLACE ";" "[[;]]" escaped_build_configs "${build_configs}")
|
||||
# We must not use the push macro here to avoid variable expansion.
|
||||
@ -983,6 +1020,14 @@ endforeach()
|
||||
|
||||
push("${MODULE_ROOT}")
|
||||
|
||||
if(INPUT_sysroot)
|
||||
qtConfAddWarning("The -sysroot option is deprecated and no longer has any effect. "
|
||||
"It is recommended to use a toolchain file instead, i.e., "
|
||||
"-DCMAKE_TOOLCHAIN_FILE=<filename>. "
|
||||
"Alternatively, you may use -DCMAKE_SYSROOT option "
|
||||
"to pass the sysroot to CMake.\n")
|
||||
endif()
|
||||
|
||||
# Restore the escaped semicolons in arguments that are lists
|
||||
list(TRANSFORM cmake_args REPLACE "\\[\\[;\\]\\]" "\\\\;")
|
||||
|
||||
|
@ -27,7 +27,7 @@ function(_qt_internal_handle_ios_launch_screen target)
|
||||
if(NOT launch_screen AND NOT QT_NO_SET_DEFAULT_IOS_LAUNCH_SCREEN)
|
||||
set(is_default_launch_screen TRUE)
|
||||
set(launch_screen
|
||||
"${__qt_internal_cmake_ios_support_files_path}/LaunchScreen.storyboard")
|
||||
"${__qt_internal_cmake_apple_support_files_path}/LaunchScreen.storyboard")
|
||||
endif()
|
||||
|
||||
# Check that the launch screen exists.
|
||||
@ -554,15 +554,13 @@ function(_qt_internal_set_xcode_bitcode_enablement target)
|
||||
"NO")
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_generate_ios_info_plist target)
|
||||
function(_qt_internal_copy_info_plist target)
|
||||
# If the project already specifies a custom file, we don't override it.
|
||||
get_target_property(existing_plist "${target}" MACOSX_BUNDLE_INFO_PLIST)
|
||||
if(existing_plist)
|
||||
return()
|
||||
get_target_property(info_plist_in "${target}" MACOSX_BUNDLE_INFO_PLIST)
|
||||
if(NOT info_plist_in)
|
||||
set(info_plist_in "${__qt_internal_cmake_apple_support_files_path}/Info.plist.app.in")
|
||||
endif()
|
||||
|
||||
set(info_plist_in "${__qt_internal_cmake_ios_support_files_path}/Info.plist.app.in")
|
||||
|
||||
string(MAKE_C_IDENTIFIER "${target}" target_identifier)
|
||||
set(info_plist_out_dir
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/.qt/info_plist/${target_identifier}")
|
||||
@ -592,6 +590,62 @@ function(_qt_internal_generate_ios_info_plist target)
|
||||
set_target_properties("${target}" PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${info_plist_out}")
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_plist_buddy plist_file)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||
"" "OUTPUT_VARIABLE;ERROR_VARIABLE" "COMMANDS")
|
||||
foreach(command ${arg_COMMANDS})
|
||||
execute_process(COMMAND "/usr/libexec/PlistBuddy"
|
||||
-c "${command}" "${plist_file}"
|
||||
OUTPUT_VARIABLE plist_buddy_output
|
||||
ERROR_VARIABLE plist_buddy_error)
|
||||
string(STRIP "${plist_buddy_output}" plist_buddy_output)
|
||||
if(arg_OUTPUT_VARIABLE)
|
||||
list(APPEND ${arg_OUTPUT_VARIABLE} ${plist_buddy_output})
|
||||
set(${arg_OUTPUT_VARIABLE} ${${arg_OUTPUT_VARIABLE}} PARENT_SCOPE)
|
||||
endif()
|
||||
if(arg_ERROR_VARIABLE)
|
||||
list(APPEND ${arg_ERROR_VARIABLE} ${plist_buddy_error})
|
||||
set(${arg_ERROR_VARIABLE} ${${arg_ERROR_VARIABLE}} PARENT_SCOPE)
|
||||
endif()
|
||||
if(plist_buddy_error)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_set_apple_localizations target)
|
||||
if(QT_NO_SET_PLIST_LOCALIZATIONS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_target_property(supported_languages "${target}" _qt_apple_supported_languages)
|
||||
if("${supported_languages}" STREQUAL "supported_languages-NOTFOUND")
|
||||
return()
|
||||
endif()
|
||||
get_target_property(plist_file "${target}" MACOSX_BUNDLE_INFO_PLIST)
|
||||
if (NOT plist_file)
|
||||
return()
|
||||
endif()
|
||||
|
||||
_qt_internal_plist_buddy("${plist_file}"
|
||||
COMMANDS "print CFBundleLocalizations"
|
||||
OUTPUT_VARIABLE existing_localizations
|
||||
)
|
||||
if(existing_localizations)
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(TRANSFORM supported_languages PREPEND
|
||||
"Add CFBundleLocalizations: string ")
|
||||
|
||||
_qt_internal_plist_buddy("${plist_file}"
|
||||
COMMANDS
|
||||
"Add CFBundleLocalizations array"
|
||||
${supported_languages}
|
||||
"Delete CFBundleAllowMixedLocalizations"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_set_ios_simulator_arch target)
|
||||
if(CMAKE_XCODE_ATTRIBUTE_ARCHS
|
||||
OR QT_NO_SET_XCODE_ARCHS)
|
||||
@ -621,6 +675,9 @@ endfunction()
|
||||
function(_qt_internal_finalize_apple_app target)
|
||||
# Shared between macOS and iOS apps
|
||||
|
||||
_qt_internal_copy_info_plist("${target}")
|
||||
_qt_internal_set_apple_localizations("${target}")
|
||||
|
||||
# Only set the various properties if targeting the Xcode generator, otherwise the various
|
||||
# Xcode tokens are embedded as-is instead of being dynamically evaluated.
|
||||
# This affects things like the version number or application name as reported by Qt API.
|
||||
@ -637,12 +694,12 @@ function(_qt_internal_finalize_apple_app target)
|
||||
endfunction()
|
||||
|
||||
function(_qt_internal_finalize_ios_app target)
|
||||
_qt_internal_finalize_apple_app("${target}")
|
||||
# Must be called before we generate the Info.plist
|
||||
_qt_internal_handle_ios_launch_screen("${target}")
|
||||
|
||||
_qt_internal_finalize_apple_app("${target}")
|
||||
_qt_internal_set_xcode_targeted_device_family("${target}")
|
||||
_qt_internal_set_xcode_bitcode_enablement("${target}")
|
||||
_qt_internal_handle_ios_launch_screen("${target}")
|
||||
_qt_internal_generate_ios_info_plist("${target}")
|
||||
_qt_internal_set_ios_simulator_arch("${target}")
|
||||
endfunction()
|
||||
|
||||
|
@ -53,7 +53,7 @@ endfunction()
|
||||
|
||||
function(__qt_internal_get_emcc_recommended_version out_var)
|
||||
# This version of Qt needs this version of emscripten.
|
||||
set(QT_EMCC_RECOMMENDED_VERSION "3.1.25")
|
||||
set(QT_EMCC_RECOMMENDED_VERSION "3.1.37")
|
||||
set(${out_var} "${QT_EMCC_RECOMMENDED_VERSION}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
@ -81,12 +81,16 @@ function(__qt_internal_get_qt_build_emsdk_version out_var)
|
||||
endif()
|
||||
if(EXISTS "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h")
|
||||
file(READ "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h" ver)
|
||||
else()
|
||||
elseif(EXISTS "${WASM_BUILD_DIR}/include/QtCore/qconfig.h")
|
||||
file(READ "${WASM_BUILD_DIR}/include/QtCore/qconfig.h" ver)
|
||||
else()
|
||||
message("qconfig.h not found, unable to determine Qt build Emscripten version")
|
||||
endif()
|
||||
if (ver)
|
||||
string(REGEX MATCH "#define QT_EMCC_VERSION.\"[0-9]+\\.[0-9]+\\.[0-9]+\"" emOutput ${ver})
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" build_emcc_version "${emOutput}")
|
||||
set(${out_var} "${build_emcc_version}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_qt_test_emscripten_version)
|
||||
|
@ -37,8 +37,6 @@ function(qt_generate_qconfig_cpp in_file out_file)
|
||||
set(QT_SYS_CONF_DIR "${INSTALL_SYSCONFDIR}")
|
||||
|
||||
# Compute and set relocation prefixes.
|
||||
# TODO: Clean this up, there's a bunch of unrealistic assumptions here.
|
||||
# See qtConfOutput_preparePaths in qtbase/configure.pri.
|
||||
if(WIN32)
|
||||
set(lib_location_absolute_path
|
||||
"${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}")
|
||||
@ -213,6 +211,7 @@ function(qt_get_qmake_module_name result module)
|
||||
string(REGEX REPLACE "^Qt6" "" module "${module}")
|
||||
string(REGEX REPLACE "Private$" "_private" module "${module}")
|
||||
string(REGEX REPLACE "Qpa$" "_qpa_lib_private" module "${module}")
|
||||
string(REGEX REPLACE "Rhi$" "_rhi_lib_private" module "${module}")
|
||||
string(TOLOWER "${module}" module)
|
||||
set(${result} ${module} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -3,10 +3,14 @@
|
||||
|
||||
function(qt_internal_add_resource target resourceName)
|
||||
if(NOT TARGET "${target}")
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(NOT in_batch)
|
||||
message(FATAL_ERROR "Trying to add resource to a non-existing target \"${target}\".")
|
||||
message(FATAL_ERROR "${target} is not a target.")
|
||||
endif()
|
||||
qt_internal_is_skipped_test(skipped ${target})
|
||||
if(skipped)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(in_batch)
|
||||
_qt_internal_test_batch_target_name(target)
|
||||
endif()
|
||||
|
||||
|
@ -8,18 +8,14 @@
|
||||
set(QT_BUILDING_QT TRUE CACHE BOOL
|
||||
"When this is present and set to true, it signals that we are building Qt from source.")
|
||||
|
||||
# Pre-calculate the developer_build feature if it's set by the user via INPUT_developer_build
|
||||
if(NOT FEATURE_developer_build AND INPUT_developer_build
|
||||
AND NOT "${INPUT_developer_build}" STREQUAL "undefined")
|
||||
set(FEATURE_developer_build ON)
|
||||
endif()
|
||||
# Pre-calculate the developer_build feature if it's set by the user via the INPUT_developer_build
|
||||
# variable when using the configure script. When not using configure, don't take the INPUT variable
|
||||
# into account, so that users can toggle the feature directly in the cache or via IDE.
|
||||
qt_internal_compute_feature_value_from_possible_input(developer_build)
|
||||
|
||||
# Pre-calculate the no_prefix feature if it's set by configure via INPUT_no_prefix.
|
||||
# This needs to be done before qtbase/configure.cmake is processed.
|
||||
if(NOT FEATURE_no_prefix AND INPUT_no_prefix
|
||||
AND NOT "${INPUT_no_prefix}" STREQUAL "undefined")
|
||||
set(FEATURE_no_prefix ON)
|
||||
endif()
|
||||
qt_internal_compute_feature_value_from_possible_input(no_prefix)
|
||||
|
||||
set(_default_build_type "Release")
|
||||
if(FEATURE_developer_build)
|
||||
@ -49,7 +45,20 @@ unset(QT_EXTRA_BUILD_INTERNALS_VARS)
|
||||
# Save the global property in a variable to make it available to feature conditions.
|
||||
get_property(QT_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
# Try to detect if an explicit CMAKE_BUILD_TYPE was set by the user.
|
||||
# CMake sets CMAKE_BUILD_TYPE_INIT to Debug on most Windows platforms and doesn't set
|
||||
# anything for UNIXes. CMake assigns CMAKE_BUILD_TYPE_INIT to CMAKE_BUILD_TYPE during
|
||||
# first project() if CMAKE_BUILD_TYPE has no previous value.
|
||||
# We use extra information about the state of CMAKE_BUILD_TYPE before the first
|
||||
# project() call that's set in QtAutodetect.
|
||||
# STREQUAL check needs to have expanded variables because an undefined var is not equal
|
||||
# to an empty defined var.
|
||||
# See also qt_internal_force_set_cmake_build_type_conditionally which is used
|
||||
# to set the build type when building other repos or tests.
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}"
|
||||
AND NOT __qt_auto_detect_cmake_build_type_before_project_call
|
||||
AND NOT __qt_build_internals_cmake_build_type
|
||||
AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${_default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE
|
||||
@ -193,6 +202,8 @@ else()
|
||||
set(QT_INTERNAL_CONFIGURE_FROM_IDE FALSE CACHE INTERNAL "Configuring Qt Project from IDE")
|
||||
endif()
|
||||
|
||||
set(_qt_sync_headers_at_configure_time_default ${QT_INTERNAL_CONFIGURE_FROM_IDE})
|
||||
|
||||
if(FEATURE_developer_build)
|
||||
if(DEFINED QT_CMAKE_EXPORT_COMPILE_COMMANDS)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ${QT_CMAKE_EXPORT_COMPILE_COMMANDS})
|
||||
@ -213,11 +224,26 @@ if(FEATURE_developer_build)
|
||||
if (CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
set(__build_benchmarks OFF)
|
||||
endif()
|
||||
|
||||
# Sync headers during the initial configuration of a -developer-build to facilitate code
|
||||
# navigation for code editors that use an LSP-based code model.
|
||||
set(_qt_sync_headers_at_configure_time_default TRUE)
|
||||
else()
|
||||
set(_qt_build_tests_default OFF)
|
||||
set(__build_benchmarks OFF)
|
||||
endif()
|
||||
|
||||
# Sync Qt header files at configure time
|
||||
option(QT_SYNC_HEADERS_AT_CONFIGURE_TIME "Run syncqt at configure time already"
|
||||
${_qt_sync_headers_at_configure_time_default})
|
||||
unset(_qt_sync_headers_at_configure_time_default)
|
||||
|
||||
# In static Ninja Multi-Config builds the sync_headers dependencies(and other autogen dependencies
|
||||
# are not added to '_autogen/timestamp' targets. See QTBUG-113974.
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config" AND NOT QT_BUILD_SHARED_LIBS)
|
||||
set(QT_SYNC_HEADERS_AT_CONFIGURE_TIME TRUE CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
# Build Benchmarks
|
||||
option(QT_BUILD_BENCHMARKS "Build Qt Benchmarks" ${__build_benchmarks})
|
||||
if(QT_BUILD_BENCHMARKS)
|
||||
@ -255,10 +281,10 @@ endif()
|
||||
|
||||
option(QT_BUILD_TESTS_BATCHED "Link all tests into a single binary." ${_qt_batch_tests})
|
||||
|
||||
if(QT_BUILD_TESTS AND QT_BUILD_TESTS_BATCHED AND CMAKE_VERSION VERSION_LESS "3.18")
|
||||
if(QT_BUILD_TESTS AND QT_BUILD_TESTS_BATCHED AND CMAKE_VERSION VERSION_LESS "3.19")
|
||||
message(FATAL_ERROR
|
||||
"Test batching requires at least CMake 3.18, due to requiring per-source "
|
||||
"TARGET_DIRECTORY assignments.")
|
||||
"Test batching requires at least CMake 3.19, due to requiring per-source "
|
||||
"TARGET_DIRECTORY assignments and DEFER calls.")
|
||||
endif()
|
||||
|
||||
# QT_BUILD_TOOLS_WHEN_CROSSCOMPILING -> QT_FORCE_BUILD_TOOLS
|
||||
@ -285,6 +311,9 @@ enable_testing()
|
||||
|
||||
option(QT_BUILD_EXAMPLES "Build Qt examples" OFF)
|
||||
option(QT_BUILD_EXAMPLES_BY_DEFAULT "Should examples be built as part of the default 'all' target." ON)
|
||||
option(QT_INSTALL_EXAMPLES_SOURCES "Install example sources" OFF)
|
||||
option(QT_INSTALL_EXAMPLES_SOURCES_BY_DEFAULT
|
||||
"Install example sources as part of the default 'install' target" ON)
|
||||
|
||||
# FIXME: Support prefix builds as well QTBUG-96232
|
||||
if(QT_WILL_INSTALL)
|
||||
@ -354,31 +383,11 @@ endif()
|
||||
|
||||
option(QT_ALLOW_SYMLINK_IN_PATHS "Allows symlinks in paths." OFF)
|
||||
|
||||
# We need to clean up QT_FEATURE_*, but only once per configuration cycle
|
||||
get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
|
||||
if(NOT qt_feature_clean)
|
||||
message(STATUS "Check for feature set changes")
|
||||
set_property(GLOBAL PROPERTY _qt_feature_clean TRUE)
|
||||
foreach(feature ${QT_KNOWN_FEATURES})
|
||||
if(DEFINED "FEATURE_${feature}" AND
|
||||
NOT "${QT_FEATURE_${feature}}" STREQUAL "${FEATURE_${feature}}")
|
||||
message(" '${feature}' is changed from ${QT_FEATURE_${feature}} \
|
||||
to ${FEATURE_${feature}}")
|
||||
set(dirty_build TRUE)
|
||||
endif()
|
||||
unset("QT_FEATURE_${feature}" CACHE)
|
||||
endforeach()
|
||||
|
||||
set(QT_KNOWN_FEATURES "" CACHE INTERNAL "" FORCE)
|
||||
|
||||
if(dirty_build)
|
||||
set_property(GLOBAL PROPERTY _qt_dirty_build TRUE)
|
||||
message(WARNING "Re-configuring in existing build folder. \
|
||||
Some features will be re-evaluated automatically.")
|
||||
endif()
|
||||
endif()
|
||||
qt_internal_detect_dirty_features()
|
||||
|
||||
if(NOT QT_BUILD_EXAMPLES)
|
||||
# Disable deployment setup to avoid warnings about missing patchelf with CMake < 3.21.
|
||||
set(QT_SKIP_SETUP_DEPLOYMENT ON)
|
||||
endif()
|
||||
|
||||
option(QT_ALLOW_DOWNLOAD "Allows files to be downloaded when building Qt." OFF)
|
||||
|
@ -79,6 +79,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
endif()
|
||||
|
||||
get_target_property(qpa_filter_regex ${target} _qt_module_qpa_headers_filter_regex)
|
||||
get_target_property(rhi_filter_regex ${target} _qt_module_rhi_headers_filter_regex)
|
||||
get_target_property(private_filter_regex ${target} _qt_module_private_headers_filter_regex)
|
||||
|
||||
# We need to use the real paths since otherwise it may lead to the invalid work of the
|
||||
@ -96,6 +97,12 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
)
|
||||
endif()
|
||||
|
||||
if(rhi_filter_regex)
|
||||
set(rhi_filter_argument
|
||||
-rhiHeadersFilter "${rhi_filter_regex}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(common_syncqt_arguments
|
||||
-module "${module}"
|
||||
-sourceDir "${source_dir_real}"
|
||||
@ -104,8 +111,10 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
-includeDir "${module_build_interface_include_dir}"
|
||||
-privateIncludeDir "${module_build_interface_private_include_dir}"
|
||||
-qpaIncludeDir "${module_build_interface_qpa_include_dir}"
|
||||
-rhiIncludeDir "${module_build_interface_rhi_include_dir}"
|
||||
-generatedHeaders ${module_headers_generated}
|
||||
${qpa_filter_argument}
|
||||
${rhi_filter_argument}
|
||||
${public_namespaces_filter}
|
||||
${non_qt_module_argument}
|
||||
${internal_module_argument}
|
||||
@ -178,6 +187,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
${syncqt_args_rsp}
|
||||
${module_headers}
|
||||
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
|
||||
"$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_internal_sync_headers_deps>>"
|
||||
COMMENT
|
||||
"Running syncqt.cpp for module: ${module}"
|
||||
VERBATIM
|
||||
@ -194,6 +204,8 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
${syncqt_outputs}
|
||||
)
|
||||
add_dependencies(sync_headers ${target}_sync_headers)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES _qt_internal_sync_headers_target ${target}_sync_headers)
|
||||
|
||||
if(is_3rd_party_library)
|
||||
add_dependencies(thirdparty_sync_headers ${target}_sync_headers)
|
||||
@ -224,7 +236,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
endif()
|
||||
add_dependencies(sync_all_public_headers ${target}_sync_all_public_headers)
|
||||
|
||||
if(NOT is_3rd_party_library AND NOT is_framework)
|
||||
if(NOT is_3rd_party_library AND NOT is_framework AND module_headers)
|
||||
# Install all the CaMeL style aliases of header files from the staging directory in one rule
|
||||
qt_install(DIRECTORY "${syncqt_staging_dir}/"
|
||||
DESTINATION "${module_install_interface_include_dir}"
|
||||
@ -246,7 +258,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
# Run sync Qt first time at configure step to make all header files available for the code model
|
||||
# of IDEs.
|
||||
get_property(synced_modules GLOBAL PROPERTY _qt_synced_modules)
|
||||
if(NOT "${module}" IN_LIST synced_modules)
|
||||
if(NOT "${module}" IN_LIST synced_modules AND QT_SYNC_HEADERS_AT_CONFIGURE_TIME)
|
||||
message(STATUS "Running syncqt.cpp for module: ${module}")
|
||||
get_target_property(syncqt_location ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt LOCATION)
|
||||
execute_process(
|
||||
|
@ -20,10 +20,14 @@
|
||||
# Skip the specified source files by PRECOMPILE_HEADERS feature.
|
||||
function(qt_internal_extend_target target)
|
||||
if(NOT TARGET "${target}")
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(NOT in_batch)
|
||||
message(FATAL_ERROR "Trying to extend a non-existing target \"${target}\".")
|
||||
message(FATAL_ERROR "${target} is not a target.")
|
||||
endif()
|
||||
qt_internal_is_skipped_test(skipped ${target})
|
||||
if(skipped)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(in_batch)
|
||||
_qt_internal_test_batch_target_name(target)
|
||||
endif()
|
||||
|
||||
@ -109,6 +113,19 @@ function(qt_internal_extend_target target)
|
||||
if(NOT base_lib STREQUAL lib)
|
||||
qt_create_nolink_target("${base_lib}" ${target})
|
||||
endif()
|
||||
|
||||
# Collect _sync_headers targets from libraries that the target depends on. This is
|
||||
# heuristic way of building the dependency tree between the _sync_headers targets of
|
||||
# different Qt modules.
|
||||
if(TARGET "${lib}")
|
||||
get_target_property(is_private ${lib} _qt_is_private_module)
|
||||
if(is_private)
|
||||
get_target_property(lib ${lib} _qt_public_module_target_name)
|
||||
endif()
|
||||
set(out_genex "$<TARGET_PROPERTY:${lib},_qt_internal_sync_headers_target>")
|
||||
set_property(TARGET ${target}
|
||||
APPEND PROPERTY _qt_internal_sync_headers_deps "${out_genex}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Set-up the target
|
||||
@ -1018,6 +1035,24 @@ function(qt_internal_mark_as_internal_target target)
|
||||
set_target_properties(${target} PROPERTIES _qt_is_internal_target TRUE)
|
||||
endfunction()
|
||||
|
||||
# Marks a target with a property to skip it adding it as a dependency when building examples as
|
||||
# ExternalProjects.
|
||||
# Needed to create a ${repo}_src global target that examples can depend on in multi-config builds
|
||||
# due to a bug in AUTOUIC.
|
||||
#
|
||||
# See QTBUG-110369.
|
||||
function(qt_internal_skip_dependency_for_examples target)
|
||||
set_target_properties(${target} PROPERTIES _qt_skip_dependency_for_examples TRUE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_is_target_skipped_for_examples target out_var)
|
||||
get_property(is_skipped TARGET ${target} PROPERTY _qt_skip_dependency_for_examples)
|
||||
if(NOT is_skipped)
|
||||
set(is_skipped FALSE)
|
||||
endif()
|
||||
set(${out_var} "${is_skipped}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_link_internal_platform_for_object_library target)
|
||||
# We need to apply iOS bitcode flags to object libraries that are associated with internal
|
||||
# modules or plugins (e.g. object libraries added by qt_internal_add_resource,
|
||||
@ -1080,11 +1115,15 @@ endfunction()
|
||||
# The function disables one or multiple internal global definitions that are defined by the
|
||||
# qt_internal_add_global_definition function for a specific 'target'.
|
||||
function(qt_internal_undefine_global_definition target)
|
||||
if(NOT TARGET ${target})
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(NOT ${in_batch})
|
||||
if(NOT TARGET "${target}")
|
||||
message(FATAL_ERROR "${target} is not a target.")
|
||||
endif()
|
||||
qt_internal_is_skipped_test(skipped ${target})
|
||||
if(skipped)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_is_in_test_batch(in_batch ${target})
|
||||
if(in_batch)
|
||||
_qt_internal_test_batch_target_name(target)
|
||||
endif()
|
||||
|
||||
@ -1135,3 +1174,157 @@ function(qt_internal_get_target_sources_property out_var)
|
||||
endif()
|
||||
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# This function collects target properties that contain generator expressions and needs to be
|
||||
# exported. This function is needed since the CMake EXPORT_PROPERTIES property doesn't support
|
||||
# properties that contain generator expressions.
|
||||
# Usage: qt_internal_add_genex_properties_export(target properties...)
|
||||
function(qt_internal_add_genex_properties_export target)
|
||||
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
set(config_check_begin "")
|
||||
set(config_check_end "")
|
||||
if(is_multi_config)
|
||||
list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
|
||||
|
||||
# The genex snippet is evaluated to '$<NOT:$<BOOL:$<CONFIG>>>' in the generated cmake file.
|
||||
# The check is only applicable to the 'main' configuration. If user project doesn't use
|
||||
# multi-config generator, then the check supposed to return true and the value from the
|
||||
# 'main' configuration supposed to be used.
|
||||
string(JOIN "" check_if_config_empty
|
||||
"$<1:$><NOT:"
|
||||
"$<1:$><BOOL:"
|
||||
"$<1:$><CONFIG$<ANGLE-R>"
|
||||
"$<ANGLE-R>"
|
||||
"$<ANGLE-R>"
|
||||
)
|
||||
|
||||
# The genex snippet is evaluated to '$<CONFIG:'Qt config type'>' in the generated cmake
|
||||
# file and checks if the config that user uses matches the generated cmake file config.
|
||||
string(JOIN "" check_user_config
|
||||
"$<1:$><CONFIG:$<CONFIG>$<ANGLE-R>"
|
||||
)
|
||||
|
||||
# The genex snippet is evaluated to '$<$<OR:$<CONFIG:'Qt config type'>>:'Property content'>
|
||||
# for non-main Qt configs and to
|
||||
# $<$<OR:$<CONFIG:'Qt config type'>,$<NOT:$<BOOL:$<CONFIG>>>>:'Property content'> for the
|
||||
# main Qt config. This guard is required to choose the correct value of the property for the
|
||||
# user project according to the user config type.
|
||||
# All genexes need to be escaped properly to protect them from evaluation by the
|
||||
# file(GENERATE call in the qt_internal_export_genex_properties function.
|
||||
string(JOIN "" config_check_begin
|
||||
"$<1:$><"
|
||||
"$<1:$><OR:"
|
||||
"${check_user_config}"
|
||||
"$<$<CONFIG:${first_config_type}>:$<COMMA>${check_if_config_empty}>"
|
||||
"$<ANGLE-R>:"
|
||||
)
|
||||
set(config_check_end "$<ANGLE-R>")
|
||||
endif()
|
||||
set(target_name "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
|
||||
foreach(property IN LISTS ARGN)
|
||||
set(target_property_genex "$<TARGET_PROPERTY:${target_name},${property}>")
|
||||
# All properties that contain lists need to be protected of processing by JOIN genex calls.
|
||||
# So this escapes the semicolons for these list.
|
||||
set(target_property_list_escape
|
||||
"$<JOIN:$<GENEX_EVAL:${target_property_genex}>,\;>")
|
||||
set(property_value
|
||||
"\"${config_check_begin}${target_property_list_escape}${config_check_end}\"")
|
||||
set_property(TARGET ${target} APPEND PROPERTY _qt_export_genex_properties_content
|
||||
"${property} ${property_value}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# This function executes generator expressions for the properties that are added by the
|
||||
# qt_internal_add_genex_properties_export function and sets the calculated values to the
|
||||
# corresponding properties in the generated ExtraProperties.cmake file. The file then needs to be
|
||||
# included after the target creation routines in Config.cmake files. It also supports Multi-Config
|
||||
# builds.
|
||||
# Arguments:
|
||||
# EXPORT_NAME_PREFIX:
|
||||
# The portion of the file name before ExtraProperties.cmake
|
||||
# CONFIG_INSTALL_DIR:
|
||||
# Installation location for the file.
|
||||
# TARGETS:
|
||||
# The internal target names.
|
||||
function(qt_internal_export_genex_properties)
|
||||
set(option_args "")
|
||||
set(single_args
|
||||
EXPORT_NAME_PREFIX
|
||||
CONFIG_INSTALL_DIR
|
||||
)
|
||||
set(multi_args TARGETS)
|
||||
cmake_parse_arguments(arg "${option_args}" "${single_args}" "${multi_args}" ${ARGN})
|
||||
|
||||
if(NOT arg_EXPORT_NAME_PREFIX)
|
||||
message(FATAL_ERROR "qt_internal_export_genex_properties: "
|
||||
"Missing EXPORT_NAME_PREFIX argument.")
|
||||
endif()
|
||||
|
||||
if(NOT arg_TARGETS)
|
||||
message(FATAL_ERROR "qt_internal_export_genex_properties: "
|
||||
"TARGETS argument must contain at least one target")
|
||||
endif()
|
||||
|
||||
foreach(target IN LISTS arg_TARGETS)
|
||||
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
set(output_file_base_name "${arg_EXPORT_NAME_PREFIX}ExtraProperties")
|
||||
set(should_append "")
|
||||
set(config_suffix "")
|
||||
if(is_multi_config)
|
||||
list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
|
||||
set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
|
||||
# If the generated file belongs to the 'main' config type, we should set property
|
||||
# but not append it.
|
||||
string(JOIN "" should_append
|
||||
"$<$<NOT:$<CONFIG:${first_config_type}>>: APPEND>")
|
||||
endif()
|
||||
set(file_name "${output_file_base_name}${config_suffix}.cmake")
|
||||
|
||||
qt_path_join(output_file "${arg_CONFIG_INSTALL_DIR}"
|
||||
"${file_name}")
|
||||
|
||||
if(NOT IS_ABSOLUTE "${output_file}")
|
||||
qt_path_join(output_file "${QT_BUILD_DIR}" "${output_file}")
|
||||
endif()
|
||||
|
||||
set(target_name "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
|
||||
|
||||
string(JOIN "" set_property_begin "set_property(TARGET "
|
||||
"${target_name}${should_append} PROPERTY "
|
||||
)
|
||||
set(set_property_end ")")
|
||||
set(set_property_glue "${set_property_end}\n${set_property_begin}")
|
||||
set(property_list
|
||||
"$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_export_genex_properties_content>>")
|
||||
string(JOIN "" set_property_content "${set_property_begin}"
|
||||
"$<JOIN:${property_list},${set_property_glue}>"
|
||||
"${set_property_end}")
|
||||
|
||||
if(is_multi_config)
|
||||
set(config_includes "")
|
||||
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
|
||||
if(NOT first_config_type STREQUAL config)
|
||||
set(include_file_name
|
||||
"${output_file_base_name}-${config}.cmake")
|
||||
list(APPEND config_includes
|
||||
"include(\"\${CMAKE_CURRENT_LIST_DIR}/${include_file_name}\")")
|
||||
endif()
|
||||
endforeach()
|
||||
list(JOIN config_includes "\n" config_includes_string)
|
||||
set(config_includes_string
|
||||
"\n$<$<CONFIG:${first_config_type}>:${config_includes_string}>")
|
||||
endif()
|
||||
|
||||
file(GENERATE OUTPUT "${output_file}"
|
||||
CONTENT "$<$<BOOL:${property_list}>:${set_property_content}${config_includes_string}>"
|
||||
CONDITION "$<BOOL:${property_list}>"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
qt_install(FILES "$<$<BOOL:${property_list}>:${output_file}>"
|
||||
DESTINATION "${arg_CONFIG_INSTALL_DIR}"
|
||||
COMPONENT Devel
|
||||
)
|
||||
endfunction()
|
||||
|
@ -247,6 +247,7 @@ function(qt_internal_add_test_to_batch batch_name name)
|
||||
|
||||
# Lazy-init the test batch
|
||||
if(NOT TARGET ${target})
|
||||
qt_internal_library_deprecation_level(deprecation_define)
|
||||
qt_internal_add_executable(${target}
|
||||
${exceptions_text}
|
||||
${gui_text}
|
||||
@ -254,11 +255,16 @@ function(qt_internal_add_test_to_batch batch_name name)
|
||||
NO_INSTALL
|
||||
OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/build_dir"
|
||||
SOURCES "${QT_CMAKE_DIR}/qbatchedtestrunner.in.cpp"
|
||||
DEFINES QTEST_BATCH_TESTS
|
||||
DEFINES QTEST_BATCH_TESTS ${deprecation_define}
|
||||
INCLUDE_DIRECTORIES ${private_includes}
|
||||
LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::Core
|
||||
${QT_CMAKE_EXPORT_NAMESPACE}::Test
|
||||
${QT_CMAKE_EXPORT_NAMESPACE}::TestPrivate
|
||||
# Add GUI by default so that the plugins link properly with non-standalone
|
||||
# build of tests. Plugin handling is currently only done in
|
||||
# qt_internal_add_executable if Gui is present. This should be reevaluated with
|
||||
# multiple batches.
|
||||
${QT_CMAKE_EXPORT_NAMESPACE}::Gui
|
||||
)
|
||||
|
||||
set_property(TARGET ${target} PROPERTY _qt_has_exceptions ${arg_EXCEPTIONS})
|
||||
@ -309,17 +315,12 @@ function(qt_internal_add_test_to_batch batch_name name)
|
||||
list(PREPEND batched_test_list ${name})
|
||||
set_property(GLOBAL PROPERTY _qt_batched_test_list_property ${batched_test_list})
|
||||
|
||||
qt_internal_library_deprecation_level(deprecation_define)
|
||||
|
||||
# Merge the current test with the rest of the batch
|
||||
qt_internal_extend_target(${target}
|
||||
INCLUDE_DIRECTORIES ${arg_INCLUDE_DIRECTORIES}
|
||||
PUBLIC_LIBRARIES ${arg_PUBLIC_LIBRARIES}
|
||||
LIBRARIES ${arg_LIBRARIES}
|
||||
SOURCES ${arg_SOURCES}
|
||||
DEFINES
|
||||
${arg_DEFINES}
|
||||
${deprecation_define}
|
||||
COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
|
||||
COMPILE_FLAGS ${arg_COMPILE_FLAGS}
|
||||
LINK_OPTIONS ${arg_LINK_OPTIONS}
|
||||
@ -336,7 +337,7 @@ function(qt_internal_add_test_to_batch batch_name name)
|
||||
set_source_files_properties(${source}
|
||||
TARGET_DIRECTORY ${target}
|
||||
PROPERTIES COMPILE_DEFINITIONS
|
||||
"BATCHED_TEST_NAME=\"${name}\"")
|
||||
"BATCHED_TEST_NAME=\"${name}\";${arg_DEFINES}" )
|
||||
endforeach()
|
||||
set(${batch_name} ${target} PARENT_SCOPE)
|
||||
|
||||
@ -363,6 +364,34 @@ function(qt_internal_is_in_test_batch out name)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_is_skipped_test out name)
|
||||
get_target_property(is_skipped_test ${name} _qt_is_skipped_test)
|
||||
set(${out} ${is_skipped_test} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_set_skipped_test name)
|
||||
set_target_properties(${name} PROPERTIES _qt_is_skipped_test TRUE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_is_qtbase_test out)
|
||||
get_filename_component(dir "${CMAKE_CURRENT_BINARY_DIR}" ABSOLUTE)
|
||||
set(${out} FALSE PARENT_SCOPE)
|
||||
|
||||
while(TRUE)
|
||||
get_filename_component(filename "${dir}" NAME)
|
||||
if("${filename}" STREQUAL "qtbase")
|
||||
set(${out} TRUE PARENT_SCOPE)
|
||||
break()
|
||||
endif()
|
||||
|
||||
set(prev_dir "${dir}")
|
||||
get_filename_component(dir "${dir}" DIRECTORY)
|
||||
if("${dir}" STREQUAL "${prev_dir}")
|
||||
break()
|
||||
endif()
|
||||
endwhile()
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_get_batched_test_arguments out testname)
|
||||
if(WASM)
|
||||
# Add a query string to the runner document, so that the script therein
|
||||
@ -403,6 +432,32 @@ function(qt_internal_add_test name)
|
||||
_qt_internal_validate_all_args_are_parsed(arg)
|
||||
_qt_internal_validate_no_unity_build(arg)
|
||||
|
||||
set(batch_current_test FALSE)
|
||||
if(QT_BUILD_TESTS_BATCHED AND NOT arg_NO_BATCH AND NOT arg_QMLTEST AND NOT arg_MANUAL
|
||||
AND ("${QT_STANDALONE_TEST_PATH}" STREQUAL ""
|
||||
OR DEFINED ENV{QT_BATCH_STANDALONE_TESTS}))
|
||||
set(batch_current_test TRUE)
|
||||
endif()
|
||||
|
||||
if(batch_current_test OR (QT_BUILD_TESTS_BATCHED AND arg_QMLTEST))
|
||||
if (QT_SUPERBUILD OR DEFINED ENV{TESTED_MODULE_COIN})
|
||||
set(is_qtbase_test FALSE)
|
||||
if(QT_SUPERBUILD)
|
||||
qt_internal_is_qtbase_test(is_qtbase_test)
|
||||
elseif($ENV{TESTED_MODULE_COIN} STREQUAL "qtbase")
|
||||
set(is_qtbase_test TRUE)
|
||||
endif()
|
||||
if(NOT is_qtbase_test)
|
||||
file(GENERATE OUTPUT "dummy${name}.cpp" CONTENT "int main() { return 0; }")
|
||||
# Add a dummy target to tackle some potential problems
|
||||
qt_internal_add_executable(${name} SOURCES "dummy${name}.cpp")
|
||||
# Batched tests outside of qtbase are unsupported and skipped
|
||||
qt_internal_set_skipped_test(${name})
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT arg_OUTPUT_DIRECTORY)
|
||||
set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
@ -421,9 +476,8 @@ function(qt_internal_add_test name)
|
||||
"removed in a future Qt version. Use the LIBRARIES option instead.")
|
||||
endif()
|
||||
|
||||
if(NOT arg_NO_BATCH AND QT_BUILD_TESTS_BATCHED AND NOT arg_QMLTEST AND NOT arg_MANUAL)
|
||||
if(batch_current_test)
|
||||
qt_internal_add_test_to_batch(name ${name} ${ARGN})
|
||||
set(setting_up_batched_test TRUE)
|
||||
elseif(arg_SOURCES)
|
||||
if(QT_BUILD_TESTS_BATCHED AND arg_QMLTEST)
|
||||
message(WARNING "QML tests won't be batched - unsupported (yet)")
|
||||
@ -499,7 +553,6 @@ function(qt_internal_add_test name)
|
||||
qt_internal_extend_target("${name}" CONDITION ANDROID
|
||||
LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::Gui
|
||||
)
|
||||
set(setting_up_batched_test FALSE)
|
||||
set_target_properties(${name} PROPERTIES _qt_is_test_executable TRUE)
|
||||
set_target_properties(${name} PROPERTIES _qt_is_manual_test ${arg_MANUAL})
|
||||
endif()
|
||||
@ -550,7 +603,7 @@ function(qt_internal_add_test name)
|
||||
elseif(WASM)
|
||||
# The test script expects an html file. In case of batched tests, the
|
||||
# version specialized for running batches has to be supplied.
|
||||
if(setting_up_batched_test)
|
||||
if(batch_current_test)
|
||||
get_target_property(batch_output_dir ${name} RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(test_executable "${batch_output_dir}/${name}.html")
|
||||
else()
|
||||
@ -562,11 +615,16 @@ function(qt_internal_add_test name)
|
||||
list(APPEND extra_test_args "--silence_timeout=60")
|
||||
# TODO: Add functionality to specify browser
|
||||
list(APPEND extra_test_args "--browser=chrome")
|
||||
list(APPEND extra_test_args "--browser_args=\"--password-store=basic\"")
|
||||
list(APPEND extra_test_args "--kill_exit")
|
||||
|
||||
# We always want to enable asyncify for tests, as some of them use exec
|
||||
# Tests may require asyncify if they use exec(). Enable asyncify for
|
||||
# batched tests since this is the configuration used on the CI system.
|
||||
# Optimize for size (-Os), since asyncify tends to make the resulting
|
||||
# binary very large
|
||||
if(batch_current_test)
|
||||
target_link_options("${name}" PRIVATE "SHELL:-s ASYNCIFY" "-Os")
|
||||
endif()
|
||||
|
||||
# This tells cmake to run the tests with this script, since wasm files can't be
|
||||
# executed directly
|
||||
@ -588,9 +646,11 @@ function(qt_internal_add_test name)
|
||||
endif()
|
||||
|
||||
if(NOT arg_MANUAL)
|
||||
if(setting_up_batched_test)
|
||||
if(batch_current_test)
|
||||
qt_internal_get_batched_test_arguments(batched_test_args ${testname})
|
||||
list(PREPEND extra_test_args ${batched_test_args})
|
||||
elseif(WASM AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
list(PREPEND extra_test_args "qvisualoutput")
|
||||
endif()
|
||||
|
||||
qt_internal_collect_command_environment(test_env_path test_env_plugin_path)
|
||||
@ -661,11 +721,30 @@ function(qt_internal_add_test name)
|
||||
foreach(testdata IN LISTS arg_TESTDATA)
|
||||
list(APPEND builtin_files ${testdata})
|
||||
endforeach()
|
||||
foreach(file IN LISTS builtin_files)
|
||||
set_source_files_properties(${file}
|
||||
PROPERTIES QT_SKIP_QUICKCOMPILER TRUE
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(batch_current_test)
|
||||
set(blacklist_path "BLACKLIST")
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
|
||||
get_target_property(blacklist_files ${name} _qt_blacklist_files)
|
||||
if(NOT blacklist_files)
|
||||
set_target_properties(${name} PROPERTIES _qt_blacklist_files "")
|
||||
set(blacklist_files "")
|
||||
cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\" CALL \"_qt_internal_finalize_batch\" \"${name}\") ")
|
||||
endif()
|
||||
list(PREPEND blacklist_files "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
|
||||
set_target_properties(${name} PROPERTIES _qt_blacklist_files "${blacklist_files}")
|
||||
endif()
|
||||
else()
|
||||
set(blacklist_path "BLACKLIST")
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
|
||||
list(APPEND builtin_files ${blacklist_path})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(REMOVE_DUPLICATES builtin_files)
|
||||
|
||||
@ -762,7 +841,8 @@ for this function. Will be ignored")
|
||||
endif()
|
||||
|
||||
set(executable_name ${arg_NAME})
|
||||
if(QT_BUILD_TESTS_BATCHED)
|
||||
qt_internal_is_in_test_batch(is_in_batch ${executable_name})
|
||||
if(is_in_batch)
|
||||
_qt_internal_test_batch_target_name(executable_name)
|
||||
endif()
|
||||
add_test(NAME "${arg_NAME}" COMMAND "${CMAKE_COMMAND}" "-P" "${arg_OUTPUT_FILE}"
|
||||
@ -828,8 +908,8 @@ function(qt_internal_add_test_helper name)
|
||||
|
||||
set(extra_args_to_pass)
|
||||
if(NOT arg_OVERRIDE_OUTPUT_DIRECTORY)
|
||||
if(QT_BUILD_TESTS_BATCHED)
|
||||
_qt_internal_test_batch_target_name(test_batch_target_name)
|
||||
if(QT_BUILD_TESTS_BATCHED AND TARGET ${test_batch_target_name})
|
||||
get_target_property(
|
||||
test_batch_output_dir ${test_batch_target_name} RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(extra_args_to_pass OUTPUT_DIRECTORY "${test_batch_output_dir}")
|
||||
|
@ -8,7 +8,8 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
|
||||
target_link_options("${wasmTarget}" INTERFACE
|
||||
"SHELL:-s MAX_WEBGL_VERSION=2"
|
||||
"SHELL:-s FETCH=1"
|
||||
"SHELL:-s WASM_BIGINT=1")
|
||||
"SHELL:-s WASM_BIGINT=1"
|
||||
"SHELL:-s STACK_SIZE=5MB")
|
||||
|
||||
target_link_libraries("${wasmTarget}" INTERFACE embind)
|
||||
|
||||
@ -93,17 +94,25 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
|
||||
|
||||
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
|
||||
|
||||
# plugins are SIDE_MODULE
|
||||
target_compile_options("${wasmTarget}" INTERFACE
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:" -s SIDE_MODULE=1>)
|
||||
target_link_options("${wasmTarget}" INTERFACE
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:" -s SIDE_MODULE=1>)
|
||||
set(side_modules
|
||||
MODULE_LIBRARY SHARED_LIBRARY)
|
||||
set(enable_side_module_if_needed
|
||||
"$<$<IN_LIST:$<TARGET_PROPERTY:TYPE>,${side_modules}>:SHELL:-s SIDE_MODULE=1>")
|
||||
set(enable_main_module_if_needed
|
||||
"$<$<IN_LIST:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:SHELL:-s MAIN_MODULE=1>")
|
||||
set(set_shared_module_type_if_needed
|
||||
"${enable_side_module_if_needed}"
|
||||
"${enable_main_module_if_needed}"
|
||||
)
|
||||
|
||||
# shared libs are SIDE_MODULE
|
||||
target_compile_options("${wasmTarget}" INTERFACE
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:" -s SIDE_MODULE=1>)
|
||||
# Add Qt libdir to linker library paths
|
||||
set(qt_lib_location
|
||||
"${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBDIR}")
|
||||
target_link_options("${wasmTarget}" INTERFACE
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:" -s SIDE_MODULE=1>)
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:SHELL:" -L${qt_lib_location}/>)
|
||||
|
||||
target_compile_options("${wasmTarget}" INTERFACE "${set_shared_module_type_if_needed}")
|
||||
target_link_options("${wasmTarget}" INTERFACE "${set_shared_module_type_if_needed}")
|
||||
|
||||
else()
|
||||
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1")
|
||||
|
@ -39,6 +39,20 @@ function(qt_internal_create_wrapper_scripts)
|
||||
DESTINATION "${INSTALL_BINDIR}")
|
||||
endif()
|
||||
|
||||
if(generate_unix)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake-create.in"
|
||||
"${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create" @ONLY
|
||||
NEWLINE_STYLE LF)
|
||||
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create"
|
||||
DESTINATION "${INSTALL_BINDIR}")
|
||||
endif()
|
||||
if(generate_non_unix)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake-create.bat.in"
|
||||
"${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create.bat" @ONLY
|
||||
NEWLINE_STYLE CRLF)
|
||||
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create.bat"
|
||||
DESTINATION "${INSTALL_BINDIR}")
|
||||
endif()
|
||||
# Provide a private convenience wrapper with options which should not be propagated via the
|
||||
# public qt-cmake wrapper e.g. CMAKE_GENERATOR.
|
||||
# These options can not be set in a toolchain file, but only on the command line.
|
||||
|
@ -313,3 +313,16 @@ $ cd some/empty/directory
|
||||
$ ~/Qt/6.0.0/bin/qt-cmake-standalone-test ~/source/of/qtbase/test/auto/corelib/io/qprocess
|
||||
$ cmake --build .
|
||||
```
|
||||
|
||||
## qt-cmake-create
|
||||
|
||||
Generates a simple CMakeLists.txt based on source files in specified project directory.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
$ cd some/source/directory/
|
||||
$ qt-cmake-create
|
||||
$ qt-cmake -S . -B /build/directory
|
||||
$ cmake --build /build/directory
|
||||
```
|
||||
|
@ -17,7 +17,6 @@ The following table describes the mapping of configure options to CMake argument
|
||||
| -no-feature-foo | -DFEATURE_foo=OFF | |
|
||||
| -list-features | | At the moment: configure with cmake once, |
|
||||
| | | then use ccmake or cmake-gui to inspect the features. |
|
||||
| -list-libraries | | |
|
||||
| -opensource | n/a | |
|
||||
| -commercial | n/a | |
|
||||
| -confirm-license | n/a | |
|
||||
@ -60,6 +59,7 @@ The following table describes the mapping of configure options to CMake argument
|
||||
| -R <string> | -DQT_EXTRA_RPATHS=path1;path2 | |
|
||||
| -rpath | negative CMAKE_SKIP_BUILD_RPATH | |
|
||||
| | negative CMAKE_SKIP_INSTALL_RPATH | |
|
||||
| | negative CMAKE_MACOSX_RPATH | |
|
||||
| -reduce-exports | -DFEATURE_reduce_exports=ON | |
|
||||
| -reduce-relocations | -DFEATURE_reduce_relocations=ON | |
|
||||
| -plugin-manifests | | |
|
||||
@ -75,16 +75,9 @@ The following table describes the mapping of configure options to CMake argument
|
||||
| -ccache | -DQT_USE_CCACHE=ON | |
|
||||
| -unity-build | -DQT_UNITY_BUILD=ON | |
|
||||
| -unity-build-batch-size <int> | -DQT_UNITY_BUILD_BATCH_SIZE=<int> | |
|
||||
| -make-tool <tool> | n/a | |
|
||||
| -mp | n/a | |
|
||||
| -warnings-are-errors | -DWARNINGS_ARE_ERRORS=ON | |
|
||||
| -silent | n/a | |
|
||||
| -sysroot <dir> | -DCMAKE_SYSROOT=<dir> | Should be provided by a toolchain file that's |
|
||||
| | | passed via -DCMAKE_TOOLCHAIN_FILE=<filename> |
|
||||
| -no-gcc-sysroot | n/a | The corresponding CMake variables are CMAKE_SYSROOT_LINK |
|
||||
| | | and CMAKE_SYSROOT_COMPILE. |
|
||||
| | | They are usually set in a toolchain file. |
|
||||
| -no-pkg-config | -DFEATURE_pkg_config=OFF | |
|
||||
| -no-vcpkg | -DQT_USE_VCPKG=OFF | |
|
||||
| -D <string> | -DQT_EXTRA_DEFINES=<string1>;<string2> | |
|
||||
| -I <string> | -DQT_EXTRA_INCLUDEPATHS=<string1>;<string2> | |
|
||||
| -L <string> | -DQT_EXTRA_LIBDIRS=<string1>;<string2> | |
|
||||
@ -110,6 +103,7 @@ The following table describes the mapping of configure options to CMake argument
|
||||
| | | build them separately, after configuration. |
|
||||
| -nomake <part> | -DQT_BUILD_TESTS=OFF | A way to turn off tools explicitly is missing. |
|
||||
| | -DQT_BUILD_EXAMPLES=OFF | |
|
||||
| -install-examples-sources | -DQT_INSTALL_EXAMPLES_SOURCES=ON | |
|
||||
| -no-gui | -DFEATURE_gui=OFF | |
|
||||
| -no-widgets | -DFEATURE_widgets=OFF | |
|
||||
| -no-dbus | -DFEATURE_dbus=OFF | |
|
||||
|
@ -1,11 +1,13 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef @header_base_name_upper@_H
|
||||
#define @header_base_name_upper@_H
|
||||
|
||||
#include <QtCore/qcompilerdetection.h>
|
||||
#include <QtCore/qtconfigmacros.h> // Q_@module_define_infix@_EXPORT
|
||||
#include <QtCore/qtdeprecationmarkers.h> // QT_IF_DEPRECATED_SINCE
|
||||
|
||||
#if defined(QT_SHARED) || !defined(QT_STATIC)
|
||||
# if defined(QT_BUILD_@module_define_infix@_LIB)
|
||||
# define Q_@module_define_infix@_EXPORT Q_DECL_EXPORT
|
||||
|
@ -4,6 +4,8 @@
|
||||
#ifndef @header_base_name_upper@_P_H
|
||||
#define @header_base_name_upper@_P_H
|
||||
|
||||
// This file is autogenerated. Changes will be overwritten.
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
|
65
coin/axivion/ci_config_linux.json
Normal file
65
coin/axivion/ci_config_linux.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"Project": {
|
||||
"Git": {
|
||||
"_active": true,
|
||||
"sourceserver_gitdir": "/data/axivion/databases/$(env:TESTED_MODULE_COIN).git"
|
||||
},
|
||||
"BuildSystemIntegration": {
|
||||
"child_order": [
|
||||
"GCCSetup",
|
||||
"CMake",
|
||||
"LinkLibraries"
|
||||
]
|
||||
},
|
||||
"CMake": {
|
||||
"_active": true,
|
||||
"_copy_from": "CMakeIntegration",
|
||||
"build_environment": {},
|
||||
"build_options": "-j4",
|
||||
"generate_options": "--fresh",
|
||||
"generator": "Ninja"
|
||||
},
|
||||
"GCCSetup": {
|
||||
"_active": true,
|
||||
"_copy_from": "Command",
|
||||
"build_command": "gccsetup --cc gcc --cxx g++ --config ../../../axivion/"
|
||||
},
|
||||
"LinkLibraries": {
|
||||
"_active": true,
|
||||
"_copy_from": "AxivionLinker",
|
||||
"input_files": [
|
||||
"build/lib/lib*.so*.ir"
|
||||
],
|
||||
"ir": "build/$(env:TESTED_MODULE_COIN).ir",
|
||||
"plugin_files": [
|
||||
"build/plugins/*/lib*.so*.ir"
|
||||
]
|
||||
},
|
||||
"Project-GlobalOptions": {
|
||||
"ci_mode": {
|
||||
"clean_before": false
|
||||
},
|
||||
"directory": "../work/qt/$(env:TESTED_MODULE_COIN)",
|
||||
"ir": "build/$(env:TESTED_MODULE_COIN).ir",
|
||||
"name": "qt_$(env:TESTED_MODULE_COIN)_dev_$(env:TARGET_OS_COIN)"
|
||||
}
|
||||
},
|
||||
"Results": {
|
||||
"Dashboard": {
|
||||
"dashboard_url": "https://axivion-srv.ci.qt.io/axivion/"
|
||||
},
|
||||
"Database": {
|
||||
"ci_mode": {
|
||||
"directory": "/data/axivion/databases"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_Format": "1.0",
|
||||
"_Version": "trunk-9e0ef9c5818",
|
||||
"_VersionNum": [
|
||||
7,
|
||||
6,
|
||||
9999,
|
||||
11489
|
||||
]
|
||||
}
|
@ -76,9 +76,14 @@ instructions:
|
||||
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
||||
- type: SignPackage
|
||||
enable_if:
|
||||
condition: property
|
||||
condition: and
|
||||
conditions:
|
||||
- condition: property
|
||||
property: host.os
|
||||
equals_value: Windows
|
||||
- condition: property
|
||||
property: features
|
||||
contains_value: Packaging
|
||||
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
|
||||
maxTimeInSeconds: 1200
|
||||
maxTimeBetweenOutput: 1200
|
||||
|
@ -73,9 +73,14 @@ instructions:
|
||||
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
||||
- type: SignPackage
|
||||
enable_if:
|
||||
condition: property
|
||||
condition: and
|
||||
conditions:
|
||||
- condition: property
|
||||
property: host.os
|
||||
equals_value: Windows
|
||||
- condition: property
|
||||
property: features
|
||||
contains_value: Packaging
|
||||
directory: "{{.InstallRoot}}/{{.AgentWorkingDir}}"
|
||||
maxTimeInSeconds: 1200
|
||||
maxTimeBetweenOutput: 1200
|
||||
|
98
coin/instructions/coin_module_axivion_template_v2.yaml
Normal file
98
coin/instructions/coin_module_axivion_template_v2.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
analysis_instructions_axivion: &analysis_instructions_axivion
|
||||
type: Group
|
||||
instructions:
|
||||
- type: Group
|
||||
instructions:
|
||||
- type: EnvironmentVariable
|
||||
variableName: AXIVION_CHAINLOAD_TOOLCHAIN_FILE
|
||||
variableValue: "{{.AgentWorkingDir}}/install/lib/cmake/Qt6/qt.toolchain.cmake"
|
||||
- type: EnvironmentVariable
|
||||
variableName: CMAKE_PREFIX_PATH
|
||||
variableValue: "{{.AgentWorkingDir}}/install/lib/cmake"
|
||||
enable_if:
|
||||
condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qtbase"
|
||||
- type: Group
|
||||
instructions:
|
||||
- type: Rename
|
||||
sourcePath: "{{.SourceDir}}/coin/axivion/ci_config_{{.Env.TARGET_OS_COIN}}.json"
|
||||
targetPath: "{{.Env.HOME}}/axivion/ci_config.json"
|
||||
userMessageOnFailure: "Moving ci_config.json failed. Make sure you have included the file in coin/axivion/ -folder"
|
||||
- type: SetBuildDirectory
|
||||
directory: "{{.SourceDir}}"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.BuildDir}}"
|
||||
- type: ExecuteCommand
|
||||
command: ["../../../axivion/start_analysis.sh"]
|
||||
maxTimeInSeconds: 28800
|
||||
maxTimeBetweenOutput: 28800
|
||||
userMessageOnFailure: "Failed to run analysis"
|
||||
|
||||
build_environment_axivion: &build_environment_axivion
|
||||
type: Group
|
||||
instructions:
|
||||
- type: ExecuteCommand
|
||||
command: ["sudo", "mkdir", "-p","/data/axivion"]
|
||||
maxTimeInSeconds: 100
|
||||
maxTimeBetweenOutput: 100
|
||||
userMessageOnFailure: "Create mount point for results failed"
|
||||
- type: ExecuteCommand
|
||||
command: ["sudo", "mount", "-o", "rw", "10.212.0.93:/data/axivion", "/data/axivion"]
|
||||
maxTimeInSeconds: 100
|
||||
maxTimeBetweenOutput: 100
|
||||
userMessageOnFailure: "Mount failed"
|
||||
- type: ExecuteCommand
|
||||
command: ["rm","-rf","{{.SourceDir}}"]
|
||||
maxTimeInSeconds: 100
|
||||
maxTimeBetweenOutput: 100
|
||||
userMessageOnFailure: "Failed to remove source directory"
|
||||
- type: MakeDirectory
|
||||
directory: "{{.SourceDir}}"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.SourceDir}}"
|
||||
- type: ExecuteCommand
|
||||
command: ["git", "clone", "--jobs={{.NumCPU}}", "-n","--depth=50", "git://{{.Env.QT_COIN_GIT_DAEMON}}/qt-project/qt/{{.Env.TESTED_MODULE_COIN}}","."]
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to clone repository"
|
||||
- type: ExecuteCommand
|
||||
command: ["git", "fetch", "--recurse-submodules", "origin", "{{.Env.TESTED_MODULE_REVISION_COIN}}"]
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to fetch sources"
|
||||
- type: ExecuteCommand
|
||||
command: ["git", "checkout", "--force", "{{.Env.TESTED_MODULE_REVISION_COIN}}"]
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to checkout sources"
|
||||
- type: ExecuteCommand
|
||||
command: ["git", "submodule", "update", "--init", "--recursive"]
|
||||
maxTimeInSeconds: 1800
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to initialize git submodules"
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/cmake_module_build_instructions.yaml"
|
||||
enable_if:
|
||||
condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qtbase"
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/cmake_qtbase_build_instructions.yaml"
|
||||
enable_if:
|
||||
condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qtbase"
|
||||
|
||||
type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/prepare_building_env.yaml"
|
||||
- *build_environment_axivion
|
||||
- *analysis_instructions_axivion
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: Axivion
|
||||
|
@ -24,6 +24,33 @@ instructions:
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "TargetBuildOnly"
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "DebianPackaging"
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: Axivion
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/coin_module_axivion_template_v2.yaml"
|
||||
enable_if:
|
||||
condition: and
|
||||
conditions:
|
||||
- condition: property
|
||||
property: features
|
||||
contains_value: Axivion
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qtdoc"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qtquickeffectmaker"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qttranslations"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
not_equals_value: "qtwebengine"
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/cmake_cross_compilation_module_build_instructions.yaml"
|
||||
@ -48,3 +75,15 @@ instructions:
|
||||
- condition: property
|
||||
property: target.arch
|
||||
equals_value: ARM64
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "DebianPackaging"
|
||||
- type: Group
|
||||
instructions:
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/debian/debian_build_module.yaml"
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: "DebianPackaging"
|
||||
|
@ -17,6 +17,19 @@ instructions:
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "TargetBuildOnly"
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "DebianPackaging"
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: Axivion
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/coin_module_axivion_template_v2.yaml"
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: Axivion
|
||||
- type: Group
|
||||
instructions:
|
||||
- type: Group
|
||||
@ -53,3 +66,15 @@ instructions:
|
||||
- condition: property
|
||||
property: target.arch
|
||||
equals_value: ARM64
|
||||
- condition: property
|
||||
property: features
|
||||
not_contains_value: "DebianPackaging"
|
||||
- type: Group
|
||||
instructions:
|
||||
- type: Group
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/debian/debian_build_module.yaml"
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: "DebianPackaging"
|
||||
|
125
coin/instructions/debian/debian_build_module.yaml
Normal file
125
coin/instructions/debian/debian_build_module.yaml
Normal file
@ -0,0 +1,125 @@
|
||||
type: Group
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: DebianPackaging
|
||||
instructions:
|
||||
- !include "{{qt/qtbase}}/debian/prepare_debian_env.yaml"
|
||||
- type: EnvironmentVariable
|
||||
variableName: GIT_SSH_COMMAND
|
||||
variableValue: "ssh -o StrictHostKeyChecking=no"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.AgentWorkingDir}}"
|
||||
- type: MakeDirectory
|
||||
directory: output/debian_packages
|
||||
- type: MakeDirectory
|
||||
directory: debian_packages
|
||||
- type: ExecuteCommand
|
||||
command: "git clone git@git.qt.io:tqtc-debian/package_generator.git"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to clone package generator repo"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ExecuteCommand
|
||||
command: "git clone -b 6.6 git@git.qt.io:tqtc-debian/qt6-{{.Env.TESTED_MODULE_PLAIN_COIN}}.git"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to clone debian packaging repo"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ChangeDirectory
|
||||
directory: "qt6-{{.Env.TESTED_MODULE_PLAIN_COIN}}"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ExecuteCommand
|
||||
command: "git checkout {{.Env.DEBIAN_RULES_REF}}"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to checkout debian rules branch"
|
||||
disable_if:
|
||||
condition: or
|
||||
conditions:
|
||||
- condition: runtime
|
||||
env_var: DEBIAN_RULES_REF
|
||||
equals_value: null
|
||||
- condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.AgentWorkingDir}}"
|
||||
- type: ExecuteCommand
|
||||
command: "wget -q {{.CoinDownloadURL}}/{{.Env.MODULE_SOURCES_RELATIVE_STORAGE_PATH}}"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed get sources"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ExecuteCommand
|
||||
command: "mv sources_unix.tar.gz qt-{{.Env.QT_REPO_MODULE_VERSION}}-{{.Env.TESTED_MODULE_PLAIN_COIN}}-src_{{.Env.QT_REPO_MODULE_VERSION}}.orig.tar.gz"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed rename src pkg"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.AgentWorkingDir}}/qt6-{{.Env.TESTED_MODULE_PLAIN_COIN}}"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
|
||||
|
||||
# rc is required currently by the script
|
||||
- type: ExecuteCommand
|
||||
command: "../package_generator/generate_packaging.sh --qt-version {{.Env.QT_REPO_MODULE_VERSION}} --deb-rev 1 --release tqtc-focal"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed to generate pkg"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ChangeDirectory
|
||||
directory: "{{.AgentWorkingDir}}"
|
||||
- type: ExecuteCommand
|
||||
command: "dpkg-source -b qt6-{{.Env.TESTED_MODULE_PLAIN_COIN}}"
|
||||
maxTimeInSeconds: 900
|
||||
maxTimeBetweenOutput: 900
|
||||
userMessageOnFailure: "Failed dpkg-source"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: ExecuteCommand
|
||||
command: ["sbuild",
|
||||
"--build-dep-resolver=apt",
|
||||
"-sAd", "tqtc-focal",
|
||||
"-c", "{{.Env.COIN_SBUILD_CHROOT}}",
|
||||
"--build-dir", "output/debian_packages",
|
||||
"--extra-repository={{.Env.COIN_EXTRA_DEBIAN_REPO}}",
|
||||
"--extra-package={{.Env.COIN_EXTRA_DEBIAN_PACKAGES}}",
|
||||
"--extra-package={{.AgentWorkingDir}}/debian_packages/",
|
||||
"qt-{{.Env.QT_REPO_MODULE_VERSION}}-{{.Env.TESTED_MODULE_PLAIN_COIN}}-src_{{.Env.QT_REPO_MODULE_VERSION}}-1.dsc"]
|
||||
maxTimeInSeconds: 18000
|
||||
maxTimeBetweenOutput: 18000
|
||||
userMessageOnFailure: "Failed build debian packages"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: COIN_SKIP_DEBIAN
|
||||
contains_value: "MISSING_DEBIAN_INST"
|
||||
- type: UploadArtifact
|
||||
archiveDirectory: "{{.AgentWorkingDir}}/output"
|
||||
transferType: UploadModuleBuildArtifact
|
||||
maxTimeInSeconds: 1200
|
||||
maxTimeBetweenOutput: 1200
|
85
coin/instructions/debian/prepare_debian_env.yaml
Normal file
85
coin/instructions/debian/prepare_debian_env.yaml
Normal file
@ -0,0 +1,85 @@
|
||||
type: Group
|
||||
enable_if:
|
||||
condition: property
|
||||
property: features
|
||||
contains_value: DebianPackaging
|
||||
instructions:
|
||||
- type: EnvironmentVariable
|
||||
variableName: COIN_SBUILD_CHROOT
|
||||
variableValue: "stable-arm64-sbuild"
|
||||
enable_if:
|
||||
condition: and
|
||||
conditions:
|
||||
- condition: runtime
|
||||
env_var: COIN_SBUILD_CHROOT
|
||||
equals_value: null
|
||||
- condition: property
|
||||
property: target.arch
|
||||
equals_value: AARCH64
|
||||
- type: EnvironmentVariable
|
||||
variableName: COIN_SBUILD_CHROOT
|
||||
variableValue: "stable-amd64-sbuild"
|
||||
enable_if:
|
||||
condition: and
|
||||
conditions:
|
||||
- condition: runtime
|
||||
env_var: COIN_SBUILD_CHROOT
|
||||
equals_value: null
|
||||
- condition: property
|
||||
property: target.arch
|
||||
equals_value: X86_64
|
||||
- type: EnvironmentVariable
|
||||
variableName: COIN_SBUILD_DISTRO
|
||||
variableValue: "arm64-focal"
|
||||
enable_if:
|
||||
condition: property
|
||||
property: target.arch
|
||||
equals_value: AARCH64
|
||||
- type: EnvironmentVariable
|
||||
variableName: COIN_SBUILD_DISTRO
|
||||
variableValue: "amd64-focal"
|
||||
disable_if:
|
||||
condition: property
|
||||
property: target.arch
|
||||
equals_value: AARCH64
|
||||
|
||||
- type: EnvironmentVariable
|
||||
variableName: COIN_SKIP_DEBIAN
|
||||
variableValue: "MISSING_DEBIAN_INST"
|
||||
enable_if:
|
||||
condition: or
|
||||
conditions:
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qtactiveqt"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qtqa"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qtdoc"
|
||||
- condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qt5"
|
||||
# Set version info to environment
|
||||
- type: ParseEnvironmentVariableFromFile
|
||||
regex: "QT_REPO_MODULE_VERSION \"(?P<QT_REPO_MODULE_VERSION>.*)\""
|
||||
filename: "{{.SourceDir}}/.cmake.conf"
|
||||
maxTimeInSeconds: 300
|
||||
maxTimeBetweenOutput: 300
|
||||
userMessageOnFailure: "Failed to parse version information from .cmake.conf"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qt5"
|
||||
- type: ParseEnvironmentVariableFromFile
|
||||
regex: "QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT \"(?P<QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT>.*)\""
|
||||
filename: "{{.SourceDir}}/.cmake.conf"
|
||||
maxTimeInSeconds: 300
|
||||
maxTimeBetweenOutput: 300
|
||||
userMessageOnFailure: "Failed to parse status information from .cmake.conf"
|
||||
disable_if:
|
||||
condition: runtime
|
||||
env_var: TESTED_MODULE_COIN
|
||||
equals_value: "qt5"
|
||||
|
@ -4,9 +4,17 @@ accept_configuration:
|
||||
property: features
|
||||
not_contains_value: Disable
|
||||
|
||||
downstream_check:
|
||||
mode: build
|
||||
modules:
|
||||
../qtdeclarative:
|
||||
ref: dev
|
||||
configurations:
|
||||
- rhel-8.4
|
||||
|
||||
machine_type:
|
||||
Build:
|
||||
cores: 4
|
||||
cores: 8
|
||||
Test:
|
||||
cores: 4
|
||||
|
||||
|
@ -141,7 +141,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
|
||||
// Leading-Zero bit count, Intel Core 4th Generation ("Haswell")
|
||||
" lzcnt"
|
||||
#endif
|
||||
#ifdef __MMX__
|
||||
#if defined(__MMX__) && defined(__i386__)
|
||||
// Multimedia Extensions, Pentium MMX, AMD K6-2
|
||||
" mmx"
|
||||
#endif
|
||||
@ -198,11 +198,11 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
|
||||
// Shadow stack, Intel processor TBA
|
||||
" shstk"
|
||||
#endif
|
||||
#if defined(__SSE__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1) || defined(_M_X64)
|
||||
#if (defined(__SSE__) && defined(__i386__)) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1 && defined(_M_IX86))
|
||||
// Streaming SIMD Extensions, Intel Pentium III, AMD Athlon
|
||||
" sse"
|
||||
#endif
|
||||
#if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(_M_X64)
|
||||
#if (defined(__SSE2__) && defined(__i386__)) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2 && defined(_M_IX86))
|
||||
// SSE2, Intel Pentium-M, Intel Pentium 4, AMD Opteron and Athlon 64
|
||||
" sse2"
|
||||
#endif
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# special case skip regeneration
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(objcopytest LANGUAGES CXX)
|
||||
add_executable(objcopytest main.cpp)
|
||||
|
@ -64,10 +64,13 @@ Build options:
|
||||
-cmake-file-api ...... Let CMake store build metadata for loading the build
|
||||
into an IDE. [no; yes if -developer-build]
|
||||
-no-guess-compiler ... Do not guess the compiler from the target mkspec.
|
||||
-release ............. Build Qt with debugging turned off [yes]
|
||||
-debug ............... Build Qt with debugging turned on [no]
|
||||
-debug-and-release ... Build two versions of Qt, with and without
|
||||
debugging turned on [yes] (Apple and Windows only)
|
||||
-release ............. Build Qt with optimizations and without debug
|
||||
symbols [yes]
|
||||
Note that -developer-build implies -debug unless
|
||||
-release is also explicitly specified
|
||||
-debug ............... Build Qt without optimizations and with debug symbols
|
||||
[no]
|
||||
-debug-and-release ... Build two versions of Qt in one build tree [no]
|
||||
-optimize-debug ...... Enable debug-friendly optimizations in debug builds
|
||||
[auto] (Not supported with MSVC or Clang toolchains)
|
||||
-optimize-size ....... Optimize release builds for size instead of speed [no]
|
||||
@ -80,7 +83,8 @@ Build options:
|
||||
sections. [auto for static builds, otherwise no]
|
||||
-force-asserts ....... Enable Q_ASSERT even in release builds [no]
|
||||
-developer-build ..... Compile and link Qt for developing Qt itself
|
||||
(exports for auto-tests, extra checks, etc.) [no]
|
||||
(exports for auto-tests, extra checks, implies
|
||||
-no-prefix, etc.) [no]
|
||||
|
||||
-shared .............. Build shared Qt libraries [yes] (no for UIKit)
|
||||
-static .............. Build static Qt libraries [no] (yes for UIKit)
|
||||
@ -157,10 +161,10 @@ Build options:
|
||||
|
||||
Build environment:
|
||||
|
||||
-sysroot <dir> ....... Set <dir> as the target sysroot
|
||||
|
||||
-pkg-config .......... Use pkg-config [auto] (Unix only)
|
||||
|
||||
-vcpkg ............... Use vcpkg [yes]
|
||||
|
||||
-D <string> .......... Pass additional preprocessor define
|
||||
-I <string> .......... Pass additional include path
|
||||
-L <string> .......... Pass additional library path
|
||||
@ -198,6 +202,9 @@ Component selection:
|
||||
[default: libs and examples, also tools if not
|
||||
cross-building, also tests if -developer-build]
|
||||
-nomake <part> ....... Exclude <part> from the list of parts to be built.
|
||||
-install-examples-sources Installs examples source code into the Qt prefix
|
||||
Only possible when -make examples is also passed
|
||||
[no]
|
||||
-gui ................. Build the Qt GUI module and dependencies [yes]
|
||||
-widgets ............. Build the Qt Widgets module and dependencies [yes]
|
||||
-no-dbus ............. Do not build the Qt D-Bus module
|
||||
@ -289,6 +296,6 @@ Gui, printing, widget options:
|
||||
Database options:
|
||||
|
||||
-sql-<driver> ........ Enable SQL <driver> plugin. Supported drivers:
|
||||
db2 ibase mysql oci odbc psql sqlite
|
||||
db2 ibase mysql oci odbc psql sqlite mimer
|
||||
[all auto]
|
||||
-sqlite .............. Select used sqlite [system/qt]
|
||||
|
134
configure.cmake
134
configure.cmake
@ -109,7 +109,6 @@ SSL_free(SSL_new(0));
|
||||
}
|
||||
")
|
||||
|
||||
# special case end
|
||||
qt_find_package(WrapZSTD 1.3 PROVIDED_TARGETS WrapZSTD::WrapZSTD MODULE_NAME global QMAKE_LIB zstd)
|
||||
qt_find_package(WrapDBus1 1.2 PROVIDED_TARGETS dbus-1 MODULE_NAME global QMAKE_LIB dbus)
|
||||
qt_find_package(Libudev PROVIDED_TARGETS PkgConfig::Libudev MODULE_NAME global QMAKE_LIB libudev)
|
||||
@ -208,51 +207,6 @@ endif()
|
||||
# machineTuple
|
||||
qt_config_compile_test_machine_tuple("machine tuple")
|
||||
|
||||
# cxx14
|
||||
qt_config_compile_test(cxx14
|
||||
LABEL "C++14 support"
|
||||
CODE
|
||||
"#if __cplusplus > 201103L
|
||||
// Compiler claims to support C++14, trust it
|
||||
#else
|
||||
# error __cplusplus must be > 201103L (the value of C++11)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* BEGIN TEST: */
|
||||
/* END TEST: */
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
CXX_STANDARD 14
|
||||
)
|
||||
|
||||
# cxx17
|
||||
qt_config_compile_test(cxx17
|
||||
LABEL "C++17 support"
|
||||
CODE
|
||||
"#if __cplusplus > 201402L
|
||||
// Compiler claims to support C++17, trust it
|
||||
#else
|
||||
# error __cplusplus must be > 201402L (the value for C++14)
|
||||
#endif
|
||||
#include <map> // https://bugs.llvm.org//show_bug.cgi?id=33117
|
||||
#include <variant>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* BEGIN TEST: */
|
||||
std::variant<int> v(42);
|
||||
int i = std::get<int>(v);
|
||||
std::visit([](const auto &) { return 1; }, v);
|
||||
/* END TEST: */
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
CXX_STANDARD 17
|
||||
)
|
||||
|
||||
# cxx20
|
||||
qt_config_compile_test(cxx20
|
||||
LABEL "C++20 support"
|
||||
@ -485,7 +439,6 @@ qt_feature("android-style-assets" PRIVATE
|
||||
)
|
||||
qt_feature("shared" PUBLIC
|
||||
LABEL "Building shared libraries"
|
||||
AUTODETECT NOT UIKIT
|
||||
CONDITION BUILD_SHARED_LIBS
|
||||
)
|
||||
qt_feature_definition("shared" "QT_STATIC" NEGATE PREREQUISITE "!defined(QT_SHARED) && !defined(QT_STATIC)")
|
||||
@ -517,7 +470,6 @@ qt_feature("optimize_size"
|
||||
CONDITION NOT QT_FEATURE_debug OR QT_FEATURE_debug_and_release
|
||||
)
|
||||
qt_feature_config("optimize_size" QMAKE_PRIVATE_CONFIG)
|
||||
# special case begin
|
||||
qt_feature("optimize_full"
|
||||
LABEL "Fully optimize release builds (-O3)"
|
||||
AUTODETECT OFF
|
||||
@ -526,10 +478,10 @@ qt_feature_config("optimize_full" QMAKE_PRIVATE_CONFIG)
|
||||
qt_feature("msvc_obj_debug_info"
|
||||
LABEL "Embed debug info in object files (MSVC)"
|
||||
CONDITION MSVC
|
||||
ENABLE QT_USE_CCACHE
|
||||
AUTODETECT OFF
|
||||
)
|
||||
qt_feature_config("msvc_obj_debug_info" QMAKE_PRIVATE_CONFIG)
|
||||
# special case end
|
||||
qt_feature("pkg-config" PUBLIC
|
||||
LABEL "Using pkg-config"
|
||||
AUTODETECT NOT APPLE AND NOT WIN32 AND NOT ANDROID
|
||||
@ -667,29 +619,10 @@ qt_feature_config("plugin-manifests" QMAKE_PUBLIC_CONFIG
|
||||
NEGATE
|
||||
NAME "no_plugin_manifest"
|
||||
)
|
||||
qt_feature("c++11" PUBLIC
|
||||
LABEL "C++11"
|
||||
)
|
||||
qt_feature_config("c++11" QMAKE_PUBLIC_QT_CONFIG)
|
||||
qt_feature("c++14" PUBLIC
|
||||
LABEL "C++14"
|
||||
CONDITION QT_FEATURE_cxx11 AND TEST_cxx14
|
||||
)
|
||||
qt_feature_config("c++14" QMAKE_PUBLIC_QT_CONFIG)
|
||||
qt_feature("c++17" PUBLIC
|
||||
LABEL "C++17"
|
||||
CONDITION QT_FEATURE_cxx14 AND TEST_cxx17
|
||||
)
|
||||
qt_feature_config("c++17" QMAKE_PUBLIC_QT_CONFIG)
|
||||
qt_feature("c++1z" PUBLIC
|
||||
LABEL "C++17"
|
||||
CONDITION QT_FEATURE_cxx17
|
||||
)
|
||||
qt_feature_config("c++1z" QMAKE_PUBLIC_QT_CONFIG)
|
||||
qt_feature("c++20" PUBLIC
|
||||
LABEL "C++20"
|
||||
AUTODETECT OFF
|
||||
CONDITION QT_FEATURE_cxx17 AND TEST_cxx20
|
||||
CONDITION TEST_cxx20
|
||||
)
|
||||
qt_feature_config("c++20" QMAKE_PUBLIC_QT_CONFIG)
|
||||
qt_feature("c++2a" PUBLIC
|
||||
@ -707,17 +640,6 @@ qt_feature("c++2b" PUBLIC
|
||||
AUTODETECT FALSE
|
||||
CONDITION QT_FEATURE_cxx20 AND (CMAKE_VERSION VERSION_GREATER_EQUAL "3.20") AND TEST_cxx2b
|
||||
)
|
||||
qt_feature("c89"
|
||||
LABEL "C89"
|
||||
)
|
||||
qt_feature("c99" PUBLIC
|
||||
LABEL "C99"
|
||||
CONDITION c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES
|
||||
)
|
||||
qt_feature("c11" PUBLIC
|
||||
LABEL "C11"
|
||||
CONDITION QT_FEATURE_c99 AND c_std_11 IN_LIST CMAKE_C_COMPILE_FEATURES
|
||||
)
|
||||
qt_feature("precompile_header"
|
||||
LABEL "Using precompiled headers"
|
||||
CONDITION BUILD_WITH_PCH AND TEST_precompile_header
|
||||
@ -920,7 +842,9 @@ qt_feature_definition("mips_dspr2" "QT_COMPILER_SUPPORTS_MIPS_DSPR2" VALUE "1")
|
||||
qt_feature_config("mips_dspr2" QMAKE_PRIVATE_CONFIG)
|
||||
qt_feature("neon" PRIVATE
|
||||
LABEL "NEON"
|
||||
CONDITION ( ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_neon ) OR QT_FORCE_FEATURE_neon # special case
|
||||
CONDITION ( ( ( TEST_architecture_arch STREQUAL arm ) OR
|
||||
( TEST_architecture_arch STREQUAL arm64 ) ) AND
|
||||
TEST_arch_${TEST_architecture_arch}_subarch_neon ) OR QT_FORCE_FEATURE_neon
|
||||
)
|
||||
qt_feature_definition("neon" "QT_COMPILER_SUPPORTS_NEON" VALUE "1")
|
||||
qt_feature_config("neon" QMAKE_PRIVATE_CONFIG)
|
||||
@ -986,7 +910,6 @@ qt_feature("stdlib-libcpp" PRIVATE
|
||||
AUTODETECT OFF
|
||||
CONDITION LINUX AND NOT ANDROID
|
||||
)
|
||||
# special case begin
|
||||
# Check whether CMake was built with zstd support.
|
||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/21552
|
||||
if(NOT DEFINED CACHE{QT_CMAKE_ZSTD_SUPPORT})
|
||||
@ -1003,7 +926,6 @@ if(NOT DEFINED CACHE{QT_CMAKE_ZSTD_SUPPORT})
|
||||
unset(qt_check_zstd_exit_code)
|
||||
endif()
|
||||
endif()
|
||||
# special case end
|
||||
qt_feature("thread" PUBLIC
|
||||
SECTION "Kernel"
|
||||
LABEL "Thread support"
|
||||
@ -1143,22 +1065,10 @@ qt_configure_add_summary_entry(
|
||||
ARGS "optimize_size"
|
||||
CONDITION NOT QT_FEATURE_debug OR QT_FEATURE_debug_and_release
|
||||
)
|
||||
# special case begin
|
||||
qt_configure_add_summary_entry(
|
||||
ARGS "optimize_full"
|
||||
)
|
||||
# special case end
|
||||
qt_configure_add_summary_entry(ARGS "shared")
|
||||
qt_configure_add_summary_entry(
|
||||
TYPE "firstAvailableFeature"
|
||||
ARGS "c11 c99 c89"
|
||||
MESSAGE "Using C standard"
|
||||
)
|
||||
qt_configure_add_summary_entry(
|
||||
TYPE "firstAvailableFeature"
|
||||
ARGS "c++2b c++20 c++17 c++14 c++11"
|
||||
MESSAGE "Using C++ standard"
|
||||
)
|
||||
qt_configure_add_summary_entry(
|
||||
ARGS "ccache"
|
||||
CONDITION UNIX
|
||||
@ -1232,6 +1142,13 @@ qt_configure_add_summary_entry(ARGS "sanitize_fuzzer_no_link")
|
||||
qt_configure_add_summary_entry(ARGS "sanitize_undefined")
|
||||
qt_configure_end_summary_section() # end of "Sanitizers" section
|
||||
qt_configure_add_summary_build_parts("Build parts")
|
||||
if(QT_INSTALL_EXAMPLES_SOURCES)
|
||||
set(_examples_sources_entry_message "yes")
|
||||
else()
|
||||
set(_examples_sources_entry_message "no")
|
||||
endif()
|
||||
qt_configure_add_summary_entry(ARGS "Install examples sources" TYPE "message"
|
||||
MESSAGE "${_examples_sources_entry_message}")
|
||||
qt_configure_add_summary_entry(
|
||||
ARGS "appstore-compliant"
|
||||
CONDITION APPLE OR ANDROID OR WIN32
|
||||
@ -1251,6 +1168,14 @@ qt_configure_add_summary_entry(ARGS "xml")
|
||||
qt_configure_end_summary_section() # end of "Qt modules and options" section
|
||||
qt_configure_add_summary_section(NAME "Support enabled for")
|
||||
qt_configure_add_summary_entry(ARGS "pkg-config")
|
||||
|
||||
if(QT_USE_VCPKG AND (DEFINED ENV{VCPKG_ROOT} OR VCPKG_TARGET_TRIPLET))
|
||||
set(_vcpkg_entry_message "yes")
|
||||
else()
|
||||
set(_vcpkg_entry_message "no")
|
||||
endif()
|
||||
qt_configure_add_summary_entry(ARGS "Using vcpkg" TYPE "message" MESSAGE "${_vcpkg_entry_message}")
|
||||
|
||||
qt_configure_add_summary_entry(ARGS "libudev")
|
||||
qt_configure_add_summary_entry(ARGS "openssl")
|
||||
qt_configure_add_summary_entry(ARGS "openssl-linked")
|
||||
@ -1265,13 +1190,6 @@ qt_configure_add_report_entry(
|
||||
MESSAGE "Using static linking will disable the use of dynamically loaded plugins. Make sure to import all needed static plugins, or compile needed modules into the library."
|
||||
CONDITION NOT QT_FEATURE_shared
|
||||
)
|
||||
# special case begin
|
||||
# qt_configure_add_report_entry(
|
||||
# TYPE ERROR
|
||||
# MESSAGE "Debug build without Release build is not currently supported on ios see QTBUG-71990. Use -debug-and-release."
|
||||
# CONDITION IOS AND QT_FEATURE_debug AND NOT QT_FEATURE_debug_and_release
|
||||
# )
|
||||
# special case end
|
||||
qt_configure_add_report_entry(
|
||||
TYPE WARNING
|
||||
MESSAGE "-debug-and-release is only supported on Darwin and Windows platforms. Qt can be built in release mode with separate debug information, so -debug-and-release is no longer necessary."
|
||||
@ -1301,6 +1219,16 @@ if (TEST_architecture_arch STREQUAL x86_64 OR TEST_architecture_arch STREQUAL i3
|
||||
MESSAGE [=[
|
||||
All x86 intrinsics and SIMD support were disabled. If this was in error, check
|
||||
the result of the build in config.tests/x86intrin and report at https://bugreports.qt.io.
|
||||
]=]
|
||||
)
|
||||
elseif (MSVC AND CLANG)
|
||||
# Warn only
|
||||
qt_configure_add_report_entry(
|
||||
TYPE WARNING
|
||||
CONDITION (NOT QT_FEATURE_x86intrin)
|
||||
MESSAGE [=[
|
||||
x86 intrinsics support is disabled for clang-cl build. This might be necessary due to
|
||||
https://github.com/llvm/llvm-project/issues/53520
|
||||
]=]
|
||||
)
|
||||
else()
|
||||
@ -1317,7 +1245,6 @@ ${TEST_x86intrin_OUTPUT}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
# special case begin
|
||||
qt_configure_add_report_entry(
|
||||
TYPE ERROR
|
||||
MESSAGE "Setting a library infix is not supported for framework builds."
|
||||
@ -1336,7 +1263,6 @@ qt_configure_add_report_entry(
|
||||
if(WASM)
|
||||
qt_extra_definition("QT_EMCC_VERSION" "\"${EMCC_VERSION}\"" PUBLIC)
|
||||
endif()
|
||||
# special case end
|
||||
qt_extra_definition("QT_VERSION_STR" "\"${PROJECT_VERSION}\"" PUBLIC)
|
||||
qt_extra_definition("QT_VERSION_MAJOR" ${PROJECT_VERSION_MAJOR} PUBLIC)
|
||||
qt_extra_definition("QT_VERSION_MINOR" ${PROJECT_VERSION_MINOR} PUBLIC)
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# special case skip regeneration
|
||||
#
|
||||
# Copy/Install doc configuration files to the build/install directory
|
||||
#
|
||||
|
@ -125,6 +125,7 @@ macro.cmakepropertywebassemblyonly = "\\note This property is used only if targe
|
||||
macro.cmakepropertyiosonly = "\\note This property is used only if targeting iOS."
|
||||
macro.cmakevariableiosonly = "\\note This variable is used only if targeting iOS."
|
||||
|
||||
macro.qtpolicydeprecatedbehavior = "\\note The \\c{OLD} behavior of a policy is deprecated, and may be removed in the future."
|
||||
#Appends the tech preview link to the brief sentence and adds to tech_preview
|
||||
#group.
|
||||
#Must be placed directly under a \brief command
|
||||
|
@ -35,7 +35,7 @@ manifestmeta.highlighted.attributes = isHighlighted:true
|
||||
manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
|
||||
"Qt3D/Qt 3D: Planets QML Example" \
|
||||
"Qt3D/Qt 3D: Simple Custom Material QML Example" \
|
||||
"QtAndroidExtras/Qt Notifier" \
|
||||
"QtCore/Qt Android Notifier" \
|
||||
"QtBluetooth/Bluetooth Low Energy Scanner Example" \
|
||||
"QtBluetooth/Bluetooth Scanner Example" \
|
||||
"QtBluetooth/QML Bluetooth Scanner Example" \
|
||||
@ -51,15 +51,12 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
|
||||
"QtLocation/Places Map (QML)" \
|
||||
"QtLocation/Plane Spotter (QML)" \
|
||||
"QtMultimedia/AudioEngine Example" \
|
||||
"QtMultimedia/Camera Example" \
|
||||
"QtMultimedia/QML Camera Example" \
|
||||
"QtMultimedia/QML Video Example" \
|
||||
"QtMultimedia/QML Video Shader Effects Example" \
|
||||
"QtNFC/Annotated URL Example" \
|
||||
"QtNFC/QML Poster Example" \
|
||||
"QtOpenGL/2D Painting Example" \
|
||||
"QtOpenGL/Hello GLES3 Example" \
|
||||
"QtOpenGL/Textures Example" \
|
||||
"QtPositioning/SatelliteInfo (C++/QML)" \
|
||||
"QtPositioning/Weather Info (C++/QML)" \
|
||||
"QtPurchasing/Qt Purchasing Examples - QtHangman" \
|
||||
@ -94,8 +91,6 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
|
||||
"QtQuickControls/Qt Quick Controls - Flat Style" \
|
||||
"QtQuickControls/Qt Quick Controls - Gallery" \
|
||||
"QtQuickControls/Qt Quick Controls - Imagine Style Example: Automotive" \
|
||||
"QtQuickControls/Qt Quick Controls - Side Panel" \
|
||||
"QtQuickControls/Qt Quick Controls - Swipe to Remove" \
|
||||
"QtQuickControls/Qt Quick Controls - Text Editor" \
|
||||
"QtQuickControls/Qt Quick Controls - Wearable Demo" \
|
||||
"QtQuickDialogs/*" \
|
||||
@ -107,47 +102,7 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
|
||||
"QtSQL/Master Detail Example" \
|
||||
"QtSVG/Text Object Example" \
|
||||
"QtUiTools/Text Finder Example" \
|
||||
"QtWebView/Qt WebView Examples - Minibrowser" \
|
||||
"QtWidgets/Address Book Example" \
|
||||
"QtWidgets/Affine Transformations" \
|
||||
"QtWidgets/Analog Clock Example" \
|
||||
"QtWidgets/Animated Tiles Example" \
|
||||
"QtWidgets/Application Chooser Example" \
|
||||
"QtWidgets/Basic Layouts Example" \
|
||||
"QtWidgets/Border Layout Example" \
|
||||
"QtWidgets/Code Editor Example" \
|
||||
"QtWidgets/Colliding Mice Example" \
|
||||
"QtWidgets/Concentric Circles Example" \
|
||||
"QtWidgets/Digital Clock Example" \
|
||||
"QtWidgets/Dynamic Layouts Example" \
|
||||
"QtWidgets/Easing Curves Example" \
|
||||
"QtWidgets/Editable Tree Model Example" \
|
||||
"QtWidgets/Elided Label Example" \
|
||||
"QtWidgets/Fade Message Effect Example" \
|
||||
"QtWidgets/Flow Layout Example" \
|
||||
"QtWidgets/Font Sampler Example" \
|
||||
"QtWidgets/Frozen Column Example" \
|
||||
"QtWidgets/Gradients" \
|
||||
"QtWidgets/Group Box Example" \
|
||||
"QtWidgets/Image Composition Example" \
|
||||
"QtWidgets/Line Edits Example" \
|
||||
"QtWidgets/Mouse Button Tester" \
|
||||
"QtWidgets/Move Blocks Example" \
|
||||
"QtWidgets/Painter Paths Example" \
|
||||
"QtWidgets/Painter Paths Example" \
|
||||
"QtWidgets/Path Stroking" \
|
||||
"QtWidgets/Pixelator Example" \
|
||||
"QtWidgets/Recent Files Example" \
|
||||
"QtWidgets/SDI Example" \
|
||||
"QtWidgets/Scribble Example" \
|
||||
"QtWidgets/Simple Tree Model Example" \
|
||||
"QtWidgets/Sliders Example" \
|
||||
"QtWidgets/Spreadsheet" \
|
||||
"QtWidgets/Touch Dials Example" \
|
||||
"QtWidgets/Transformations Example" \
|
||||
"QtWidgets/Undo Framework" \
|
||||
"QtWidgets/Vector Deformation" \
|
||||
"QtWidgets/Wiggly Example"
|
||||
"QtWebView/Qt WebView Examples - Minibrowser"
|
||||
|
||||
manifestmeta.android.tags = android
|
||||
|
||||
|
@ -1,2 +1,25 @@
|
||||
qt_internal_add_example(bindablesubscription)
|
||||
qt_internal_add_example(subscription)
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(bindableproperties LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/bindableproperties")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
add_subdirectory(shared)
|
||||
add_subdirectory(subscription)
|
||||
add_subdirectory(bindablesubscription)
|
||||
|
||||
install(TARGETS subscription bindablesubscription
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
||||
|
@ -1,50 +1,15 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(bindablesubscription LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/bindableproperties/bindablesubscription")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(bindablesubscription
|
||||
../shared/subscriptionwindow.cpp ../shared/subscriptionwindow.h ../shared/subscriptionwindow.ui
|
||||
main.cpp
|
||||
bindablesubscription.cpp bindablesubscription.h
|
||||
bindableuser.cpp bindableuser.h
|
||||
bindablesubscription.cpp
|
||||
bindablesubscription.h
|
||||
bindableuser.cpp
|
||||
bindableuser.h
|
||||
)
|
||||
|
||||
target_link_libraries(bindablesubscription PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
bindableproperties_shared
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(countries_resource_files
|
||||
"../shared/finland.png"
|
||||
"../shared/germany.png"
|
||||
"../shared/norway.png"
|
||||
)
|
||||
|
||||
qt_add_resources(bindablesubscription "countries"
|
||||
PREFIX
|
||||
"/"
|
||||
BASE
|
||||
"../shared"
|
||||
FILES
|
||||
${countries_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS bindablesubscription
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
||||
|
23
examples/corelib/bindableproperties/shared/CMakeLists.txt
Normal file
23
examples/corelib/bindableproperties/shared/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_library(bindableproperties_shared STATIC
|
||||
subscriptionwindow.cpp
|
||||
subscriptionwindow.h
|
||||
subscriptionwindow.ui
|
||||
)
|
||||
|
||||
target_link_libraries(bindableproperties_shared PUBLIC
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
qt_add_resources(bindableproperties_shared "countries"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
"finland.png"
|
||||
"germany.png"
|
||||
"norway.png"
|
||||
)
|
@ -1,50 +1,12 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(subscription LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/bindableproperties/subscription")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(subscription
|
||||
../shared/subscriptionwindow.cpp ../shared/subscriptionwindow.h ../shared/subscriptionwindow.ui
|
||||
main.cpp
|
||||
subscription.cpp subscription.h
|
||||
user.cpp user.h
|
||||
)
|
||||
|
||||
target_link_libraries(subscription PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(countries_resource_files
|
||||
"../shared/finland.png"
|
||||
"../shared/germany.png"
|
||||
"../shared/norway.png"
|
||||
)
|
||||
|
||||
qt_add_resources(subscription "countries"
|
||||
PREFIX
|
||||
"/"
|
||||
BASE
|
||||
"../shared"
|
||||
FILES
|
||||
${countries_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS subscription
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
bindableproperties_shared
|
||||
)
|
||||
|
@ -23,6 +23,8 @@ qt_add_executable(androidnotifier
|
||||
main.cpp
|
||||
notificationclient.cpp
|
||||
notificationclient.h
|
||||
android/src/org/qtproject/example/androidnotifier/NotificationClient.java
|
||||
android/AndroidManifest.xml
|
||||
)
|
||||
|
||||
target_link_libraries(androidnotifier PRIVATE
|
||||
|
@ -6,6 +6,7 @@
|
||||
\example platform/androidnotifier
|
||||
\examplecategory {Mobile}
|
||||
\brief Demonstrates calling Java code from Qt in an Android application.
|
||||
\ingroup androidplatform
|
||||
|
||||
\image androidnotifier.png
|
||||
|
||||
@ -48,7 +49,7 @@
|
||||
|
||||
The call to the Java meethod use \l QJniObject which relies on the Java Native
|
||||
Interface (JNI) APIs to communicate with Java. Also, in the previous snippet,
|
||||
we are passing the app's context object which the the static Java code can use
|
||||
we are passing the app's context object, which the static Java code can use
|
||||
to tap into the app's specific properties and APIs.
|
||||
|
||||
To make sure our smiley buttons do what they are supposed to, we add the
|
||||
|
188
examples/corelib/serialization/cbordump/cbortag.py
Normal file
188
examples/corelib/serialization/cbordump/cbortag.py
Normal file
@ -0,0 +1,188 @@
|
||||
#!/bin/env python3
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
"""Digest cbor-tags.xml file into code for insertion into main.cpp
|
||||
|
||||
See main.cpp's comment on how to regenerate its GENERATED CODE.
|
||||
See ./cbortag.py --help for further details on how to invoke.
|
||||
You can import this is a module without invoking the script.
|
||||
"""
|
||||
|
||||
def firstChild(parent, tag):
|
||||
"""Return parent's first child element with the given tag."""
|
||||
return next(node for node in parent.childNodes
|
||||
if node.nodeType == parent.ELEMENT_NODE and node.nodeName == tag)
|
||||
|
||||
def nodeAttrIs(node, attr, seek):
|
||||
"""Checks whether the node has a given value for an attribute
|
||||
|
||||
Takes the node to check, the name of the attribute and the value
|
||||
to check against. Returns true if the node does have that value
|
||||
for the named attribute."""
|
||||
if node.nodeType != node.ELEMENT_NODE:
|
||||
return False
|
||||
if node.attributes is None or attr not in node.attributes:
|
||||
return False
|
||||
return node.attributes[attr].value == seek
|
||||
|
||||
def getRfcValue(node):
|
||||
"""Extract RFC reference from an <xref type="rfc" ...> element
|
||||
|
||||
Some of these have a reference including section details as the
|
||||
body of the element, otherwise the data attribute should identify
|
||||
the RFC. If neither is found, an empty string is returned."""
|
||||
if node.childNodes:
|
||||
return node.childNodes[0].nodeValue # Maybe accumulate several children ?
|
||||
if node.attributes is None or 'data' not in node.attributes:
|
||||
return ''
|
||||
return node.attributes['data'].value
|
||||
|
||||
def readRegistry(filename):
|
||||
"""Handles the XML parsing and returns the relevant parts.
|
||||
|
||||
Single argument is the path to the cbor-tags.xml file; returns a
|
||||
twople of the title element's text and an interator over the
|
||||
record nodes. Checks some things are as expected while doing so."""
|
||||
from xml.dom.minidom import parse
|
||||
doc = parse(filename).documentElement
|
||||
assert nodeAttrIs(doc, 'id', 'cbor-tags')
|
||||
title = firstChild(doc, 'title').childNodes[0].nodeValue
|
||||
registry = firstChild(doc, 'registry')
|
||||
assert nodeAttrIs(registry, 'id', 'tags')
|
||||
records = (node for node in registry.childNodes if node.nodeName == 'record')
|
||||
return title, records
|
||||
|
||||
def digest(record):
|
||||
"""Digest a single record from cbor-tags.xml
|
||||
|
||||
If the record is not of interest, returns the twople (None, None).
|
||||
For records of interest, returns (n, t) where n is the numeric tag
|
||||
code of the record and t is a text describing it. If the record,
|
||||
or its semantics field, has an xref child with type="rfc", the RFC
|
||||
mentioned there is included with the text of the semantics; such a
|
||||
record is of interest, provided it has a semantics field and no
|
||||
dash in its value. Records with a value field containing a dash
|
||||
(indicating a range) are not of interest. Records with a value of
|
||||
256 or above are only of interest if they include an RFC."""
|
||||
data = {}
|
||||
for kid in record.childNodes:
|
||||
if kid.nodeName == 'xref':
|
||||
if not nodeAttrIs(kid, 'type', 'rfc'):
|
||||
continue
|
||||
rfc = getRfcValue(kid)
|
||||
if rfc:
|
||||
# Potentially stomping one taken from semantics
|
||||
data['rfc'] = rfc
|
||||
elif kid.nodeName == 'semantics':
|
||||
text = rfc = ''
|
||||
for part in kid.childNodes:
|
||||
if part.nodeType == kid.TEXT_NODE:
|
||||
text += part.nodeValue
|
||||
elif part.nodeType == kid.ELEMENT_NODE:
|
||||
if part.nodeName != 'xref' or not nodeAttrIs(part, 'type', 'rfc'):
|
||||
continue # potentially append content to text
|
||||
assert not rfc, ('Duplicate RFC ?', rfc, part)
|
||||
rfc = getRfcValue(part)
|
||||
if rfc:
|
||||
if text.endswith('()'):
|
||||
text = text[:-2].rstrip()
|
||||
if 'rfc' not in data:
|
||||
data['rfc'] = rfc
|
||||
data['semantics'] = ' '.join(text.split())
|
||||
elif kid.nodeName == 'value':
|
||||
data['value'] = kid.childNodes[0].nodeValue
|
||||
text = data.get('semantics')
|
||||
if not text or 'value' not in data or '-' in data['value']:
|
||||
return None, None
|
||||
value = int(data['value'])
|
||||
if 'rfc' in data:
|
||||
rfc = data["rfc"].replace('rfc', 'RFC')
|
||||
text = f'{text} [{rfc}]'
|
||||
elif value >= 256:
|
||||
return None, None
|
||||
return value, text
|
||||
|
||||
def entries(records):
|
||||
"""Digest each record of interest into a value and text.
|
||||
|
||||
The value and text form the raw material of the tagDescriptions
|
||||
array in main.cpp; see digest for which records are retained."""
|
||||
for record in records:
|
||||
value, text = digest(record)
|
||||
if value is not None:
|
||||
yield value, text
|
||||
|
||||
def marginBound(text, prior, left, right):
|
||||
"""Split up a string literal for tidy display.
|
||||
|
||||
The first parameter, text, is the content of the string literal;
|
||||
quotes shall be added. It may be split into several fragments,
|
||||
each quoted, so as to abide by line length constraints.
|
||||
|
||||
The remaining parameters are integers: prior is the text already
|
||||
present on the line before text is to be added; left is the width
|
||||
of the left margin for all subsequent lines; and right is the
|
||||
right margin to stay within, where possible. The returned string
|
||||
is either a space with the whole quoted text following, to fit on
|
||||
the line already started to length prior, or a sequence of quoted
|
||||
strings, each preceded by a newline and indent of width left."""
|
||||
if prior + 3 + len(text) < right: # 1 for space, 2 for quotes
|
||||
return f' "{text}"'
|
||||
width = right - left - 2 # 2 for the quotes
|
||||
words = iter(text.split(' '))
|
||||
lines, current = [''], [next(words)]
|
||||
for word in words:
|
||||
if len(word) + sum(len(w) + 1 for w in current) > width:
|
||||
line = ' '.join(current)
|
||||
lines.append(f'"{line}"')
|
||||
current = ['', word]
|
||||
else:
|
||||
current.append(word)
|
||||
line = ' '.join(current)
|
||||
lines.append(f'"{line}"')
|
||||
return ('\n' + ' ' * left).join(lines)
|
||||
|
||||
def main(argv, speak):
|
||||
"""Takes care of driving the process.
|
||||
|
||||
Takes the command-line argument list (whose first entry is the
|
||||
name of this script) and standard output (or compatible stream of
|
||||
your choosing) to which to write data. If the --out option is
|
||||
specified in the arguments, the file it names is used in place of
|
||||
this output stream."""
|
||||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||
parser = ArgumentParser(
|
||||
description='Digest cbor-tags.xml into code to insert in main.cpp',
|
||||
formatter_class=ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('path', help='path of the cbor-tags.xml file',
|
||||
default='cbor-tags.xml')
|
||||
parser.add_argument('--out', help='file to write instead of standard output')
|
||||
args = parser.parse_args(argv[1:])
|
||||
emit = (open(args.out) if args.out else speak).write
|
||||
|
||||
title, records = readRegistry(args.path)
|
||||
emit(f"""\
|
||||
struct CborTagDescription
|
||||
{{
|
||||
QCborTag tag;
|
||||
const char *description; // with space and parentheses
|
||||
}};
|
||||
|
||||
// {title}
|
||||
static const CborTagDescription tagDescriptions[] = {{
|
||||
// from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
|
||||
""")
|
||||
|
||||
for value, text in sorted(entries(records)):
|
||||
prior = f' {{ QCborTag({value}),'
|
||||
body = marginBound(f' ({text})', len(prior), 6, 96)
|
||||
emit(f"{prior}{body} }},\n")
|
||||
|
||||
emit("""\
|
||||
{ QCborTag(-1), nullptr }
|
||||
};
|
||||
""")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(main(sys.argv, sys.stdout))
|
Binary file not shown.
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 9.3 KiB |
@ -19,18 +19,12 @@ using namespace Qt::StringLiterals;
|
||||
/*
|
||||
* To regenerate:
|
||||
* curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
|
||||
* xsltproc tag-transform.xslt cbor-tags.xml
|
||||
* ./cbortag.py cbor-tags.xml
|
||||
*
|
||||
* The XHTML URL mentioned in the comment below is a human-readable version of
|
||||
* the same resource.
|
||||
*/
|
||||
|
||||
/* TODO (if possible): fix XSLT to replace each newline and surrounding space in
|
||||
a semantics entry with a single space, instead of using a raw string to wrap
|
||||
each, propagating the spacing from the XML to the output of cbordump. Also
|
||||
auto-purge dangling spaces from the ends of generated lines.
|
||||
*/
|
||||
|
||||
// GENERATED CODE
|
||||
struct CborTagDescription
|
||||
{
|
||||
@ -38,180 +32,101 @@ struct CborTagDescription
|
||||
const char *description; // with space and parentheses
|
||||
};
|
||||
|
||||
// CBOR Tags
|
||||
// Concise Binary Object Representation (CBOR) Tags
|
||||
static const CborTagDescription tagDescriptions[] = {
|
||||
// from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
|
||||
{ QCborTag(0),
|
||||
R"r( (Standard date/time string; see Section 3.4.1 [RFC8949]))r" },
|
||||
{ QCborTag(1),
|
||||
R"r( (Epoch-based date/time; see Section 3.4.2 [RFC8949]))r" },
|
||||
{ QCborTag(2),
|
||||
R"r( (Positive bignum; see Section 3.4.3 [RFC8949]))r" },
|
||||
{ QCborTag(3),
|
||||
R"r( (Negative bignum; see Section 3.4.3 [RFC8949]))r" },
|
||||
{ QCborTag(4),
|
||||
R"r( (Decimal fraction; see Section 3.4.4 [RFC8949]))r" },
|
||||
{ QCborTag(5),
|
||||
R"r( (Bigfloat; see Section 3.4.4 [RFC8949]))r" },
|
||||
{ QCborTag(16),
|
||||
R"r( (COSE Single Recipient Encrypted Data Object [RFC9052]))r" },
|
||||
{ QCborTag(17),
|
||||
R"r( (COSE Mac w/o Recipients Object [RFC9052]))r" },
|
||||
{ QCborTag(18),
|
||||
R"r( (COSE Single Signer Data Object [RFC9052]))r" },
|
||||
{ QCborTag(19),
|
||||
R"r( (COSE standalone V2 countersignature [RFC9338]))r" },
|
||||
{ QCborTag(0), " (Standard date/time string; see Section 3.4.1 [RFC8949])" },
|
||||
{ QCborTag(1), " (Epoch-based date/time; see Section 3.4.2 [RFC8949])" },
|
||||
{ QCborTag(2), " (Positive bignum; see Section 3.4.3 [RFC8949])" },
|
||||
{ QCborTag(3), " (Negative bignum; see Section 3.4.3 [RFC8949])" },
|
||||
{ QCborTag(4), " (Decimal fraction; see Section 3.4.4 [RFC8949])" },
|
||||
{ QCborTag(5), " (Bigfloat; see Section 3.4.4 [RFC8949])" },
|
||||
{ QCborTag(16), " (COSE Single Recipient Encrypted Data Object [RFC9052])" },
|
||||
{ QCborTag(17), " (COSE Mac w/o Recipients Object [RFC9052])" },
|
||||
{ QCborTag(18), " (COSE Single Signer Data Object [RFC9052])" },
|
||||
{ QCborTag(19), " (COSE standalone V2 countersignature [RFC9338])" },
|
||||
{ QCborTag(21),
|
||||
R"r( (Expected conversion to base64url encoding; see Section 3.4.5.2 [RFC8949]))r" },
|
||||
{ QCborTag(22),
|
||||
R"r( (Expected conversion to base64 encoding; see Section 3.4.5.2 [RFC8949]))r" },
|
||||
{ QCborTag(23),
|
||||
R"r( (Expected conversion to base16 encoding; see Section 3.4.5.2 [RFC8949]))r" },
|
||||
{ QCborTag(24),
|
||||
R"r( (Encoded CBOR data item; see Section 3.4.5.1 [RFC8949]))r" },
|
||||
{ QCborTag(25),
|
||||
R"r( (reference the nth previously seen string))r" },
|
||||
{ QCborTag(26),
|
||||
R"r( (Serialised Perl object with classname and constructor arguments))r" },
|
||||
" (Expected conversion to base64url encoding; see Section 3.4.5.2 [RFC8949])" },
|
||||
{ QCborTag(22), " (Expected conversion to base64 encoding; see Section 3.4.5.2 [RFC8949])" },
|
||||
{ QCborTag(23), " (Expected conversion to base16 encoding; see Section 3.4.5.2 [RFC8949])" },
|
||||
{ QCborTag(24), " (Encoded CBOR data item; see Section 3.4.5.1 [RFC8949])" },
|
||||
{ QCborTag(25), " (reference the nth previously seen string)" },
|
||||
{ QCborTag(26), " (Serialised Perl object with classname and constructor arguments)" },
|
||||
{ QCborTag(27),
|
||||
R"r( (Serialised language-independent object with type name and constructor arguments))r" },
|
||||
{ QCborTag(28),
|
||||
R"r( (mark value as (potentially) shared))r" },
|
||||
{ QCborTag(29),
|
||||
R"r( (reference nth marked value))r" },
|
||||
{ QCborTag(30),
|
||||
R"r( (Rational number))r" },
|
||||
{ QCborTag(31),
|
||||
R"r( (Absent value in a CBOR Array))r" },
|
||||
{ QCborTag(32),
|
||||
R"r( (URI; see Section 3.4.5.3 [RFC8949]))r" },
|
||||
{ QCborTag(33),
|
||||
R"r( (base64url; see Section 3.4.5.3 [RFC8949]))r" },
|
||||
{ QCborTag(34),
|
||||
R"r( (base64; see Section 3.4.5.3 [RFC8949]))r" },
|
||||
{ QCborTag(35),
|
||||
R"r( (Regular expression; see Section 2.4.4.3 [RFC7049]))r" },
|
||||
{ QCborTag(36),
|
||||
R"r( (MIME message; see Section 3.4.5.3 [RFC8949]))r" },
|
||||
{ QCborTag(37),
|
||||
R"r( (Binary UUID (RFC4122, Section 4.1.2)))r" },
|
||||
{ QCborTag(38),
|
||||
R"r( (Language-tagged string [RFC9290]))r" },
|
||||
{ QCborTag(39),
|
||||
R"r( (Identifier))r" },
|
||||
{ QCborTag(40),
|
||||
R"r( (Multi-dimensional Array, row-major order [RFC8746]))r" },
|
||||
{ QCborTag(41),
|
||||
R"r( (Homogeneous Array [RFC8746]))r" },
|
||||
{ QCborTag(42),
|
||||
R"r( (IPLD content identifier))r" },
|
||||
{ QCborTag(43),
|
||||
R"r( (YANG bits datatype; see Section 6.7. [RFC9254]))r" },
|
||||
{ QCborTag(44),
|
||||
R"r( (YANG enumeration datatype; see Section 6.6. [RFC9254]))r" },
|
||||
{ QCborTag(45),
|
||||
R"r( (YANG identityref datatype; see Section 6.10. [RFC9254]))r" },
|
||||
{ QCborTag(46),
|
||||
R"r( (YANG instance-identifier datatype; see Section 6.13. [RFC9254]))r" },
|
||||
{ QCborTag(47),
|
||||
R"r( (YANG Schema Item iDentifier (sid); see Section 3.2. [RFC9254]))r" },
|
||||
{ QCborTag(52),
|
||||
R"r( (IPv4, [prefixlen,IPv4], [IPv4,prefixpart] [RFC9164]))r" },
|
||||
{ QCborTag(54),
|
||||
R"r( (IPv6, [prefixlen,IPv6], [IPv6,prefixpart] [RFC9164]))r" },
|
||||
{ QCborTag(61),
|
||||
R"r( (CBOR Web Token (CWT) [RFC8392]))r" },
|
||||
{ QCborTag(63),
|
||||
R"r( (Encoded CBOR Sequence ))r" },
|
||||
{ QCborTag(64),
|
||||
R"r( (uint8 Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(65),
|
||||
R"r( (uint16, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(66),
|
||||
R"r( (uint32, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(67),
|
||||
R"r( (uint64, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(68),
|
||||
R"r( (uint8 Typed Array, clamped arithmetic [RFC8746]))r" },
|
||||
{ QCborTag(69),
|
||||
R"r( (uint16, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(70),
|
||||
R"r( (uint32, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(71),
|
||||
R"r( (uint64, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(72),
|
||||
R"r( (sint8 Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(73),
|
||||
R"r( (sint16, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(74),
|
||||
R"r( (sint32, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(75),
|
||||
R"r( (sint64, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(76),
|
||||
R"r( ((reserved) [RFC8746]))r" },
|
||||
{ QCborTag(77),
|
||||
R"r( (sint16, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(78),
|
||||
R"r( (sint32, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(79),
|
||||
R"r( (sint64, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(80),
|
||||
R"r( (IEEE 754 binary16, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(81),
|
||||
R"r( (IEEE 754 binary32, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(82),
|
||||
R"r( (IEEE 754 binary64, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(83),
|
||||
R"r( (IEEE 754 binary128, big endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(84),
|
||||
R"r( (IEEE 754 binary16, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(85),
|
||||
R"r( (IEEE 754 binary32, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(86),
|
||||
R"r( (IEEE 754 binary64, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(87),
|
||||
R"r( (IEEE 754 binary128, little endian, Typed Array [RFC8746]))r" },
|
||||
{ QCborTag(96),
|
||||
R"r( (COSE Encrypted Data Object [RFC9052]))r" },
|
||||
{ QCborTag(97),
|
||||
R"r( (COSE MACed Data Object [RFC9052]))r" },
|
||||
{ QCborTag(98),
|
||||
R"r( (COSE Signed Data Object [RFC9052]))r" },
|
||||
{ QCborTag(100),
|
||||
R"r( (Number of days since the epoch date 1970-01-01 [RFC8943]))r" },
|
||||
{ QCborTag(101),
|
||||
R"r( (alternatives as given by the uint + 128; see Section 9.1))r" },
|
||||
{ QCborTag(103),
|
||||
R"r( (Geographic Coordinates))r" },
|
||||
{ QCborTag(104),
|
||||
R"r( (Geographic Coordinate Reference System WKT or EPSG number))r" },
|
||||
{ QCborTag(110),
|
||||
R"r( (relative object identifier (BER encoding); SDNV sequence [RFC9090]))r" },
|
||||
{ QCborTag(111),
|
||||
R"r( (object identifier (BER encoding) [RFC9090]))r" },
|
||||
{ QCborTag(112),
|
||||
R"r( (object identifier (BER encoding), relative to 1.3.6.1.4.1 [RFC9090]))r" },
|
||||
{ QCborTag(120),
|
||||
R"r( (Internet of Things Data Point))r" },
|
||||
" (Serialised language-independent object with type name and constructor arguments)" },
|
||||
{ QCborTag(28), " (mark value as (potentially) shared)" },
|
||||
{ QCborTag(29), " (reference nth marked value)" },
|
||||
{ QCborTag(30), " (Rational number)" },
|
||||
{ QCborTag(31), " (Absent value in a CBOR Array)" },
|
||||
{ QCborTag(32), " (URI; see Section 3.4.5.3 [RFC8949])" },
|
||||
{ QCborTag(33), " (base64url; see Section 3.4.5.3 [RFC8949])" },
|
||||
{ QCborTag(34), " (base64; see Section 3.4.5.3 [RFC8949])" },
|
||||
{ QCborTag(35), " (Regular expression; see Section 2.4.4.3 [RFC7049])" },
|
||||
{ QCborTag(36), " (MIME message; see Section 3.4.5.3 [RFC8949])" },
|
||||
{ QCborTag(37), " (Binary UUID [RFC4122, Section 4.1.2])" },
|
||||
{ QCborTag(38), " (Language-tagged string [RFC9290, Appendix A])" },
|
||||
{ QCborTag(39), " (Identifier)" },
|
||||
{ QCborTag(40), " (Multi-dimensional Array, row-major order [RFC8746])" },
|
||||
{ QCborTag(41), " (Homogeneous Array [RFC8746])" },
|
||||
{ QCborTag(42), " (IPLD content identifier)" },
|
||||
{ QCborTag(43), " (YANG bits datatype; see Section 6.7. [RFC9254])" },
|
||||
{ QCborTag(44), " (YANG enumeration datatype; see Section 6.6. [RFC9254])" },
|
||||
{ QCborTag(45), " (YANG identityref datatype; see Section 6.10. [RFC9254])" },
|
||||
{ QCborTag(46), " (YANG instance-identifier datatype; see Section 6.13. [RFC9254])" },
|
||||
{ QCborTag(47), " (YANG Schema Item iDentifier (sid); see Section 3.2. [RFC9254])" },
|
||||
{ QCborTag(52), " (IPv4, [prefixlen,IPv4], [IPv4,prefixpart] [RFC9164])" },
|
||||
{ QCborTag(54), " (IPv6, [prefixlen,IPv6], [IPv6,prefixpart] [RFC9164])" },
|
||||
{ QCborTag(61), " (CBOR Web Token (CWT) [RFC8392])" },
|
||||
{ QCborTag(63), " (Encoded CBOR Sequence [RFC8742])" },
|
||||
{ QCborTag(64), " (uint8 Typed Array [RFC8746])" },
|
||||
{ QCborTag(65), " (uint16, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(66), " (uint32, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(67), " (uint64, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(68), " (uint8 Typed Array, clamped arithmetic [RFC8746])" },
|
||||
{ QCborTag(69), " (uint16, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(70), " (uint32, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(71), " (uint64, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(72), " (sint8 Typed Array [RFC8746])" },
|
||||
{ QCborTag(73), " (sint16, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(74), " (sint32, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(75), " (sint64, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(76), " ((reserved) [RFC8746])" },
|
||||
{ QCborTag(77), " (sint16, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(78), " (sint32, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(79), " (sint64, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(80), " (IEEE 754 binary16, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(81), " (IEEE 754 binary32, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(82), " (IEEE 754 binary64, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(83), " (IEEE 754 binary128, big endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(84), " (IEEE 754 binary16, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(85), " (IEEE 754 binary32, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(86), " (IEEE 754 binary64, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(87), " (IEEE 754 binary128, little endian, Typed Array [RFC8746])" },
|
||||
{ QCborTag(96), " (COSE Encrypted Data Object [RFC9052])" },
|
||||
{ QCborTag(97), " (COSE MACed Data Object [RFC9052])" },
|
||||
{ QCborTag(98), " (COSE Signed Data Object [RFC9052])" },
|
||||
{ QCborTag(100), " (Number of days since the epoch date 1970-01-01 [RFC8943])" },
|
||||
{ QCborTag(101), " (alternatives as given by the uint + 128; see Section 9.1)" },
|
||||
{ QCborTag(103), " (Geographic Coordinates)" },
|
||||
{ QCborTag(104), " (Geographic Coordinate Reference System WKT or EPSG number)" },
|
||||
{ QCborTag(110), " (relative object identifier (BER encoding); SDNV sequence [RFC9090])" },
|
||||
{ QCborTag(111), " (object identifier (BER encoding) [RFC9090])" },
|
||||
{ QCborTag(112), " (object identifier (BER encoding), relative to 1.3.6.1.4.1 [RFC9090])" },
|
||||
{ QCborTag(120), " (Internet of Things Data Point)" },
|
||||
{ QCborTag(260),
|
||||
R"r( (Network Address (IPv4 or IPv6 or MAC Address) (DEPRECATED in favor of 52 and 54
|
||||
for IP addresses) [http://www.employees.oRg/~RaviR/CboR-netwoRk.txt]))r" },
|
||||
" (Network Address (IPv4 or IPv6 or MAC Address) (DEPRECATED in favor of 52 and 54 for IP"
|
||||
" addresses) [RFC9164])" },
|
||||
{ QCborTag(261),
|
||||
R"r( (Network Address Prefix (IPv4 or IPv6 Address + Mask Length) (DEPRECATED in favor of 52 and 54
|
||||
for IP addresses) [https://github.Com/toRaviR/CBOR-Tag-SpeCs/blob/masteR/netwoRkPReFix.md]))r" },
|
||||
" (Network Address Prefix (IPv4 or IPv6 Address + Mask Length) (DEPRECATED in favor of 52"
|
||||
" and 54 for IP addresses) [RFC9164])" },
|
||||
{ QCborTag(271),
|
||||
R"r( (DDoS Open Threat Signaling (DOTS) signal channel object,
|
||||
as defined in [RFC9132]))r" },
|
||||
{ QCborTag(1004),
|
||||
R"r( ( full-date string [RFC8943]))r" },
|
||||
{ QCborTag(1040),
|
||||
R"r( (Multi-dimensional Array, column-major order [RFC8746]))r" },
|
||||
{ QCborTag(55799),
|
||||
R"r( (Self-described CBOR; see Section 3.4.6 [RFC8949]))r" },
|
||||
{ QCborTag(55800),
|
||||
R"r( (indicates that the file contains CBOR Sequences [RFC9277]))r" },
|
||||
" (DDoS Open Threat Signaling (DOTS) signal channel object, as defined in [RFC9132])" },
|
||||
{ QCborTag(1004), " (full-date string [RFC8943])" },
|
||||
{ QCborTag(1040), " (Multi-dimensional Array, column-major order [RFC8746])" },
|
||||
{ QCborTag(55799), " (Self-described CBOR; see Section 3.4.6 [RFC8949])" },
|
||||
{ QCborTag(55800), " (indicates that the file contains CBOR Sequences [RFC9277])" },
|
||||
{ QCborTag(55801),
|
||||
R"r( (indicates that the file starts with a CBOR-Labeled Non-CBOR Data label. [RFC9277]))r" },
|
||||
" (indicates that the file starts with a CBOR-Labeled Non-CBOR Data label. [RFC9277])" },
|
||||
{ QCborTag(-1), nullptr }
|
||||
};
|
||||
// END GENERATED CODE
|
||||
|
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://www.iana.org/assignments" xmlns="http://www.iana.org/assignments" xmlns:_="http://www.iana.org/assignments" xmlns:DEFAULT="http://www.iana.org/assignments" version="1.0">
|
||||
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
|
||||
<xsl:template match="/a:registry[@id='cbor-tags']">struct CborTagDescription
|
||||
{
|
||||
QCborTag tag;
|
||||
const char *description; // with space and parentheses
|
||||
};
|
||||
|
||||
// <xsl:value-of select="a:registry/a:title"/>
|
||||
static const CborTagDescription tagDescriptions[] = {
|
||||
// from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
|
||||
<xsl:for-each select="a:registry/a:record">
|
||||
<xsl:sort select="a:value" data-type="number"/>
|
||||
<xsl:if test="a:semantics != ''">
|
||||
<xsl:call-template name="row"/>
|
||||
</xsl:if>
|
||||
</xsl:for-each> { QCborTag(-1), nullptr }
|
||||
};
|
||||
</xsl:template>
|
||||
<xsl:template name="row"> { QCborTag(<xsl:value-of select="a:value"/>),
|
||||
R"r( (<xsl:value-of select="a:semantics"/> <xsl:call-template name="xref"/>))r" },
|
||||
</xsl:template><!-- fn:replace(a:semantics, '\s+', ' ') -->
|
||||
<xsl:template name="xref"><xsl:if test="a:xref/@type = 'rfc'"> [<xsl:value-of
|
||||
select="translate(a:xref/@data,'rfc','RFC')"/>]</xsl:if>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
@ -35,8 +35,8 @@
|
||||
serializing to another format — for example XML or QDataStream, which require passing
|
||||
a document-like object — or when the object identity is important (QObject
|
||||
subclasses, for example), other patterns may be more suitable. See the
|
||||
\l{xml/dombookmarks} and \l{xml/streambookmarks} examples for XML, and the
|
||||
implementation of \l QListWidgetItem::read() and \l QListWidgetItem::write()
|
||||
\l{dombookmarks} example for XML, and the implementation of
|
||||
\l QListWidgetItem::read() and \l QListWidgetItem::write()
|
||||
for idiomatic QDataStream serialization. The \c{print()} functions in this example
|
||||
are good examples of QTextStream serialization, even though they, of course, lack
|
||||
the deserialization side.
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
//! [0]
|
||||
constexpr int DataSize = 100000;
|
||||
const int DataSize = 100000;
|
||||
|
||||
constexpr int BufferSize = 8192;
|
||||
const int BufferSize = 8192;
|
||||
char buffer[BufferSize];
|
||||
|
||||
QSemaphore freeBytes(BufferSize);
|
||||
|
@ -23,7 +23,8 @@ public:
|
||||
{
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
connect(&m_animator, SIGNAL(frameChanged(int)), SLOT(update()));
|
||||
connect(&m_animator, &QTimeLine::frameChanged,
|
||||
this, qOverload<>(&Digits::update));
|
||||
m_animator.setFrameRange(0, 100);
|
||||
m_animator.setDuration(600);
|
||||
m_animator.setEasingCurve(QEasingCurve::InOutSine);
|
||||
@ -272,9 +273,9 @@ public:
|
||||
QAction *slideAction = new QAction("&Slide", this);
|
||||
QAction *flipAction = new QAction("&Flip", this);
|
||||
QAction *rotateAction = new QAction("&Rotate", this);
|
||||
connect(slideAction, SIGNAL(triggered()), SLOT(chooseSlide()));
|
||||
connect(flipAction, SIGNAL(triggered()), SLOT(chooseFlip()));
|
||||
connect(rotateAction, SIGNAL(triggered()), SLOT(chooseRotate()));
|
||||
connect(slideAction, &QAction::triggered, this, &DigiFlip::chooseSlide);
|
||||
connect(flipAction, &QAction::triggered, this, &DigiFlip::chooseFlip);
|
||||
connect(rotateAction, &QAction::triggered, this, &DigiFlip::chooseRotate);
|
||||
addAction(slideAction);
|
||||
addAction(flipAction);
|
||||
addAction(rotateAction);
|
||||
|
@ -71,8 +71,8 @@ public:
|
||||
|
||||
ui.searchBar->hide();
|
||||
ui.infoBox->hide();
|
||||
connect(ui.searchButton, SIGNAL(clicked()), SLOT(startSearch()));
|
||||
connect(ui.flightEdit, SIGNAL(returnPressed()), SLOT(startSearch()));
|
||||
connect(ui.searchButton, &QPushButton::clicked, this, &FlightInfo::startSearch);
|
||||
connect(ui.flightEdit, &QLineEdit::returnPressed, this, &FlightInfo::startSearch);
|
||||
|
||||
setWindowTitle("Flight Info");
|
||||
|
||||
@ -83,11 +83,11 @@ public:
|
||||
QAction *searchTodayAction = new QAction("Today's Flight", this);
|
||||
QAction *searchYesterdayAction = new QAction("Yesterday's Flight", this);
|
||||
QAction *randomAction = new QAction("Random Flight", this);
|
||||
connect(searchTodayAction, SIGNAL(triggered()), SLOT(today()));
|
||||
connect(searchYesterdayAction, SIGNAL(triggered()), SLOT(yesterday()));
|
||||
connect(randomAction, SIGNAL(triggered()), SLOT(randomFlight()));
|
||||
connect(&m_manager, SIGNAL(finished(QNetworkReply*)),
|
||||
this, SLOT(handleNetworkData(QNetworkReply*)));
|
||||
connect(searchTodayAction, &QAction::triggered, this, &FlightInfo::today);
|
||||
connect(searchYesterdayAction, &QAction::triggered, this, &FlightInfo::yesterday);
|
||||
connect(randomAction, &QAction::triggered, this, &FlightInfo::randomFlight);
|
||||
connect(&m_manager, &QNetworkAccessManager::finished,
|
||||
this, &FlightInfo::handleNetworkData);
|
||||
addAction(searchTodayAction);
|
||||
addAction(searchYesterdayAction);
|
||||
addAction(randomAction);
|
||||
|
@ -24,8 +24,8 @@ LightMaps::LightMaps(QWidget *parent)
|
||||
{
|
||||
m_normalMap = new SlippyMap(this);
|
||||
m_largeMap = new SlippyMap(this);
|
||||
connect(m_normalMap, SIGNAL(updated(QRect)), SLOT(updateMap(QRect)));
|
||||
connect(m_largeMap, SIGNAL(updated(QRect)), SLOT(update()));
|
||||
connect(m_normalMap, &SlippyMap::updated, this, &LightMaps::updateMap);
|
||||
connect(m_largeMap, &SlippyMap::updated, this, &LightMaps::updateMap);
|
||||
}
|
||||
|
||||
void LightMaps::setCenter(qreal lat, qreal lng)
|
||||
|
@ -5,3 +5,4 @@ if(NOT TARGET Qt6::Gui)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_add_example(rasterwindow)
|
||||
qt_internal_add_example(rhiwindow)
|
||||
|
BIN
examples/gui/doc/images/rhiwindow_example.jpg
Normal file
BIN
examples/gui/doc/images/rhiwindow_example.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
440
examples/gui/doc/src/rhiwindow.qdoc
Normal file
440
examples/gui/doc/src/rhiwindow.qdoc
Normal file
@ -0,0 +1,440 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\example rhiwindow
|
||||
\title RHI Window Example
|
||||
\examplecategory {Graphics & Multimedia}
|
||||
|
||||
\brief This example shows how to create a minimal QWindow-based
|
||||
application using QRhi.
|
||||
|
||||
\image rhiwindow_example.jpg
|
||||
|
||||
Qt 6.6 starts offering its accelerated 3D API and shader abstraction layer
|
||||
for application use as well. Applications can now use the same 3D graphics
|
||||
classes Qt itself uses to implement the Qt Quick scenegraph or the Qt Quick
|
||||
3D engine. In earlier Qt versions QRhi and the related classes were all
|
||||
private APIs. From 6.6 on these classes are in a similar category as QPA
|
||||
family of classes: neither fully public nor private, but something
|
||||
in-between, with a more limited compatibility promise compared to public
|
||||
APIs. On the other hand, QRhi and the related classes now come with full
|
||||
documentation similarly to public APIs.
|
||||
|
||||
There are multiple ways to use QRhi, the example here shows the most
|
||||
low-level approach: targeting a QWindow, while not using Qt Quick, Qt Quick
|
||||
3D, or Widgets in any form, and setting up all the rendering and windowing
|
||||
infrastructure in the application.
|
||||
|
||||
In contrast, when writing a QML application with Qt Quick or Qt Quick 3D,
|
||||
and wanting to add QRhi-based rendering to it, such an application is going
|
||||
to rely on the window and rendering infrastructure Qt Quick has already
|
||||
initialized, and it is likely going to query an existing QRhi instance from
|
||||
the QQuickWindow. There dealing with QRhi::create(), platform/API specifics
|
||||
such as \l{QVulkanInstance}{Vulkan instances}, or correctly handling
|
||||
\l{QExposeEvent}{expose} and resize events for the window are all managed
|
||||
by Qt Quick. Whereas in this example, all that is managed and taken care
|
||||
of by the application itself.
|
||||
|
||||
\note For QWidget-based applications in particular, it should be noted that
|
||||
QWidget::createWindowContainer() allows embedding a QWindow (backed by a
|
||||
native window) into the widget-based user interface. Therefore, the \c
|
||||
HelloWindow class from this example is reusable in QWidget-based
|
||||
applications, assuming the necessary initialization from \c main() is in
|
||||
place as well.
|
||||
|
||||
\section1 3D API Support
|
||||
|
||||
The application supports all the current \l{QRhi::Implementation}{QRhi
|
||||
backends}. When no command-line arguments are specified, platform-specific
|
||||
defaults are used: Direct 3D 11 on Windows, OpenGL on Linux, Metal on
|
||||
macOS/iOS.
|
||||
|
||||
Running with \c{--help} shows the available command-line options:
|
||||
|
||||
\list
|
||||
\li -d or --d3d11 for Direct 3D 11
|
||||
\li -D or --d3d12 for Direct 3D 12
|
||||
\li -m or --metal for Metal
|
||||
\li -v or --vulkan for Vulkan
|
||||
\li -g or --opengl for OpenGL or OpenGL ES
|
||||
\li -n or --null for the \l{QRhi::Null}{Null backend}
|
||||
\endlist
|
||||
|
||||
\section1 Build System Notes
|
||||
|
||||
This application relies solely on the Qt GUI module. It does not use Qt
|
||||
Widgets or Qt Quick.
|
||||
|
||||
In order to access the RHI APIs, which are available to all Qt applications
|
||||
but come with a limited compatibility promise, the \c target_link_libraries
|
||||
CMake command lists \c{Qt6::GuiPrivate}. This is what enables the
|
||||
\c{#include <rhi/qrhi.h>} include statement to compile successfully.
|
||||
|
||||
\section1 Features
|
||||
|
||||
The application features:
|
||||
|
||||
\list
|
||||
|
||||
\li A resizable QWindow,
|
||||
|
||||
\li a swapchain and depth-stencil buffer that properly follows the size of
|
||||
the window,
|
||||
|
||||
\li logic to initialize, render, and tear down at the appropriate time
|
||||
based on events such as \l QExposeEvent and \l QPlatformSurfaceEvent,
|
||||
|
||||
\li rendering a fullscreen textured quad, using a texture the contents of
|
||||
which is generated in a QImage via QPainter (using the raster paint engine,
|
||||
i.e. the generating of the image's pixel data is all CPU-based, that data
|
||||
is then uploaded into a GPU texture),
|
||||
|
||||
\li rendering a triangle with blending and depth testing enabled, using a
|
||||
perspective projection, while applying a model transform that changes on
|
||||
every frame,
|
||||
|
||||
\li an efficient, cross-platform render loop using
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()}.
|
||||
|
||||
\endlist
|
||||
|
||||
\section1 Shaders
|
||||
|
||||
The application uses two sets of vertex and fragment shader pairs:
|
||||
|
||||
\list
|
||||
|
||||
\li one for the fullscreen quad, which uses no vertex inputs and the
|
||||
fragment shader samples a texture (\c quad.vert, \c quad.frag),
|
||||
|
||||
\li and another pair for the triangle, where vertex positions and colors
|
||||
are provided in a vertex buffer and a modelview-projection matrix is
|
||||
provided in a uniform buffer (\c color.vert, \c color.frag).
|
||||
|
||||
\endlist
|
||||
|
||||
The shaders are written as Vulkan-compatible GLSL source code.
|
||||
|
||||
Due to being a Qt GUI module example, this example cannot have a dependency
|
||||
on the \l{Qt Shader Tools} module. This means that CMake helper functions
|
||||
such as \c{qt_add_shaders} are not available for use. Therefore, the
|
||||
example has the pre-processed \c{.qsb} files included in the
|
||||
\c{shaders/prebuilt} folder, and they are simply included within the
|
||||
executable via \c{qt_add_resources}. This approach is not generally
|
||||
recommended for applications, consider rather using \l{Qt Shader Tools
|
||||
Build System Integration}{qt_add_shaders}, which avoids the need to
|
||||
manually generate and manage the \c{.qsb} files.
|
||||
|
||||
To generate the \c{.qsb} files for this example, the command \c{qsb --qt6
|
||||
color.vert -o prebuilt/color.vert.qsb} etc. was used. This leads to
|
||||
compiling to \l{https://www.khronos.org/spir/}{SPIR-V} and than transpiling
|
||||
into GLSL (\c{100 es} and \c 120), HLSL (5.0), and MSL (1.2). All the
|
||||
shader versions are then packed together into a QShader and serialized to
|
||||
disk.
|
||||
|
||||
\section1 API-specific Initialization
|
||||
|
||||
For some of the 3D APIs the main() function has to perform the appropriate
|
||||
API-specific initialiation, e.g. to create a QVulkanInstance when using
|
||||
Vulkan. For OpenGL we have to ensure a depth buffer is available, this is
|
||||
done via QSurfaceFormat. These steps are not in the scope of QRhi since
|
||||
QRhi backends for OpenGL or Vulkan build on the existing Qt facilities such
|
||||
as QOpenGLContext or QVulkanInstance.
|
||||
|
||||
\snippet rhiwindow/main.cpp api-setup
|
||||
|
||||
\note For Vulkan, note how
|
||||
QRhiVulkanInitParams::preferredInstanceExtensions() is taken into account
|
||||
to ensure the appropriate extensions are enabled.
|
||||
|
||||
\c HelloWindow is a subclass of \c RhiWindow, which in turn is a QWindow.
|
||||
\c RhiWindow contains everything needed to manage a resizable window with
|
||||
a\ swapchain (and depth-stencil buffer), and is potentially reusable in
|
||||
other applications as well. \c HelloWindow contains the rendering logic
|
||||
specific to this particular example application.
|
||||
|
||||
In the QWindow subclass constructor the surface type is set based on the
|
||||
selected 3D API.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp rhiwindow-ctor
|
||||
|
||||
Creating and initializing a QRhi object is implemented in
|
||||
RhiWindow::init(). Note that this is invoked only when the window is
|
||||
\c renderable, which is indicated by an \l{QExposeEvent}{expose event}.
|
||||
|
||||
Depending on which 3D API we use, the appropriate InitParams struct needs
|
||||
to be passed to QRhi::create(). With OpenGL for example, a
|
||||
QOffscreenSurface (or some other QSurface) must be created by the
|
||||
application and provided for use to the QRhi. With Vulkan, a successfully
|
||||
initialized QVulkanInstance is required. Others, such as Direct 3D or Metal
|
||||
need no additional information to be able to initialize.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp rhi-init
|
||||
|
||||
Apart from this, everything else, all the rendering code, is fully
|
||||
cross-platform and has no branching or conditions specific to any of the 3D
|
||||
API.
|
||||
|
||||
\section1 Expose Events
|
||||
|
||||
What \c renderable exactly means is platform-specific. For example, on
|
||||
macOS a window that is fully obscured (fully behind some other window) is
|
||||
not renderable, whereas on Windows obscuring has no significance.
|
||||
Fortunately, the application needs no special knowledge about this: Qt's
|
||||
platform plugins abstract the differences behind the expose event. However,
|
||||
the \l{QWindow::exposeEvent()}{exposeEvent()} reimplementation also needs
|
||||
to be aware that an empty output size (e.g. width and height of 0) is also
|
||||
something that should be treated as a non-renderable situation. On Windows
|
||||
for example, this is what is going to happen when minimizing the window.
|
||||
Hence the check based on QRhiSwapChain::surfacePixelSize().
|
||||
|
||||
This implementation of expose event handling attempts to be robust, safe,
|
||||
and portable. Qt Quick itself also implements a very similar logic in its
|
||||
render loops.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp expose
|
||||
|
||||
In RhiWindow::render(), which is invoked in response to the
|
||||
\l{QEvent::UpdateRequest}{UpdateRequest} event generated by
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()}, the following check is in
|
||||
place, to prevent attempting to render when the swapchain initialization
|
||||
failed, or when the window became non-renderable.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-precheck
|
||||
|
||||
\section1 Swapchain, Depth-Stencil buffer, and Resizing
|
||||
|
||||
To render to the QWindow, a QRhiSwapChain is needed. In addition, a
|
||||
QRhiRenderBuffer acting as the depth-stencil buffer is created as well
|
||||
since the application demonstrates how depth testing can be enabled in a
|
||||
graphics pipeline. With some legacy 3D APIs managing the depth/stencil
|
||||
buffer for a window is part of the corresponding windowing system interface
|
||||
API (EGL, WGL, GLX, etc., meaning the depth/stencil buffer is implicitly
|
||||
managed together with the \c{window surface}), whereas with modern APIs
|
||||
managing the depth-stencil buffer for a window-based render target is no
|
||||
different from offscreen render targets. QRhi abstracts this, but for best
|
||||
performance it still needs to be indicated that the QRhiRenderBuffer is
|
||||
\l{QRhiRenderBuffer::UsedWithSwapChainOnly}{used with together with a
|
||||
QRhiSwapChain}.
|
||||
|
||||
The QRhiSwapChain is associated with the QWindow and the depth/stencil
|
||||
buffer.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.h swapchain-data
|
||||
\codeline
|
||||
\snippet rhiwindow/rhiwindow.cpp swapchain-init
|
||||
|
||||
When the window size changes, the swapchain needs to be resized as well.
|
||||
This is implemented in resizeSwapChain().
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp swapchain-resize
|
||||
|
||||
Unlike other QRhiResource subclasses, QRhiSwapChain features slightly
|
||||
different semantics when it comes to its create-function. As the name,
|
||||
\l{QRhiSwapChain::createOrResize()}{createOrResize()}, suggests, this needs
|
||||
to be called whenever it is known that the output window size may be out of
|
||||
sync with what the swapchain was last initialized. The associated
|
||||
QRhiRenderBuffer for depth-stencil gets its
|
||||
\l{QRhiRenderBuffer::pixelSize()}{size} set automatically, and
|
||||
\l{QRhiRenderBuffer::create()}{create()} is called on it implicitly from the
|
||||
swapchain's createOrResize().
|
||||
|
||||
This is also a convenient place to (re)calculate the projection and view
|
||||
matrices since the perspective projection we set up depends on the output
|
||||
aspect ratio.
|
||||
|
||||
\note To eliminate coordinate system differences, the
|
||||
\l{QRhi::clipSpaceCorrMatrix()}{a backend/API-specific "correction" matrix}
|
||||
is queried from QRhi and baked in to the projection matrix. This is what
|
||||
allows the application to work with OpenGL-style vertex data, assuming a
|
||||
coordinate system with the origin at the bottom-left.
|
||||
|
||||
The resizeSwapChain() function is called from RhiWindow::render() when it
|
||||
is discovered that the currently reported size is not the same anymore as
|
||||
what the swapchain was last initialized with.
|
||||
|
||||
See QRhiSwapChain::currentPixelSize() and QRhiSwapChain::surfacePixelSize()
|
||||
for further details.
|
||||
|
||||
High DPI support is built-in: the sizes, as the naming indicates, are
|
||||
always in pixels, taking the window-specific
|
||||
\l{QWindow::devicePixelRatio()}{scale factor} into account. On the QRhi
|
||||
(and 3D API) level there is no concept of high DPI scaling, everything is
|
||||
always in pixels. This means that a QWindow with a size() of 1280x720 and
|
||||
a devicePixelRatio() of 2 is a render target (swapchain) with a (pixel) size
|
||||
of 2560x1440.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-resize
|
||||
|
||||
\section1 Render Loop
|
||||
|
||||
The application renders continuously, throttled by the presentation rate
|
||||
(vsync). This is ensured by calling
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()} from RhiWindow::render() when
|
||||
the currently recorded frame has been submitted.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp request-update
|
||||
|
||||
This eventually leads to getting a \l{QEvent::UpdateRequest}{UpdateRequest}
|
||||
event. This is handled in the reimplementation of event().
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp event
|
||||
|
||||
\section1 Resource and Pipeline Setup
|
||||
|
||||
The application records a single render pass that issues two draw calls,
|
||||
with two different graphics pipelines. One is the "background", with the
|
||||
texture containing the QPainter-generated image, then a single triangle is
|
||||
rendered on top with blending enabled.
|
||||
|
||||
The vertex and uniform buffer used with the triangle is created like this.
|
||||
The size of the uniform buffer is 68 bytes since the shader specific a \c
|
||||
mat4 and a \c float member in the uniform block. Watch out for the
|
||||
\l{https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159}{std140
|
||||
layout rules}. This presents no surprises in this example since the \c
|
||||
float member that follows the \c mat4 has the correct alignment without any
|
||||
additional padding, but it may become relevant in other applications,
|
||||
especially when working with types such as \c vec2 or \c vec3. When in
|
||||
doubt, consider checking the QShaderDescription for the
|
||||
\l{QShader::description()}{QShader}, or, what is often more convenient, run
|
||||
the \c qsb tool on the \c{.qsb} file with the \c{-d} argument to inspect
|
||||
the metadata in human-readable form. The printed information includes,
|
||||
among other things, the uniform block member offsets, sizes, and the total
|
||||
size in bytes of each uniform block.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-init-1
|
||||
|
||||
The vertex and fragment shaders both need a uniform buffer at binding point
|
||||
0. This is ensured by the QRhiShaderResourceBindings object. The graphics
|
||||
pipeline is then setup with the shaders and a number of additional
|
||||
information. The example also relies on a number of convenient defaults,
|
||||
e.g. the primitive topology is
|
||||
\l{QRhiGraphicsPipeline::Triangles}{Triangles}, but that is the default,
|
||||
and therefore it is not explicitly set. See QRhiGraphicsPipeline for
|
||||
further details.
|
||||
|
||||
In addition to specifying the topology and various state, the pipeline must
|
||||
also be associated with:
|
||||
|
||||
\list
|
||||
|
||||
\li The vertex input layout in form of a QRhiVertexInputLayout. This
|
||||
specifies the type and component count for each vertex input location, the
|
||||
total stride in bytes per vertex, and other related data.
|
||||
QRhiVertexInputLayout only holds data, not actual native resources, and is
|
||||
copiable.
|
||||
|
||||
\li A valid and successfully initialized QRhiShaderResourceBindings object.
|
||||
This describes the layout of the resource bindings (uniform buffers,
|
||||
textures, samplers) the shaders expect. This must either by the
|
||||
QRhiShaderResourceBindings used when recording the draw calls, or another
|
||||
that is
|
||||
\l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible with it}.
|
||||
This simple application takes the former approach.
|
||||
|
||||
\li A valid QRhiRenderPassDescriptor object. This must be retrieved from,
|
||||
or \l{QRhiRenderPassDescriptor::isCompatible()}{be compatible with} the
|
||||
render target. The example uses the former, by creating a
|
||||
QRhiRenderPassDescriptor object via
|
||||
QRhiSwapChain::newCompatibleRenderPassDescriptor().
|
||||
|
||||
\endlist
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-init-2
|
||||
|
||||
getShader() is a helper function that loads a \c{.qsb} file and
|
||||
deserializes a QShader from it.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp getshader
|
||||
|
||||
The \c{color.vert} shader specifies the following as the vertex inputs:
|
||||
|
||||
\badcode
|
||||
layout(location = 0) in vec4 position;
|
||||
layout(location = 1) in vec3 color;
|
||||
\endcode
|
||||
|
||||
The C++ code however provides vertex data as 2 floats for position, with 3
|
||||
floats for the color interleaved. (\c x, \c y, \c r, \c g, \c b for each
|
||||
vertex) This is why the stride is \c{5 * sizeof(float)} and the inputs for
|
||||
locations 0 and 1 are specified as \c Float2 and \c Float3, respectively.
|
||||
This is valid, and the \c z and \c w of the \c vec4 position will get set
|
||||
automatically.
|
||||
|
||||
\section1 Rendering
|
||||
|
||||
Recording a frame is started by calling \l{QRhi::beginFrame()} and finished
|
||||
by calling \l{QRhi::endFrame()}.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp beginframe
|
||||
|
||||
Some of the resources (buffers, textures) have static data in the
|
||||
application, meaning the content never changes. The vertex buffer's content
|
||||
is provided in the initialization step for example, and is not changed
|
||||
afterwards. These data update operations are recorded in \c
|
||||
m_initialUpdates. When not yet done, the commands on this resource update
|
||||
batch are merged into the per-frame batch.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-1
|
||||
|
||||
Having a per-frame resource update batch is necessary since the uniform
|
||||
buffer contents with the modelview-projection matrix and the opacity
|
||||
changes on every frame.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-rotation
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-opacity
|
||||
|
||||
To begin recording the render pass, a QRhiCommandBuffer is queried, and the
|
||||
output size is determined, which will be useful for setting up the viewport
|
||||
and resizing our fullscreen texture, if needed.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-cb
|
||||
|
||||
Starting a render pass implies clearing the render target's color and
|
||||
depth-stencil buffers (unless the render target flags indicate otherwise,
|
||||
but that is only an option for texture-based render targets). Here we
|
||||
specify black for color, 1.0f for depth, and 0 for stencil (unused). The
|
||||
last argument, \c resourceUpdates, is what ensures that the data update
|
||||
commands recorded on the batch get committed. Alternatively, we could have
|
||||
used QRhiCommandBuffer::resourceUpdate() instead. The render pass targets a
|
||||
swapchain, hence calling
|
||||
\l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}
|
||||
to get a valid QRhiRenderTarget.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-pass
|
||||
|
||||
Recording the draw call for the triangle is straightforward: set the
|
||||
pipeline, set the shader resources, set the vertex/index buffer(s), and
|
||||
record the draw call. Here we use a non-indexed draw with just 3 vertices.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-pass-record
|
||||
|
||||
The \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} call
|
||||
has no arguments given, which implies using \c m_colorTriSrb since that was
|
||||
associated with the active QRhiGraphicsPipeline (\c m_colorPipeline).
|
||||
|
||||
We will not dive into the details of the rendering of the fullscreen
|
||||
background image. See the example source code for that. It is however worth
|
||||
noting a common pattern for "resizing" a texture or buffer resource. There
|
||||
is no such thing as changing the size of an existing native resource, so
|
||||
changing a texture or buffer size must be followed by a call to create(),
|
||||
to release and recreate the underlying native resources. To ensure that the
|
||||
QRhiTexture always has the required size, the application implements the
|
||||
following logic. Note that \c m_texture stays valid for the entire lifetime
|
||||
of the window, which means object references to it, e.g. in a
|
||||
QRhiShaderResourceBindings, continue to be valid all the time. It is only
|
||||
the underlying native resources that come and go over time.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp ensure-texture
|
||||
|
||||
Once a QImage is generated and the QPainter-based drawing into it has
|
||||
finished, we use
|
||||
\l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} to record a
|
||||
texture upload on the resource update batch:
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp ensure-texture-2
|
||||
|
||||
\sa QRhi, QRhiSwapChain, QWindow, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiBuffer, QRhiTexture
|
||||
*/
|
@ -4,4 +4,5 @@ TEMPLATE = subdirs
|
||||
QT_FOR_CONFIG += gui
|
||||
CONFIG += no_docs_target
|
||||
|
||||
SUBDIRS += rasterwindow
|
||||
SUBDIRS += rasterwindow \
|
||||
rhiwindow
|
||||
|
59
examples/gui/rhiwindow/CMakeLists.txt
Normal file
59
examples/gui/rhiwindow/CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(rhiwindow LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/gui/rhiwindow")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(rhiwindow
|
||||
main.cpp
|
||||
rhiwindow.cpp rhiwindow.h
|
||||
)
|
||||
|
||||
set_target_properties(rhiwindow PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(rhiwindow PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::GuiPrivate
|
||||
)
|
||||
|
||||
set_source_files_properties("shaders/prebuilt/color.vert.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "color.vert.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/color.frag.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "color.frag.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/quad.vert.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "quad.vert.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/quad.frag.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "quad.frag.qsb"
|
||||
)
|
||||
qt_add_resources(rhiwindow "rhiwindow"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
"shaders/prebuilt/color.vert.qsb"
|
||||
"shaders/prebuilt/color.frag.qsb"
|
||||
"shaders/prebuilt/quad.vert.qsb"
|
||||
"shaders/prebuilt/quad.frag.qsb"
|
||||
)
|
||||
|
||||
install(TARGETS rhiwindow
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
110
examples/gui/rhiwindow/main.cpp
Normal file
110
examples/gui/rhiwindow/main.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include "rhiwindow.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QRhi::Implementation graphicsApi;
|
||||
|
||||
// Use platform-specific defaults when no command-line arguments given.
|
||||
#if defined(Q_OS_WIN)
|
||||
graphicsApi = QRhi::D3D11;
|
||||
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
graphicsApi = QRhi::Metal;
|
||||
#elif QT_CONFIG(vulkan)
|
||||
graphicsApi = QRhi::Vulkan;
|
||||
#else
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
#endif
|
||||
|
||||
QCommandLineParser cmdLineParser;
|
||||
cmdLineParser.addHelpOption();
|
||||
QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
|
||||
cmdLineParser.addOption(nullOption);
|
||||
QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL"));
|
||||
cmdLineParser.addOption(glOption);
|
||||
QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
|
||||
cmdLineParser.addOption(vkOption);
|
||||
QCommandLineOption d3d11Option({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
|
||||
cmdLineParser.addOption(d3d11Option);
|
||||
QCommandLineOption d3d12Option({ "D", "d3d12" }, QLatin1String("Direct3D 12"));
|
||||
cmdLineParser.addOption(d3d12Option);
|
||||
QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
|
||||
cmdLineParser.addOption(mtlOption);
|
||||
|
||||
cmdLineParser.process(app);
|
||||
if (cmdLineParser.isSet(nullOption))
|
||||
graphicsApi = QRhi::Null;
|
||||
if (cmdLineParser.isSet(glOption))
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
if (cmdLineParser.isSet(vkOption))
|
||||
graphicsApi = QRhi::Vulkan;
|
||||
if (cmdLineParser.isSet(d3d11Option))
|
||||
graphicsApi = QRhi::D3D11;
|
||||
if (cmdLineParser.isSet(d3d12Option))
|
||||
graphicsApi = QRhi::D3D12;
|
||||
if (cmdLineParser.isSet(mtlOption))
|
||||
graphicsApi = QRhi::Metal;
|
||||
|
||||
//! [api-setup]
|
||||
// For OpenGL, to ensure there is a depth/stencil buffer for the window.
|
||||
// With other APIs this is under the application's control (QRhiRenderBuffer etc.)
|
||||
// and so no special setup is needed for those.
|
||||
QSurfaceFormat fmt;
|
||||
fmt.setDepthBufferSize(24);
|
||||
fmt.setStencilBufferSize(8);
|
||||
// Special case macOS to allow using OpenGL there.
|
||||
// (the default Metal is the recommended approach, though)
|
||||
// gl_VertexID is a GLSL 130 feature, and so the default OpenGL 2.1 context
|
||||
// we get on macOS is not sufficient.
|
||||
#ifdef Q_OS_MACOS
|
||||
fmt.setVersion(4, 1);
|
||||
fmt.setProfile(QSurfaceFormat::CoreProfile);
|
||||
#endif
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
|
||||
// For Vulkan.
|
||||
#if QT_CONFIG(vulkan)
|
||||
QVulkanInstance inst;
|
||||
if (graphicsApi == QRhi::Vulkan) {
|
||||
// Request validation, if available. This is completely optional
|
||||
// and has a performance impact, and should be avoided in production use.
|
||||
inst.setLayers({ "VK_LAYER_KHRONOS_validation" });
|
||||
// Play nice with QRhi.
|
||||
inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
|
||||
if (!inst.create()) {
|
||||
qWarning("Failed to create Vulkan instance, switching to OpenGL");
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//! [api-setup]
|
||||
|
||||
HelloWindow window(graphicsApi);
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
if (graphicsApi == QRhi::Vulkan)
|
||||
window.setVulkanInstance(&inst);
|
||||
#endif
|
||||
window.resize(1280, 720);
|
||||
window.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + window.graphicsApiName());
|
||||
window.show();
|
||||
|
||||
int ret = app.exec();
|
||||
|
||||
// RhiWindow::event() will not get invoked when the
|
||||
// PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
|
||||
// destruction. That happens only when exiting via app::quit() instead of
|
||||
// the more common QWindow::close(). Take care of it: if the QPlatformWindow
|
||||
// is still around (there was no close() yet), get rid of the swapchain
|
||||
// while it's not too late.
|
||||
if (window.handle())
|
||||
window.releaseSwapChain();
|
||||
|
||||
return ret;
|
||||
}
|
435
examples/gui/rhiwindow/rhiwindow.cpp
Normal file
435
examples/gui/rhiwindow/rhiwindow.cpp
Normal file
@ -0,0 +1,435 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "rhiwindow.h"
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#include <QPainter>
|
||||
#include <QFile>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
//! [rhiwindow-ctor]
|
||||
RhiWindow::RhiWindow(QRhi::Implementation graphicsApi)
|
||||
: m_graphicsApi(graphicsApi)
|
||||
{
|
||||
switch (graphicsApi) {
|
||||
case QRhi::OpenGLES2:
|
||||
setSurfaceType(OpenGLSurface);
|
||||
break;
|
||||
case QRhi::Vulkan:
|
||||
setSurfaceType(VulkanSurface);
|
||||
break;
|
||||
case QRhi::D3D11:
|
||||
case QRhi::D3D12:
|
||||
setSurfaceType(Direct3DSurface);
|
||||
break;
|
||||
case QRhi::Metal:
|
||||
setSurfaceType(MetalSurface);
|
||||
break;
|
||||
case QRhi::Null:
|
||||
break; // RasterSurface
|
||||
}
|
||||
}
|
||||
//! [rhiwindow-ctor]
|
||||
|
||||
QString RhiWindow::graphicsApiName() const
|
||||
{
|
||||
switch (m_graphicsApi) {
|
||||
case QRhi::Null:
|
||||
return QLatin1String("Null (no output)");
|
||||
case QRhi::OpenGLES2:
|
||||
return QLatin1String("OpenGL");
|
||||
case QRhi::Vulkan:
|
||||
return QLatin1String("Vulkan");
|
||||
case QRhi::D3D11:
|
||||
return QLatin1String("Direct3D 11");
|
||||
case QRhi::D3D12:
|
||||
return QLatin1String("Direct3D 12");
|
||||
case QRhi::Metal:
|
||||
return QLatin1String("Metal");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
//! [expose]
|
||||
void RhiWindow::exposeEvent(QExposeEvent *)
|
||||
{
|
||||
// initialize and start rendering when the window becomes usable for graphics purposes
|
||||
if (isExposed() && !m_initialized) {
|
||||
init();
|
||||
resizeSwapChain();
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
const QSize surfaceSize = m_hasSwapChain ? m_sc->surfacePixelSize() : QSize();
|
||||
|
||||
// stop pushing frames when not exposed (or size is 0)
|
||||
if ((!isExposed() || (m_hasSwapChain && surfaceSize.isEmpty())) && m_initialized && !m_notExposed)
|
||||
m_notExposed = true;
|
||||
|
||||
// Continue when exposed again and the surface has a valid size. Note that
|
||||
// surfaceSize can be (0, 0) even though size() reports a valid one, hence
|
||||
// trusting surfacePixelSize() and not QWindow.
|
||||
if (isExposed() && m_initialized && m_notExposed && !surfaceSize.isEmpty()) {
|
||||
m_notExposed = false;
|
||||
m_newlyExposed = true;
|
||||
}
|
||||
|
||||
// always render a frame on exposeEvent() (when exposed) in order to update
|
||||
// immediately on window resize.
|
||||
if (isExposed() && !surfaceSize.isEmpty())
|
||||
render();
|
||||
}
|
||||
//! [expose]
|
||||
|
||||
//! [event]
|
||||
bool RhiWindow::event(QEvent *e)
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::UpdateRequest:
|
||||
render();
|
||||
break;
|
||||
|
||||
case QEvent::PlatformSurface:
|
||||
// this is the proper time to tear down the swapchain (while the native window and surface are still around)
|
||||
if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
|
||||
releaseSwapChain();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWindow::event(e);
|
||||
}
|
||||
//! [event]
|
||||
|
||||
//! [rhi-init]
|
||||
void RhiWindow::init()
|
||||
{
|
||||
if (m_graphicsApi == QRhi::Null) {
|
||||
QRhiNullInitParams params;
|
||||
m_rhi.reset(QRhi::create(QRhi::Null, ¶ms));
|
||||
}
|
||||
|
||||
#if QT_CONFIG(opengl)
|
||||
if (m_graphicsApi == QRhi::OpenGLES2) {
|
||||
m_fallbackSurface.reset(QRhiGles2InitParams::newFallbackSurface());
|
||||
QRhiGles2InitParams params;
|
||||
params.fallbackSurface = m_fallbackSurface.get();
|
||||
params.window = this;
|
||||
m_rhi.reset(QRhi::create(QRhi::OpenGLES2, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
if (m_graphicsApi == QRhi::Vulkan) {
|
||||
QRhiVulkanInitParams params;
|
||||
params.inst = vulkanInstance();
|
||||
params.window = this;
|
||||
m_rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (m_graphicsApi == QRhi::D3D11) {
|
||||
QRhiD3D11InitParams params;
|
||||
// Enable the debug layer, if available. This is optional
|
||||
// and should be avoided in production builds.
|
||||
params.enableDebugLayer = true;
|
||||
m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms));
|
||||
} else if (m_graphicsApi == QRhi::D3D12) {
|
||||
QRhiD3D12InitParams params;
|
||||
// Enable the debug layer, if available. This is optional
|
||||
// and should be avoided in production builds.
|
||||
params.enableDebugLayer = true;
|
||||
m_rhi.reset(QRhi::create(QRhi::D3D12, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
if (m_graphicsApi == QRhi::Metal) {
|
||||
QRhiMetalInitParams params;
|
||||
m_rhi.reset(QRhi::create(QRhi::Metal, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_rhi)
|
||||
qFatal("Failed to create RHI backend");
|
||||
//! [rhi-init]
|
||||
|
||||
//! [swapchain-init]
|
||||
m_sc.reset(m_rhi->newSwapChain());
|
||||
m_ds.reset(m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
|
||||
QSize(), // no need to set the size here, due to UsedWithSwapChainOnly
|
||||
1,
|
||||
QRhiRenderBuffer::UsedWithSwapChainOnly));
|
||||
m_sc->setWindow(this);
|
||||
m_sc->setDepthStencil(m_ds.get());
|
||||
m_rp.reset(m_sc->newCompatibleRenderPassDescriptor());
|
||||
m_sc->setRenderPassDescriptor(m_rp.get());
|
||||
//! [swapchain-init]
|
||||
|
||||
customInit();
|
||||
}
|
||||
|
||||
//! [swapchain-resize]
|
||||
void RhiWindow::resizeSwapChain()
|
||||
{
|
||||
m_hasSwapChain = m_sc->createOrResize(); // also handles m_ds
|
||||
|
||||
const QSize outputSize = m_sc->currentPixelSize();
|
||||
m_viewProjection = m_rhi->clipSpaceCorrMatrix();
|
||||
m_viewProjection.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
|
||||
m_viewProjection.translate(0, 0, -4);
|
||||
}
|
||||
//! [swapchain-resize]
|
||||
|
||||
void RhiWindow::releaseSwapChain()
|
||||
{
|
||||
if (m_hasSwapChain) {
|
||||
m_hasSwapChain = false;
|
||||
m_sc->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
//! [render-precheck]
|
||||
void RhiWindow::render()
|
||||
{
|
||||
if (!m_hasSwapChain || m_notExposed)
|
||||
return;
|
||||
//! [render-precheck]
|
||||
|
||||
//! [render-resize]
|
||||
// If the window got resized or newly exposed, resize the swapchain. (the
|
||||
// newly-exposed case is not actually required by some platforms, but is
|
||||
// here for robustness and portability)
|
||||
//
|
||||
// This (exposeEvent + the logic here) is the only safe way to perform
|
||||
// resize handling. Note the usage of the RHI's surfacePixelSize(), and
|
||||
// never QWindow::size(). (the two may or may not be the same under the hood,
|
||||
// depending on the backend and platform)
|
||||
//
|
||||
if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
|
||||
resizeSwapChain();
|
||||
if (!m_hasSwapChain)
|
||||
return;
|
||||
m_newlyExposed = false;
|
||||
}
|
||||
//! [render-resize]
|
||||
|
||||
//! [beginframe]
|
||||
QRhi::FrameOpResult result = m_rhi->beginFrame(m_sc.get());
|
||||
if (result == QRhi::FrameOpSwapChainOutOfDate) {
|
||||
resizeSwapChain();
|
||||
if (!m_hasSwapChain)
|
||||
return;
|
||||
result = m_rhi->beginFrame(m_sc.get());
|
||||
}
|
||||
if (result != QRhi::FrameOpSuccess) {
|
||||
qWarning("beginFrame failed with %d, will retry", result);
|
||||
requestUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
customRender();
|
||||
//! [beginframe]
|
||||
|
||||
//! [request-update]
|
||||
m_rhi->endFrame(m_sc.get());
|
||||
|
||||
// Always request the next frame via requestUpdate(). On some platforms this is backed
|
||||
// by a platform-specific solution, e.g. CVDisplayLink on macOS, which is potentially
|
||||
// more efficient than a timer, queued metacalls, etc.
|
||||
requestUpdate();
|
||||
}
|
||||
//! [request-update]
|
||||
|
||||
static float vertexData[] = {
|
||||
// Y up (note clipSpaceCorrMatrix in m_viewProjection), CCW
|
||||
0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
//! [getshader]
|
||||
static QShader getShader(const QString &name)
|
||||
{
|
||||
QFile f(name);
|
||||
if (f.open(QIODevice::ReadOnly))
|
||||
return QShader::fromSerialized(f.readAll());
|
||||
|
||||
return QShader();
|
||||
}
|
||||
//! [getshader]
|
||||
|
||||
HelloWindow::HelloWindow(QRhi::Implementation graphicsApi)
|
||||
: RhiWindow(graphicsApi)
|
||||
{
|
||||
}
|
||||
|
||||
//! [ensure-texture]
|
||||
void HelloWindow::ensureFullscreenTexture(const QSize &pixelSize, QRhiResourceUpdateBatch *u)
|
||||
{
|
||||
if (m_texture && m_texture->pixelSize() == pixelSize)
|
||||
return;
|
||||
|
||||
if (!m_texture)
|
||||
m_texture.reset(m_rhi->newTexture(QRhiTexture::RGBA8, pixelSize));
|
||||
else
|
||||
m_texture->setPixelSize(pixelSize);
|
||||
|
||||
m_texture->create();
|
||||
|
||||
QImage image(pixelSize, QImage::Format_RGBA8888_Premultiplied);
|
||||
//! [ensure-texture]
|
||||
QPainter painter(&image);
|
||||
painter.fillRect(QRectF(QPointF(0, 0), pixelSize), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f));
|
||||
painter.setPen(Qt::transparent);
|
||||
painter.setBrush({ QGradient(QGradient::DeepBlue) });
|
||||
painter.drawRoundedRect(QRectF(QPointF(20, 20), pixelSize - QSize(40, 40)), 16, 16);
|
||||
painter.setPen(Qt::black);
|
||||
QFont font;
|
||||
font.setPixelSize(0.05 * qMin(pixelSize.width(), pixelSize.height()));
|
||||
painter.setFont(font);
|
||||
painter.drawText(QRectF(QPointF(60, 60), pixelSize - QSize(120, 120)), 0,
|
||||
QLatin1String("Rendering with QRhi to a resizable QWindow.\nThe 3D API is %1.\nUse the command-line options to choose a different API.")
|
||||
.arg(graphicsApiName()));
|
||||
painter.end();
|
||||
|
||||
if (m_rhi->isYUpInNDC())
|
||||
image = image.mirrored();
|
||||
|
||||
//! [ensure-texture-2]
|
||||
u->uploadTexture(m_texture.get(), image);
|
||||
//! [ensure-texture-2]
|
||||
}
|
||||
|
||||
//! [render-init-1]
|
||||
void HelloWindow::customInit()
|
||||
{
|
||||
m_initialUpdates = m_rhi->nextResourceUpdateBatch();
|
||||
|
||||
m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
|
||||
m_vbuf->create();
|
||||
m_initialUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData);
|
||||
|
||||
static const quint32 UBUF_SIZE = 68;
|
||||
m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE));
|
||||
m_ubuf->create();
|
||||
//! [render-init-1]
|
||||
|
||||
ensureFullscreenTexture(m_sc->surfacePixelSize(), m_initialUpdates);
|
||||
|
||||
m_sampler.reset(m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
|
||||
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
|
||||
m_sampler->create();
|
||||
|
||||
//! [render-init-2]
|
||||
m_colorTriSrb.reset(m_rhi->newShaderResourceBindings());
|
||||
static const QRhiShaderResourceBinding::StageFlags visibility =
|
||||
QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage;
|
||||
m_colorTriSrb->setBindings({
|
||||
QRhiShaderResourceBinding::uniformBuffer(0, visibility, m_ubuf.get())
|
||||
});
|
||||
m_colorTriSrb->create();
|
||||
|
||||
m_colorPipeline.reset(m_rhi->newGraphicsPipeline());
|
||||
// Enable depth testing; not quite needed for a simple triangle, but we
|
||||
// have a depth-stencil buffer so why not.
|
||||
m_colorPipeline->setDepthTest(true);
|
||||
m_colorPipeline->setDepthWrite(true);
|
||||
// Blend factors default to One, OneOneMinusSrcAlpha, which is convenient.
|
||||
QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
|
||||
premulAlphaBlend.enable = true;
|
||||
m_colorPipeline->setTargetBlends({ premulAlphaBlend });
|
||||
m_colorPipeline->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
|
||||
});
|
||||
QRhiVertexInputLayout inputLayout;
|
||||
inputLayout.setBindings({
|
||||
{ 5 * sizeof(float) }
|
||||
});
|
||||
inputLayout.setAttributes({
|
||||
{ 0, 0, QRhiVertexInputAttribute::Float2, 0 },
|
||||
{ 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
|
||||
});
|
||||
m_colorPipeline->setVertexInputLayout(inputLayout);
|
||||
m_colorPipeline->setShaderResourceBindings(m_colorTriSrb.get());
|
||||
m_colorPipeline->setRenderPassDescriptor(m_rp.get());
|
||||
m_colorPipeline->create();
|
||||
//! [render-init-2]
|
||||
|
||||
m_fullscreenQuadSrb.reset(m_rhi->newShaderResourceBindings());
|
||||
m_fullscreenQuadSrb->setBindings({
|
||||
QRhiShaderResourceBinding::sampledTexture(0, QRhiShaderResourceBinding::FragmentStage,
|
||||
m_texture.get(), m_sampler.get())
|
||||
});
|
||||
m_fullscreenQuadSrb->create();
|
||||
|
||||
m_fullscreenQuadPipeline.reset(m_rhi->newGraphicsPipeline());
|
||||
m_fullscreenQuadPipeline->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String(":/quad.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/quad.frag.qsb")) }
|
||||
});
|
||||
m_fullscreenQuadPipeline->setVertexInputLayout({});
|
||||
m_fullscreenQuadPipeline->setShaderResourceBindings(m_fullscreenQuadSrb.get());
|
||||
m_fullscreenQuadPipeline->setRenderPassDescriptor(m_rp.get());
|
||||
m_fullscreenQuadPipeline->create();
|
||||
}
|
||||
|
||||
//! [render-1]
|
||||
void HelloWindow::customRender()
|
||||
{
|
||||
QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
|
||||
|
||||
if (m_initialUpdates) {
|
||||
resourceUpdates->merge(m_initialUpdates);
|
||||
m_initialUpdates->release();
|
||||
m_initialUpdates = nullptr;
|
||||
}
|
||||
//! [render-1]
|
||||
|
||||
//! [render-rotation]
|
||||
m_rotation += 1.0f;
|
||||
QMatrix4x4 modelViewProjection = m_viewProjection;
|
||||
modelViewProjection.rotate(m_rotation, 0, 1, 0);
|
||||
resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData());
|
||||
//! [render-rotation]
|
||||
|
||||
//! [render-opacity]
|
||||
m_opacity += m_opacityDir * 0.005f;
|
||||
if (m_opacity < 0.0f || m_opacity > 1.0f) {
|
||||
m_opacityDir *= -1;
|
||||
m_opacity = qBound(0.0f, m_opacity, 1.0f);
|
||||
}
|
||||
resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 64, 4, &m_opacity);
|
||||
//! [render-opacity]
|
||||
|
||||
//! [render-cb]
|
||||
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
|
||||
const QSize outputSizeInPixels = m_sc->currentPixelSize();
|
||||
//! [render-cb]
|
||||
|
||||
// (re)create the texture with a size matching the output surface size, when necessary.
|
||||
ensureFullscreenTexture(outputSizeInPixels, resourceUpdates);
|
||||
|
||||
//! [render-pass]
|
||||
cb->beginPass(m_sc->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 }, resourceUpdates);
|
||||
//! [render-pass]
|
||||
|
||||
cb->setGraphicsPipeline(m_fullscreenQuadPipeline.get());
|
||||
cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
|
||||
cb->setShaderResources();
|
||||
cb->draw(3);
|
||||
|
||||
//! [render-pass-record]
|
||||
cb->setGraphicsPipeline(m_colorPipeline.get());
|
||||
cb->setShaderResources();
|
||||
const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
|
||||
cb->setVertexInput(0, 1, &vbufBinding);
|
||||
cb->draw(3);
|
||||
|
||||
cb->endPass();
|
||||
//! [render-pass-record]
|
||||
}
|
78
examples/gui/rhiwindow/rhiwindow.h
Normal file
78
examples/gui/rhiwindow/rhiwindow.h
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWindow>
|
||||
#include <QOffscreenSurface>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class RhiWindow : public QWindow
|
||||
{
|
||||
public:
|
||||
RhiWindow(QRhi::Implementation graphicsApi);
|
||||
QString graphicsApiName() const;
|
||||
void releaseSwapChain();
|
||||
|
||||
protected:
|
||||
virtual void customInit() = 0;
|
||||
virtual void customRender() = 0;
|
||||
|
||||
// destruction order matters to a certain degree: the fallbackSurface must
|
||||
// outlive the rhi, the rhi must outlive all other resources. The resources
|
||||
// need no special order when destroying.
|
||||
#if QT_CONFIG(opengl)
|
||||
std::unique_ptr<QOffscreenSurface> m_fallbackSurface;
|
||||
#endif
|
||||
std::unique_ptr<QRhi> m_rhi;
|
||||
//! [swapchain-data]
|
||||
std::unique_ptr<QRhiSwapChain> m_sc;
|
||||
std::unique_ptr<QRhiRenderBuffer> m_ds;
|
||||
std::unique_ptr<QRhiRenderPassDescriptor> m_rp;
|
||||
//! [swapchain-data]
|
||||
bool m_hasSwapChain = false;
|
||||
QMatrix4x4 m_viewProjection;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void resizeSwapChain();
|
||||
void render();
|
||||
|
||||
void exposeEvent(QExposeEvent *) override;
|
||||
bool event(QEvent *) override;
|
||||
|
||||
QRhi::Implementation m_graphicsApi;
|
||||
bool m_initialized = false;
|
||||
bool m_notExposed = false;
|
||||
bool m_newlyExposed = false;
|
||||
};
|
||||
|
||||
class HelloWindow : public RhiWindow
|
||||
{
|
||||
public:
|
||||
HelloWindow(QRhi::Implementation graphicsApi);
|
||||
|
||||
void customInit() override;
|
||||
void customRender() override;
|
||||
|
||||
private:
|
||||
void ensureFullscreenTexture(const QSize &pixelSize, QRhiResourceUpdateBatch *u);
|
||||
|
||||
std::unique_ptr<QRhiBuffer> m_vbuf;
|
||||
std::unique_ptr<QRhiBuffer> m_ubuf;
|
||||
std::unique_ptr<QRhiTexture> m_texture;
|
||||
std::unique_ptr<QRhiSampler> m_sampler;
|
||||
std::unique_ptr<QRhiShaderResourceBindings> m_colorTriSrb;
|
||||
std::unique_ptr<QRhiGraphicsPipeline> m_colorPipeline;
|
||||
std::unique_ptr<QRhiShaderResourceBindings> m_fullscreenQuadSrb;
|
||||
std::unique_ptr<QRhiGraphicsPipeline> m_fullscreenQuadPipeline;
|
||||
|
||||
QRhiResourceUpdateBatch *m_initialUpdates = nullptr;
|
||||
|
||||
float m_rotation = 0;
|
||||
float m_opacity = 1;
|
||||
int m_opacityDir = -1;
|
||||
};
|
||||
|
||||
#endif
|
4
examples/gui/rhiwindow/rhiwindow.pri
Normal file
4
examples/gui/rhiwindow/rhiwindow.pri
Normal file
@ -0,0 +1,4 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
SOURCES += $$PWD/rhiwindow.cpp
|
||||
HEADERS += $$PWD/rhiwindow.h
|
||||
RESOURCES += $$PWD/rhiwindow.qrc
|
9
examples/gui/rhiwindow/rhiwindow.pro
Normal file
9
examples/gui/rhiwindow/rhiwindow.pro
Normal file
@ -0,0 +1,9 @@
|
||||
include(rhiwindow.pri)
|
||||
|
||||
QT += gui-private
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/gui/rhiwindow
|
||||
INSTALLS += target
|
8
examples/gui/rhiwindow/rhiwindow.qrc
Normal file
8
examples/gui/rhiwindow/rhiwindow.qrc
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file alias="color.vert.qsb">shaders/prebuilt/color.vert.qsb</file>
|
||||
<file alias="color.frag.qsb">shaders/prebuilt/color.frag.qsb</file>
|
||||
<file alias="quad.vert.qsb">shaders/prebuilt/quad.vert.qsb</file>
|
||||
<file alias="quad.frag.qsb">shaders/prebuilt/quad.frag.qsb</file>
|
||||
</qresource>
|
||||
</RCC>
|
15
examples/gui/rhiwindow/shaders/color.frag
Normal file
15
examples/gui/rhiwindow/shaders/color.frag
Normal file
@ -0,0 +1,15 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 v_color;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(v_color * opacity, opacity);
|
||||
}
|
17
examples/gui/rhiwindow/shaders/color.vert
Normal file
17
examples/gui/rhiwindow/shaders/color.vert
Normal file
@ -0,0 +1,17 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
layout(location = 1) in vec3 color;
|
||||
|
||||
layout(location = 0) out vec3 v_color;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
v_color = color;
|
||||
gl_Position = mvp * position;
|
||||
}
|
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.frag.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.frag.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.vert.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.vert.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.frag.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.frag.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.vert.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.vert.qsb
Normal file
Binary file not shown.
11
examples/gui/rhiwindow/shaders/quad.frag
Normal file
11
examples/gui/rhiwindow/shaders/quad.frag
Normal file
@ -0,0 +1,11 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec2 v_uv;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(binding = 0) uniform sampler2D tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(tex, v_uv);
|
||||
fragColor = vec4(c.rgb * c.a, c.a);
|
||||
}
|
10
examples/gui/rhiwindow/shaders/quad.vert
Normal file
10
examples/gui/rhiwindow/shaders/quad.vert
Normal file
@ -0,0 +1,10 @@
|
||||
#version 440
|
||||
|
||||
layout (location = 0) out vec2 v_uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
// https://www.saschawillems.de/blog/2016/08/13/vulkan-tutorial-on-rendering-a-fullscreen-quad-without-buffers/
|
||||
v_uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(v_uv * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static std::optional<QDnsLookup::Type> typeFromParameter(QStringView type)
|
||||
{
|
||||
if (type.compare(u"a", Qt::CaseInsensitive) == 0)
|
||||
@ -218,7 +219,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
DnsManager manager;
|
||||
manager.setQuery(query);
|
||||
QTimer::singleShot(0, &manager, SLOT(execute()));
|
||||
QTimer::singleShot(0, &manager, &DnsManager::execute);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
/*!
|
||||
\example network-chat
|
||||
\title Network Chat Example
|
||||
\title Network Chat
|
||||
\ingroup examples-network
|
||||
\examplecategory {Networking}
|
||||
\meta tag {network,serialization}
|
||||
\brief Demonstrates a stateful peer-to-peer Chat client.
|
||||
|
||||
This example uses broadcasting with QUdpSocket and QNetworkInterface to
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user