6.5.3 clean
@ -8,7 +8,7 @@ if (NOT DEFINED QT_SUPERBUILD OR DEFINED QT_REPO_MODULE_VERSION)
|
|||||||
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
|
list(APPEND QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(QT_REPO_MODULE_VERSION "6.5.1")
|
set(QT_REPO_MODULE_VERSION "6.5.3")
|
||||||
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
|
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
|
||||||
|
|
||||||
set(QT_COPYRIGHT_YEAR "2023")
|
set(QT_COPYRIGHT_YEAR "2023")
|
||||||
|
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
|
||||||
* text=auto
|
|
@ -1 +1 @@
|
|||||||
QT_PACKAGEDATE_STR=2023-05-22
|
QT_PACKAGEDATE_STR=2023-09-25
|
2
.tag
@ -1 +1 @@
|
|||||||
55aee8697512af105dfefabc1e2ec41d4df1e45e
|
372eaedc5b8c771c46acc4c96e91bbade4ca3624
|
||||||
|
@ -40,11 +40,26 @@ function(qt_internal_check_if_path_has_symlinks path)
|
|||||||
endwhile()
|
endwhile()
|
||||||
endif()
|
endif()
|
||||||
if(is_symlink)
|
if(is_symlink)
|
||||||
message(FATAL_ERROR "The path \"${path}\" contains symlinks. \
|
set(possible_solutions_for_resolving_symlink [[
|
||||||
This is not supported. Possible solutions:
|
- Map directories using a transparent mechanism such as mount --bind
|
||||||
- map directories using a transparent mechanism such as mount --bind
|
- Pass the real path of the build directory to CMake, e.g. using
|
||||||
- pass the real path of the build directory to CMake, e.g. using \
|
cd $(realpath <path>) before invoking cmake <source_dir>.
|
||||||
cd $(realpath <path>) before invoking cmake <source_dir>.")
|
]])
|
||||||
|
if(QT_ALLOW_SYMLINK_IN_PATHS)
|
||||||
|
# In some cases, e.g., Homebrew, it is beneficial to skip this check.
|
||||||
|
# Before this, Homebrew had to patch this out to be able to get their build.
|
||||||
|
message(WARNING
|
||||||
|
"The path \"${path}\" contains symlinks. "
|
||||||
|
"This is not recommended, and it may lead to unexpected issues. If you do "
|
||||||
|
"not have a good reason for enabling 'QT_ALLOW_SYMLINK_IN_PATHS', disable "
|
||||||
|
"it, and follow one of the following solutions: \n"
|
||||||
|
"${possible_solutions_for_resolving_symlink} ")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The path \"${path}\" contains symlinks. "
|
||||||
|
"This is not supported. Possible solutions: \n"
|
||||||
|
"${possible_solutions_for_resolving_symlink} ")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}")
|
qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}")
|
||||||
|
@ -128,7 +128,8 @@ check_cxx_source_compiles("
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
int main(int, char **) {
|
int main(int, char **) {
|
||||||
EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0;
|
[[maybe_unused]] EGLint x = 0;
|
||||||
|
EGLDisplay dpy = 0; EGLContext ctx = 0;
|
||||||
eglDestroyContext(dpy, ctx);
|
eglDestroyContext(dpy, ctx);
|
||||||
}" HAVE_EGL)
|
}" HAVE_EGL)
|
||||||
|
|
||||||
|
@ -12,12 +12,24 @@ find_path(GSSAPI_INCLUDE_DIRS
|
|||||||
HINTS ${PC_GSSAPI_INCLUDEDIR}
|
HINTS ${PC_GSSAPI_INCLUDEDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# On macOS, vcpkg opts for finding frameworks LAST. This is generally fine;
|
||||||
|
# however, in the case of GSSAPI, `usr/lib/libgssapi_krb5.tbd` which is a
|
||||||
|
# symlink to `Kerberos.framework` misses a few symols, e.g.,
|
||||||
|
# `___gss_c_nt_hostbased_service_oid_desc`, and it causes build failure.
|
||||||
|
# So, we need to make sure that we find `GSS.framework`.
|
||||||
|
set(gssapi_library_names
|
||||||
|
GSS # framework
|
||||||
|
gss # solaris
|
||||||
|
gssapi # FreeBSD
|
||||||
|
gssapi_krb5
|
||||||
|
)
|
||||||
|
if(APPLE)
|
||||||
|
list(REMOVE_ITEM gssapi_library_names "gssapi_krb5")
|
||||||
|
endif()
|
||||||
|
|
||||||
find_library(GSSAPI_LIBRARIES
|
find_library(GSSAPI_LIBRARIES
|
||||||
NAMES
|
NAMES
|
||||||
GSS # framework
|
${gssapi_library_names}
|
||||||
gss # solaris
|
|
||||||
gssapi # FreeBSD
|
|
||||||
gssapi_krb5
|
|
||||||
HINTS ${PC_GSSAPI_LIBDIR}
|
HINTS ${PC_GSSAPI_LIBDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,4 +56,3 @@ mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
|
|||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
set_package_properties(GSSAPI PROPERTIES
|
set_package_properties(GSSAPI PROPERTIES
|
||||||
DESCRIPTION "Generic Security Services Application Program Interface")
|
DESCRIPTION "Generic Security Services Application Program Interface")
|
||||||
|
|
||||||
|
@ -18,9 +18,7 @@ find_package_handle_standard_args(PPS DEFAULT_MSG PPS_INCLUDE_DIR PPS_LIBRARY)
|
|||||||
mark_as_advanced(PPS_INCLUDE_DIR PPS_LIBRARY)
|
mark_as_advanced(PPS_INCLUDE_DIR PPS_LIBRARY)
|
||||||
|
|
||||||
if(PPS_FOUND)
|
if(PPS_FOUND)
|
||||||
add_library(__PPS INTERFACE IMPORTED)
|
add_library(PPS::PPS INTERFACE IMPORTED)
|
||||||
target_link_libraries(__PPS INTERFACE "${PPS_LIBRARY}")
|
target_link_libraries(PPS::PPS INTERFACE "${PPS_LIBRARY}")
|
||||||
target_include_directories(__PPS INTERFACE "${PPS_INCLUDE_DIR}")
|
target_include_directories(PPS::PPS INTERFACE "${PPS_INCLUDE_DIR}")
|
||||||
|
|
||||||
add_library(PPS::PPS ALIAS __PPS)
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -17,14 +17,18 @@ if (OpenGL_FOUND)
|
|||||||
|
|
||||||
add_library(WrapOpenGL::WrapOpenGL INTERFACE IMPORTED)
|
add_library(WrapOpenGL::WrapOpenGL INTERFACE IMPORTED)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
# CMake 3.27 and older:
|
||||||
# On Darwin platforms FindOpenGL sets IMPORTED_LOCATION to the absolute path of the library
|
# On Darwin platforms FindOpenGL sets IMPORTED_LOCATION to the absolute path of the library
|
||||||
# within the framework. This ends up as an absolute path link flag, which we don't want,
|
# within the framework. This ends up as an absolute path link flag, which we don't want,
|
||||||
# because that makes our .prl files un-relocatable.
|
# because that makes our .prl files un-relocatable.
|
||||||
# Extract the framework path instead, and use that in INTERFACE_LINK_LIBRARIES,
|
# Extract the framework path instead, and use that in INTERFACE_LINK_LIBRARIES,
|
||||||
# which CMake ends up transforming into a reloctable -framework flag.
|
# which CMake ends up transforming into a relocatable -framework flag.
|
||||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/20871 for details.
|
# See https://gitlab.kitware.com/cmake/cmake/-/issues/20871 for details.
|
||||||
|
#
|
||||||
|
# CMake 3.28 and above:
|
||||||
|
# IMPORTED_LOCATION is the absolute path the the OpenGL.framework folder.
|
||||||
get_target_property(__opengl_fw_lib_path OpenGL::GL IMPORTED_LOCATION)
|
get_target_property(__opengl_fw_lib_path OpenGL::GL IMPORTED_LOCATION)
|
||||||
if(__opengl_fw_lib_path)
|
if(__opengl_fw_lib_path AND NOT __opengl_fw_lib_path MATCHES "/([^/]+)\\.framework$")
|
||||||
get_filename_component(__opengl_fw_path "${__opengl_fw_lib_path}" DIRECTORY)
|
get_filename_component(__opengl_fw_path "${__opengl_fw_lib_path}" DIRECTORY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ function(qt_internal_add_app target)
|
|||||||
${arg_NO_UNITY_BUILD}
|
${arg_NO_UNITY_BUILD}
|
||||||
${forward_install_dir}
|
${forward_install_dir}
|
||||||
SOURCES ${arg_SOURCES}
|
SOURCES ${arg_SOURCES}
|
||||||
|
NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
|
||||||
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
${arg_INCLUDE_DIRECTORIES}
|
${arg_INCLUDE_DIRECTORIES}
|
||||||
|
@ -115,43 +115,38 @@ endfunction()
|
|||||||
|
|
||||||
|
|
||||||
function(qt_run_linker_version_script_support)
|
function(qt_run_linker_version_script_support)
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" "VERS_1 { global: sym; };
|
|
||||||
VERS_2 { global: sym; }
|
|
||||||
VERS_1;
|
|
||||||
")
|
|
||||||
if(DEFINED CMAKE_REQUIRED_FLAGS)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
|
|
||||||
else()
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "")
|
|
||||||
endif()
|
|
||||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/version_flag.map\"")
|
|
||||||
|
|
||||||
# Pass the linker that the main project uses to the version script compile test.
|
|
||||||
qt_internal_get_active_linker_flags(linker_flags)
|
|
||||||
if(linker_flags)
|
|
||||||
set(CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_cxx_source_compiles("int main(void){return 0;}" HAVE_LD_VERSION_SCRIPT)
|
|
||||||
if(DEFINED CMAKE_REQUIRED_FLAGS_SAVE)
|
|
||||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
|
|
||||||
endif()
|
|
||||||
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
|
|
||||||
|
|
||||||
# For some reason the linker command line written by the XCode generator, which is
|
# For some reason the linker command line written by the XCode generator, which is
|
||||||
# subsequently executed by xcodebuild, ignores the linker flag, and thus the test
|
# subsequently executed by xcodebuild, ignores the linker flag, and thus the test
|
||||||
# seemingly succeeds. Explicitly disable the version script test on darwin platforms.
|
# seemingly succeeds. Explicitly disable the version script test on darwin platforms.
|
||||||
if(APPLE)
|
|
||||||
set(HAVE_LD_VERSION_SCRIPT OFF)
|
|
||||||
endif()
|
|
||||||
# Also makes no sense with MSVC-style command-line
|
# Also makes no sense with MSVC-style command-line
|
||||||
if(MSVC)
|
if(NOT APPLE AND NOT MSVC)
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" [=[
|
||||||
|
VERS_1 { global: sym1; };
|
||||||
|
VERS_2 { global: sym2; } VERS_1;
|
||||||
|
]=])
|
||||||
|
set(CMAKE_REQUIRED_LINK_OPTIONS "")
|
||||||
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS
|
||||||
|
"-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/version_flag.map")
|
||||||
|
# Pass the linker that the main project uses to the version script compile test.
|
||||||
|
qt_internal_get_active_linker_flags(linker_flags)
|
||||||
|
if(linker_flags)
|
||||||
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags})
|
||||||
|
endif()
|
||||||
|
check_cxx_source_compiles([=[
|
||||||
|
int sym1;
|
||||||
|
int sym2;
|
||||||
|
int main(void) { return 0; }
|
||||||
|
]=] HAVE_LD_VERSION_SCRIPT)
|
||||||
|
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map")
|
||||||
|
else()
|
||||||
set(HAVE_LD_VERSION_SCRIPT OFF)
|
set(HAVE_LD_VERSION_SCRIPT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}" CACHE INTERNAL "linker version script support")
|
set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}"
|
||||||
|
CACHE INTERNAL "linker version script support")
|
||||||
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_ld_version_script)
|
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_ld_version_script)
|
||||||
set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported")
|
set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT}
|
||||||
|
CACHE INTERNAL "Test variables that should be exported")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(qt_internal_ensure_latest_win_nt_api)
|
function(qt_internal_ensure_latest_win_nt_api)
|
||||||
|
@ -101,7 +101,8 @@ if(MACOS AND QT_IS_MACOS_UNIVERSAL
|
|||||||
QT_FEATURE_x86intrin)
|
QT_FEATURE_x86intrin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MACOS AND QT_IS_MACOS_UNIVERSAL AND __qt_osx_first_arch STREQUAL "x86_64")
|
if(MACOS AND QT_IS_MACOS_UNIVERSAL AND
|
||||||
|
(__qt_osx_first_arch STREQUAL "x86_64" OR __qt_osx_first_arch STREQUAL "x86_64h"))
|
||||||
set(QT_FORCE_FEATURE_neon ON CACHE INTERNAL "Force enable neon due to platform requirements.")
|
set(QT_FORCE_FEATURE_neon ON CACHE INTERNAL "Force enable neon due to platform requirements.")
|
||||||
set(__QtFeature_custom_enabled_cache_variables
|
set(__QtFeature_custom_enabled_cache_variables
|
||||||
TEST_subarch_neon
|
TEST_subarch_neon
|
||||||
@ -373,6 +374,10 @@ qt_copy_or_install(DIRECTORY cmake/
|
|||||||
FILES_MATCHING PATTERN "Find*.cmake"
|
FILES_MATCHING PATTERN "Find*.cmake"
|
||||||
PATTERN "tests" EXCLUDE
|
PATTERN "tests" EXCLUDE
|
||||||
PATTERN "3rdparty" EXCLUDE
|
PATTERN "3rdparty" EXCLUDE
|
||||||
|
PATTERN "macos" EXCLUDE
|
||||||
|
PATTERN "ios" EXCLUDE
|
||||||
|
PATTERN "platforms" EXCLUDE
|
||||||
|
PATTERN "QtBuildInternals" EXCLUDE
|
||||||
)
|
)
|
||||||
|
|
||||||
# In prefix builds we also need to copy the files into the build config directory, so that the
|
# In prefix builds we also need to copy the files into the build config directory, so that the
|
||||||
@ -383,6 +388,10 @@ if(QT_WILL_INSTALL)
|
|||||||
FILES_MATCHING PATTERN "Find*.cmake"
|
FILES_MATCHING PATTERN "Find*.cmake"
|
||||||
PATTERN "tests" EXCLUDE
|
PATTERN "tests" EXCLUDE
|
||||||
PATTERN "3rdparty" EXCLUDE
|
PATTERN "3rdparty" EXCLUDE
|
||||||
|
PATTERN "macos" EXCLUDE
|
||||||
|
PATTERN "ios" EXCLUDE
|
||||||
|
PATTERN "platforms" EXCLUDE
|
||||||
|
PATTERN "QtBuildInternals" EXCLUDE
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -284,21 +284,21 @@ if(WIN32)
|
|||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64)
|
list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64)
|
||||||
endif()
|
endif()
|
||||||
if(MSVC)
|
|
||||||
if (CLANG)
|
if(CLANG)
|
||||||
|
if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR MSVC)
|
||||||
set(QT_DEFAULT_MKSPEC win32-clang-msvc)
|
set(QT_DEFAULT_MKSPEC win32-clang-msvc)
|
||||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
elseif(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" OR MINGW)
|
||||||
|
set(QT_DEFAULT_MKSPEC win32-clang-g++)
|
||||||
|
endif()
|
||||||
|
elseif(MSVC)
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||||
set(QT_DEFAULT_MKSPEC win32-arm64-msvc)
|
set(QT_DEFAULT_MKSPEC win32-arm64-msvc)
|
||||||
else()
|
else()
|
||||||
set(QT_DEFAULT_MKSPEC win32-msvc)
|
set(QT_DEFAULT_MKSPEC win32-msvc)
|
||||||
endif()
|
endif()
|
||||||
elseif(CLANG AND MINGW)
|
|
||||||
set(QT_DEFAULT_MKSPEC win32-clang-g++)
|
|
||||||
elseif(MINGW)
|
elseif(MINGW)
|
||||||
set(QT_DEFAULT_MKSPEC win32-g++)
|
set(QT_DEFAULT_MKSPEC win32-g++)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MINGW)
|
|
||||||
list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1)
|
list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1)
|
||||||
endif()
|
endif()
|
||||||
elseif(LINUX)
|
elseif(LINUX)
|
||||||
@ -376,15 +376,23 @@ else()
|
|||||||
set(QT_QMAKE_HOST_MKSPEC "${QT_QMAKE_TARGET_MKSPEC}")
|
set(QT_QMAKE_HOST_MKSPEC "${QT_QMAKE_TARGET_MKSPEC}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}")
|
if(NOT QT_QMAKE_TARGET_MKSPEC OR NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}")
|
||||||
|
if(NOT QT_QMAKE_TARGET_MKSPEC)
|
||||||
|
set(reason "Platform is not detected. Please make sure your build environment is configured"
|
||||||
|
" properly or specify it manually using QT_QMAKE_TARGET_MKSPEC variable and one of the"
|
||||||
|
" known platforms.")
|
||||||
|
else()
|
||||||
|
set(reason "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}")
|
||||||
|
endif()
|
||||||
|
|
||||||
file(GLOB known_platforms
|
file(GLOB known_platforms
|
||||||
LIST_DIRECTORIES true
|
LIST_DIRECTORIES true
|
||||||
RELATIVE "${QT_MKSPECS_DIR}"
|
RELATIVE "${QT_MKSPECS_DIR}"
|
||||||
"${QT_MKSPECS_DIR}/*"
|
"${QT_MKSPECS_DIR}/*"
|
||||||
)
|
)
|
||||||
list(JOIN known_platforms "\n " known_platforms)
|
list(JOIN known_platforms "\n " known_platforms)
|
||||||
message(FATAL_ERROR "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}\n\
|
message(FATAL_ERROR "${reason}\n"
|
||||||
Known platforms:\n ${known_platforms}")
|
"Known platforms:\n ${known_platforms}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT DEFINED QT_DEFAULT_PLATFORM_DEFINITIONS)
|
if(NOT DEFINED QT_DEFAULT_PLATFORM_DEFINITIONS)
|
||||||
@ -459,6 +467,7 @@ set(__default_private_args
|
|||||||
DISABLE_AUTOGEN_TOOLS
|
DISABLE_AUTOGEN_TOOLS
|
||||||
ENABLE_AUTOGEN_TOOLS
|
ENABLE_AUTOGEN_TOOLS
|
||||||
PLUGIN_TYPES
|
PLUGIN_TYPES
|
||||||
|
NO_PCH_SOURCES
|
||||||
NO_UNITY_BUILD_SOURCES
|
NO_UNITY_BUILD_SOURCES
|
||||||
)
|
)
|
||||||
set(__default_public_args
|
set(__default_public_args
|
||||||
|
@ -109,7 +109,7 @@ from the build directory")
|
|||||||
set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE)
|
set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
if(QT_SUPERBUILD)
|
if(QT_SUPERBUILD)
|
||||||
qt_internal_save_previously_found_packages()
|
qt_internal_save_previously_visited_packages()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -308,24 +308,19 @@ function(qt_build_internals_add_toplevel_targets)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
macro(qt_enable_cmake_languages)
|
macro(qt_enable_cmake_languages)
|
||||||
include(CheckLanguage)
|
|
||||||
set(__qt_required_language_list C CXX)
|
set(__qt_required_language_list C CXX)
|
||||||
set(__qt_optional_language_list )
|
set(__qt_platform_required_language_list )
|
||||||
|
|
||||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/20545
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
list(APPEND __qt_optional_language_list OBJC OBJCXX)
|
list(APPEND __qt_platform_required_language_list OBJC OBJCXX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(__qt_lang ${__qt_required_language_list})
|
foreach(__qt_lang ${__qt_required_language_list})
|
||||||
enable_language(${__qt_lang})
|
enable_language(${__qt_lang})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach(__qt_lang ${__qt_optional_language_list})
|
foreach(__qt_lang ${__qt_platform_required_language_list})
|
||||||
check_language(${__qt_lang})
|
enable_language(${__qt_lang})
|
||||||
if(CMAKE_${__qt_lang}_COMPILER)
|
|
||||||
enable_language(${__qt_lang})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# The qtbase call is handled in qtbase/CMakeLists.txt.
|
# The qtbase call is handled in qtbase/CMakeLists.txt.
|
||||||
@ -434,6 +429,12 @@ macro(qt_build_repo_begin)
|
|||||||
add_custom_target(sync_headers)
|
add_custom_target(sync_headers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# The special target that we use to sync 3rd-party headers before the gn run when building
|
||||||
|
# qtwebengine in top-level builds.
|
||||||
|
if(NOT TARGET thirdparty_sync_headers)
|
||||||
|
add_custom_target(thirdparty_sync_headers)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets.
|
# Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets.
|
||||||
# Internal executables will add a dependency on the qpa_default_plugins target,
|
# Internal executables will add a dependency on the qpa_default_plugins target,
|
||||||
# so that building and running a test ensures it won't fail at runtime due to a missing qpa
|
# so that building and running a test ensures it won't fail at runtime due to a missing qpa
|
||||||
@ -562,7 +563,7 @@ macro(qt_build_repo_end)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT QT_SUPERBUILD)
|
if(NOT QT_SUPERBUILD)
|
||||||
qt_internal_save_previously_found_packages()
|
qt_internal_save_previously_visited_packages()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(QT_INTERNAL_FRESH_REQUESTED)
|
if(QT_INTERNAL_FRESH_REQUESTED)
|
||||||
@ -1415,3 +1416,13 @@ function(qt_internal_run_common_config_tests)
|
|||||||
qt_internal_check_cmp0099_available()
|
qt_internal_check_cmp0099_available()
|
||||||
qt_configure_end_summary_section()
|
qt_configure_end_summary_section()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# It is used in QtWebEngine to replace the REALPATH with ABSOLUTE path, which is
|
||||||
|
# useful for building Qt in Homebrew.
|
||||||
|
function(qt_internal_get_filename_path_mode out_var)
|
||||||
|
set(mode REALPATH)
|
||||||
|
if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS)
|
||||||
|
set(mode ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
set(${out_var} ${mode} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
@ -124,5 +124,5 @@ endif()
|
|||||||
# Emscripten Clang
|
# Emscripten Clang
|
||||||
if(WASM)
|
if(WASM)
|
||||||
set(QT_CFLAGS_OPTIMIZE_DEBUG "-O2 -g") # -Og is not supported
|
set(QT_CFLAGS_OPTIMIZE_DEBUG "-O2 -g") # -Og is not supported
|
||||||
set(QT_CFLAGS_SSE2 -O2 -msimd128 -msse -msse2)
|
set(QT_CFLAGS_SSE2 "-O2 -msimd128 -msse -msse2")
|
||||||
endif()
|
endif()
|
||||||
|
@ -30,6 +30,7 @@ function(qt_internal_add_executable name)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
_qt_internal_create_executable(${name})
|
_qt_internal_create_executable(${name})
|
||||||
|
qt_internal_mark_as_internal_target(${name})
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
_qt_internal_android_executable_finalizer(${name})
|
_qt_internal_android_executable_finalizer(${name})
|
||||||
endif()
|
endif()
|
||||||
@ -119,6 +120,7 @@ function(qt_internal_add_executable name)
|
|||||||
qt_internal_extend_target("${name}"
|
qt_internal_extend_target("${name}"
|
||||||
${arg_NO_UNITY_BUILD}
|
${arg_NO_UNITY_BUILD}
|
||||||
SOURCES ${arg_SOURCES}
|
SOURCES ${arg_SOURCES}
|
||||||
|
NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
|
||||||
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
||||||
INCLUDE_DIRECTORIES ${private_includes}
|
INCLUDE_DIRECTORIES ${private_includes}
|
||||||
DEFINES ${arg_DEFINES}
|
DEFINES ${arg_DEFINES}
|
||||||
@ -369,6 +371,7 @@ function(qt_internal_add_configure_time_executable target)
|
|||||||
set(target_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/configure_time_bins")
|
set(target_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/configure_time_bins")
|
||||||
if(arg_CONFIG)
|
if(arg_CONFIG)
|
||||||
set(CMAKE_TRY_COMPILE_CONFIGURATION "${arg_CONFIG}")
|
set(CMAKE_TRY_COMPILE_CONFIGURATION "${arg_CONFIG}")
|
||||||
|
string(TOUPPER "_${arg_CONFIG}" config_suffix)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
||||||
@ -462,6 +465,29 @@ function(qt_internal_add_configure_time_executable target)
|
|||||||
set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
|
set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY)
|
configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY)
|
||||||
|
|
||||||
|
qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
|
||||||
|
foreach(lang IN LISTS enabled_languages)
|
||||||
|
set(compiler_flags_var "CMAKE_${lang}_FLAGS")
|
||||||
|
list(APPEND cmake_flags_arg "-D${compiler_flags_var}:STRING=${${compiler_flags_var}}")
|
||||||
|
if(arg_CONFIG)
|
||||||
|
set(compiler_flags_var_config "${compiler_flags_var}${config_suffix}")
|
||||||
|
list(APPEND cmake_flags_arg
|
||||||
|
"-D${compiler_flags_var_config}:STRING=${${compiler_flags_var_config}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
qt_internal_get_target_link_types_for_flag_manipulation(target_link_types)
|
||||||
|
foreach(linker_type IN LISTS target_link_types)
|
||||||
|
set(linker_flags_var "CMAKE_${linker_type}_LINKER_FLAGS")
|
||||||
|
list(APPEND cmake_flags_arg "-D${linker_flags_var}:STRING=${${linker_flags_var}}")
|
||||||
|
if(arg_CONFIG)
|
||||||
|
set(linker_flags_var_config "${linker_flags_var}${config_suffix}")
|
||||||
|
list(APPEND cmake_flags_arg
|
||||||
|
"-D${linker_flags_var_config}:STRING=${${linker_flags_var_config}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
try_compile(result
|
try_compile(result
|
||||||
"${target_binary_dir}"
|
"${target_binary_dir}"
|
||||||
"${target_binary_dir}"
|
"${target_binary_dir}"
|
||||||
|
@ -41,10 +41,13 @@ macro(qt_find_package)
|
|||||||
# Due to this behavior being different from what general CMake projects expect, it is only
|
# Due to this behavior being different from what general CMake projects expect, it is only
|
||||||
# done for -developer-builds.
|
# done for -developer-builds.
|
||||||
if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND
|
if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND
|
||||||
NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES)
|
NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES
|
||||||
|
AND "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES)
|
||||||
set(_qt_find_package_skip_find_package TRUE)
|
set(_qt_find_package_skip_find_package TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set_property(GLOBAL APPEND PROPERTY _qt_previously_searched_packages "${ARGV0}")
|
||||||
|
|
||||||
if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS)
|
if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS)
|
||||||
set(_qt_find_package_skip_find_package TRUE)
|
set(_qt_find_package_skip_find_package TRUE)
|
||||||
foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS})
|
foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS})
|
||||||
@ -221,7 +224,7 @@ endmacro()
|
|||||||
# Only applies to -developer-builds by default.
|
# Only applies to -developer-builds by default.
|
||||||
# Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES.
|
# Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES.
|
||||||
# Opting out will need two reconfigurations to take effect.
|
# Opting out will need two reconfigurations to take effect.
|
||||||
function(qt_internal_save_previously_found_packages)
|
function(qt_internal_save_previously_visited_packages)
|
||||||
if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES)
|
if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES)
|
||||||
set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}")
|
set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}")
|
||||||
else()
|
else()
|
||||||
@ -235,6 +238,7 @@ function(qt_internal_save_previously_found_packages)
|
|||||||
if(NOT should_save)
|
if(NOT should_save)
|
||||||
# When the value is flipped to OFF, remove any previously saved packages.
|
# When the value is flipped to OFF, remove any previously saved packages.
|
||||||
unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE)
|
unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE)
|
||||||
|
unset(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES CACHE)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -244,6 +248,15 @@ function(qt_internal_save_previously_found_packages)
|
|||||||
set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL
|
set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL
|
||||||
"List of CMake packages found during configuration using qt_find_package.")
|
"List of CMake packages found during configuration using qt_find_package.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
get_property(_qt_previously_searched_packages GLOBAL PROPERTY _qt_previously_searched_packages)
|
||||||
|
if(_qt_previously_searched_packages)
|
||||||
|
list(REMOVE_DUPLICATES _qt_previously_searched_packages)
|
||||||
|
set(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES
|
||||||
|
"${_qt_previously_searched_packages}" CACHE INTERNAL
|
||||||
|
"List of CMake packages searched during configuration using qt_find_package."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan".
|
# Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan".
|
||||||
|
@ -33,22 +33,15 @@ function(qt_internal_add_linker_version_script target)
|
|||||||
endif()
|
endif()
|
||||||
string(APPEND contents "};\n")
|
string(APPEND contents "};\n")
|
||||||
set(current "Qt_${PROJECT_VERSION_MAJOR}")
|
set(current "Qt_${PROJECT_VERSION_MAJOR}")
|
||||||
if (QT_NAMESPACE STREQUAL "")
|
|
||||||
set(tag_symbol "qt_version_tag")
|
|
||||||
else()
|
|
||||||
set(tag_symbol "qt_version_tag_${QT_NAMESPACE}")
|
|
||||||
endif()
|
|
||||||
string(APPEND contents "${current} { *; };\n")
|
string(APPEND contents "${current} { *; };\n")
|
||||||
|
|
||||||
foreach(minor_version RANGE ${PROJECT_VERSION_MINOR})
|
get_target_property(type ${target} TYPE)
|
||||||
set(previous "${current}")
|
if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
|
||||||
set(current "Qt_${PROJECT_VERSION_MAJOR}.${minor_version}")
|
set(property_genex "$<TARGET_PROPERTY:${target},_qt_extra_linker_script_content>")
|
||||||
if (minor_version EQUAL ${PROJECT_VERSION_MINOR})
|
set(check_genex "$<BOOL:${property_genex}>")
|
||||||
string(APPEND contents "${current} { ${tag_symbol}; } ${previous};\n")
|
string(APPEND contents
|
||||||
else()
|
"$<${check_genex}:${property_genex}>")
|
||||||
string(APPEND contents "${current} {} ${previous};\n")
|
endif()
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(infile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.in")
|
set(infile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.in")
|
||||||
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version")
|
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version")
|
||||||
@ -87,6 +80,11 @@ function(qt_internal_add_link_flags_no_undefined target)
|
|||||||
if (NOT QT_BUILD_SHARED_LIBS OR WASM)
|
if (NOT QT_BUILD_SHARED_LIBS OR WASM)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||||
|
# ld64 defaults to -undefined,error, and in Xcode 15
|
||||||
|
# passing this option is deprecated, causing a warning.
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
if ((GCC OR CLANG) AND NOT MSVC)
|
if ((GCC OR CLANG) AND NOT MSVC)
|
||||||
if(CLANG AND QT_FEATURE_sanitizer)
|
if(CLANG AND QT_FEATURE_sanitizer)
|
||||||
return()
|
return()
|
||||||
@ -124,11 +122,20 @@ endfunction()
|
|||||||
|
|
||||||
function(qt_internal_apply_gc_binaries target visibility)
|
function(qt_internal_apply_gc_binaries target visibility)
|
||||||
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
|
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
|
||||||
list(FIND possible_visibilities "${visibility}" known_visibility)
|
if(NOT visibility IN_LIST possible_visibilities)
|
||||||
if (known_visibility EQUAL "-1")
|
|
||||||
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
|
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
string(JOIN "" clang_or_gcc_begin
|
||||||
|
"$<$<OR:"
|
||||||
|
"$<CXX_COMPILER_ID:GNU>,"
|
||||||
|
"$<CXX_COMPILER_ID:Clang>,"
|
||||||
|
"$<CXX_COMPILER_ID:AppleClang>,"
|
||||||
|
"$<CXX_COMPILER_ID:IntelLLVM>"
|
||||||
|
">:"
|
||||||
|
)
|
||||||
|
set(clang_or_gcc_end ">")
|
||||||
|
|
||||||
if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
|
if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(gc_sections_flag "-Wl,-dead_strip")
|
set(gc_sections_flag "-Wl,-dead_strip")
|
||||||
@ -137,16 +144,26 @@ function(qt_internal_apply_gc_binaries target visibility)
|
|||||||
elseif(LINUX OR BSD OR WIN32 OR ANDROID)
|
elseif(LINUX OR BSD OR WIN32 OR ANDROID)
|
||||||
set(gc_sections_flag "-Wl,--gc-sections")
|
set(gc_sections_flag "-Wl,--gc-sections")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Save the flag value with and without genex wrapping, so we can remove the wrapping
|
||||||
|
# when generating .pc pkgconfig files.
|
||||||
|
set_property(GLOBAL PROPERTY _qt_internal_gc_sections_without_genex "${gc_sections_flag}")
|
||||||
|
|
||||||
|
set(gc_sections_flag
|
||||||
|
"${clang_or_gcc_begin}${gc_sections_flag}${clang_or_gcc_end}")
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY _qt_internal_gc_sections_with_genex "${gc_sections_flag}")
|
||||||
endif()
|
endif()
|
||||||
if(gc_sections_flag)
|
if(gc_sections_flag)
|
||||||
target_link_options("${target}" ${visibility} "${gc_sections_flag}")
|
target_link_options("${target}" ${visibility} "${gc_sections_flag}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
|
if((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
|
||||||
set(split_sections_flags "-ffunction-sections" "-fdata-sections")
|
set(split_sections_flags
|
||||||
|
"${clang_or_gcc_begin}-ffunction-sections;-fdata-sections${clang_or_gcc_end}")
|
||||||
endif()
|
endif()
|
||||||
if(split_sections_flags)
|
if(split_sections_flags)
|
||||||
target_compile_options("${target}" ${visibility} ${split_sections_flags})
|
target_compile_options("${target}" ${visibility} "${split_sections_flags}")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@ -156,13 +173,17 @@ function(qt_internal_apply_intel_cet target visibility)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
|
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
|
||||||
list(FIND possible_visibilities "${visibility}" known_visibility)
|
if(NOT visibility IN_LIST possible_visibilities)
|
||||||
if (known_visibility EQUAL "-1")
|
|
||||||
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
|
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(GCC)
|
if(GCC)
|
||||||
set(flags "-mshstk")
|
string(JOIN "" flags
|
||||||
|
"$<$<OR:"
|
||||||
|
"$<CXX_COMPILER_ID:GNU>,"
|
||||||
|
"$<CXX_COMPILER_ID:Clang>,"
|
||||||
|
"$<CXX_COMPILER_ID:AppleClang>"
|
||||||
|
">:-mshstk>")
|
||||||
endif()
|
endif()
|
||||||
if(flags)
|
if(flags)
|
||||||
target_compile_options("${target}" ${visibility} "${flags}")
|
target_compile_options("${target}" ${visibility} "${flags}")
|
||||||
@ -287,14 +308,15 @@ function(qt_set_msvc_cplusplus_options target visibility)
|
|||||||
# Check qt_config_compile_test for more info.
|
# Check qt_config_compile_test for more info.
|
||||||
if(MSVC AND MSVC_VERSION GREATER_EQUAL 1913)
|
if(MSVC AND MSVC_VERSION GREATER_EQUAL 1913)
|
||||||
set(flags "-Zc:__cplusplus" "-permissive-")
|
set(flags "-Zc:__cplusplus" "-permissive-")
|
||||||
target_compile_options("${target}" ${visibility} "$<$<COMPILE_LANGUAGE:CXX>:${flags}>")
|
target_compile_options("${target}" ${visibility}
|
||||||
|
"$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<COMPILE_LANGUAGE:CXX>>:${flags}>")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(qt_enable_utf8_sources target)
|
function(qt_enable_utf8_sources target)
|
||||||
set(utf8_flags "")
|
set(utf8_flags "")
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
list(APPEND utf8_flags "-utf-8")
|
list(APPEND utf8_flags "$<$<CXX_COMPILER_ID:MSVC>:-utf-8>")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(utf8_flags)
|
if(utf8_flags)
|
||||||
@ -557,12 +579,20 @@ endfunction()
|
|||||||
|
|
||||||
# Removes specified flags from CMAKE_<LANGUAGES>_FLAGS[_CONFIGS] variables
|
# Removes specified flags from CMAKE_<LANGUAGES>_FLAGS[_CONFIGS] variables
|
||||||
#
|
#
|
||||||
# IN_CACHE enables flags removal from CACHE
|
# Option Arguments:
|
||||||
# CONFIGS list of configurations that need to clear flags. Clears all configs by default if not
|
# IN_CACHE
|
||||||
# specified.
|
# Enables flags removal from CACHE
|
||||||
# LANGUAGES list of LANGUAGES that need clear flags. Clears all languages by default if not
|
# REGEX
|
||||||
# specified.
|
# Enables the flag processing as a regular expression.
|
||||||
# REGEX enables the flag processing as a regular expression.
|
#
|
||||||
|
# Multi-value Arguments:
|
||||||
|
# CONFIGS
|
||||||
|
# List of configurations that need to clear flags. Clears all configs by default if not
|
||||||
|
# specified.
|
||||||
|
#
|
||||||
|
# LANGUAGES
|
||||||
|
# List of LANGUAGES that need clear flags. Clears all languages by default if not
|
||||||
|
# specified.
|
||||||
function(qt_internal_remove_compiler_flags flags)
|
function(qt_internal_remove_compiler_flags flags)
|
||||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||||
"IN_CACHE;REGEX"
|
"IN_CACHE;REGEX"
|
||||||
@ -585,8 +615,7 @@ function(qt_internal_remove_compiler_flags flags)
|
|||||||
if(arg_CONFIGS)
|
if(arg_CONFIGS)
|
||||||
set(configs "${arg_CONFIGS}")
|
set(configs "${arg_CONFIGS}")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR
|
qt_internal_get_configs_for_flag_manipulation(configs)
|
||||||
"You must specify at least one configuration for which to remove the flags.")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(arg_REGEX)
|
if(arg_REGEX)
|
||||||
@ -992,14 +1021,42 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
|
|||||||
IN_CACHE)
|
IN_CACHE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Legacy Android toolchain file adds the `-g` flag to CMAKE_<LANG>_FLAGS, as a
|
||||||
|
# result, our release build ends up containing debug symbols. To avoid that, we
|
||||||
|
# remove the flag from CMAKE_<LANGL>_FLAGS and add
|
||||||
|
# it to CMAKE_<LANG>_FLAGS_DEBUG.
|
||||||
|
#
|
||||||
|
# Note:
|
||||||
|
# The new `android.toolchain.cmake` file does not have this problem, but
|
||||||
|
# it has other issues, eg., https://github.com/android/ndk/issues/1693, so we
|
||||||
|
# cannot force it. While we do load the new toolchain, it automatically falls
|
||||||
|
# back to the legacy toolchain, ie., `android-legacy.toolchain.cmake` which
|
||||||
|
# has the problem described above.
|
||||||
|
#
|
||||||
|
# Todo:
|
||||||
|
# When the new toolchain is fixed, and it doesn't fall back to the legacy
|
||||||
|
# anymore by default, then we should be able to remove this workaround.
|
||||||
|
if(ANDROID AND ANDROID_COMPILER_FLAGS MATCHES "(^| )-g")
|
||||||
|
qt_internal_remove_compiler_flags("-g")
|
||||||
|
qt_internal_add_compiler_flags(FLAGS "-g" CONFIGS DEBUG RELWITHDEBINFO)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Update all relevant flags in the calling scope
|
# Update all relevant flags in the calling scope
|
||||||
foreach(config ${configs})
|
foreach(lang ${enabled_languages})
|
||||||
foreach(lang ${enabled_languages})
|
set(flag_var_name "CMAKE_${lang}_FLAGS")
|
||||||
|
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
||||||
|
|
||||||
|
foreach(config ${configs})
|
||||||
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
|
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
|
||||||
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
foreach(t ${target_link_types})
|
foreach(t ${target_link_types})
|
||||||
|
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS")
|
||||||
|
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
||||||
|
|
||||||
|
foreach(config ${configs})
|
||||||
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
|
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
|
||||||
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
@ -185,6 +185,9 @@ function(qt_internal_add_headersclean_target module_target module_headers)
|
|||||||
# <windows.h> and <GL.h> violate the standards.
|
# <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)
|
||||||
|
|
||||||
|
# Because we now add `-DNOMINMAX` to `PlatformCommonInternal`.
|
||||||
|
set(hcleanUDEFS -UNOMINMAX)
|
||||||
|
|
||||||
# cl.exe needs a source path
|
# cl.exe needs a source path
|
||||||
get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH)
|
get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH)
|
||||||
|
|
||||||
@ -195,6 +198,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
|
|||||||
"${hcleanFLAGS}"
|
"${hcleanFLAGS}"
|
||||||
"${target_includes_joined_genex}"
|
"${target_includes_joined_genex}"
|
||||||
"${hcleanDEFS}"
|
"${hcleanDEFS}"
|
||||||
|
"${hcleanUDEFS}"
|
||||||
)
|
)
|
||||||
string(JOIN " " compiler_command_line_variables
|
string(JOIN " " compiler_command_line_variables
|
||||||
"-FI"
|
"-FI"
|
||||||
@ -227,7 +231,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
|
|||||||
file(GENERATE OUTPUT "${headers_check_parameters}"
|
file(GENERATE OUTPUT "${headers_check_parameters}"
|
||||||
CONTENT "${headers_check_parameters_content}")
|
CONTENT "${headers_check_parameters_content}")
|
||||||
|
|
||||||
set(sync_headers_dep "sync_headers")
|
set(sync_headers_dep "${module_target}_sync_headers")
|
||||||
|
|
||||||
foreach(header ${hclean_headers})
|
foreach(header ${hclean_headers})
|
||||||
# We need realpath here to make sure path starts with drive letter
|
# We need realpath here to make sure path starts with drive letter
|
||||||
|
@ -102,7 +102,7 @@ function(qt_internal_add_global_definition definition)
|
|||||||
set(optional_args)
|
set(optional_args)
|
||||||
set(single_value_args VALUE)
|
set(single_value_args VALUE)
|
||||||
set(multi_value_args SCOPE)
|
set(multi_value_args SCOPE)
|
||||||
cmake_parse_arguments(args
|
cmake_parse_arguments(arg
|
||||||
"${optional_args}"
|
"${optional_args}"
|
||||||
"${single_value_args}"
|
"${single_value_args}"
|
||||||
"${multi_value_args}"
|
"${multi_value_args}"
|
||||||
@ -168,6 +168,8 @@ if(WIN32)
|
|||||||
# Needed for M_PI define. Same as mkspecs/features/qt_module.prf.
|
# Needed for M_PI define. Same as mkspecs/features/qt_module.prf.
|
||||||
# It's set for every module being built, but it's not propagated to user apps.
|
# It's set for every module being built, but it's not propagated to user apps.
|
||||||
target_compile_definitions(PlatformModuleInternal INTERFACE _USE_MATH_DEFINES)
|
target_compile_definitions(PlatformModuleInternal INTERFACE _USE_MATH_DEFINES)
|
||||||
|
# Not disabling min/max macros may result in unintended substitutions of std::min/max
|
||||||
|
target_compile_definitions(PlatformCommonInternal INTERFACE NOMINMAX)
|
||||||
endif()
|
endif()
|
||||||
if(FEATURE_largefile AND UNIX)
|
if(FEATURE_largefile AND UNIX)
|
||||||
target_compile_definitions(PlatformCommonInternal
|
target_compile_definitions(PlatformCommonInternal
|
||||||
@ -205,6 +207,14 @@ function(qt_internal_apply_bitcode_flags target)
|
|||||||
target_compile_options("${target}" INTERFACE ${bitcode_flags})
|
target_compile_options("${target}" INTERFACE ${bitcode_flags})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# Function guards linker options that are applicable for internal Qt targets only from propagating
|
||||||
|
# them to user projects.
|
||||||
|
function(qt_internal_platform_link_options target scope)
|
||||||
|
set(options ${ARGN})
|
||||||
|
set(is_internal_target_genex "$<BOOL:$<TARGET_PROPERTY:_qt_is_internal_target>>")
|
||||||
|
target_link_options(${target} ${scope} "$<${is_internal_target_genex}:${options}>")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# Apple deprecated the entire OpenGL API in favor of Metal, which
|
# Apple deprecated the entire OpenGL API in favor of Metal, which
|
||||||
# we are aware of, so silence the deprecation warnings in code.
|
# we are aware of, so silence the deprecation warnings in code.
|
||||||
# This does not apply to user-code, which will need to silence
|
# This does not apply to user-code, which will need to silence
|
||||||
@ -283,7 +293,7 @@ if (MSVC)
|
|||||||
$<$<NOT:$<CONFIG:Debug>>:-guard:cf -Gw>
|
$<$<NOT:$<CONFIG:Debug>>:-guard:cf -Gw>
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_options(PlatformCommonInternal INTERFACE
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
|
||||||
-DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE
|
-DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE
|
||||||
$<$<NOT:$<CONFIG:Debug>>:-OPT:REF -OPT:ICF -GUARD:CF>
|
$<$<NOT:$<CONFIG:Debug>>:-OPT:REF -OPT:ICF -GUARD:CF>
|
||||||
)
|
)
|
||||||
@ -299,7 +309,7 @@ endif()
|
|||||||
|
|
||||||
if(QT_FEATURE_intelcet)
|
if(QT_FEATURE_intelcet)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_link_options(PlatformCommonInternal INTERFACE
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
|
||||||
-CETCOMPAT
|
-CETCOMPAT
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
@ -328,30 +338,31 @@ endif()
|
|||||||
if(DEFINED QT_EXTRA_FRAMEWORKPATHS AND APPLE)
|
if(DEFINED QT_EXTRA_FRAMEWORKPATHS AND APPLE)
|
||||||
list(TRANSFORM QT_EXTRA_FRAMEWORKPATHS PREPEND "-F" OUTPUT_VARIABLE __qt_fw_flags)
|
list(TRANSFORM QT_EXTRA_FRAMEWORKPATHS PREPEND "-F" OUTPUT_VARIABLE __qt_fw_flags)
|
||||||
target_compile_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
|
target_compile_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
|
||||||
target_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
|
||||||
unset(__qt_fw_flags)
|
unset(__qt_fw_flags)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt_internal_get_active_linker_flags(__qt_internal_active_linker_flags)
|
qt_internal_get_active_linker_flags(__qt_internal_active_linker_flags)
|
||||||
if(__qt_internal_active_linker_flags)
|
if(__qt_internal_active_linker_flags)
|
||||||
target_link_options(PlatformCommonInternal INTERFACE "${__qt_internal_active_linker_flags}")
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
|
||||||
|
"${__qt_internal_active_linker_flags}")
|
||||||
endif()
|
endif()
|
||||||
unset(__qt_internal_active_linker_flags)
|
unset(__qt_internal_active_linker_flags)
|
||||||
|
|
||||||
if(QT_FEATURE_enable_gdb_index)
|
if(QT_FEATURE_enable_gdb_index)
|
||||||
target_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index")
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(QT_FEATURE_enable_new_dtags)
|
if(QT_FEATURE_enable_new_dtags)
|
||||||
target_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags")
|
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
function(qt_get_implicit_sse2_genex_condition out_var)
|
function(qt_get_implicit_sse2_genex_condition out_var)
|
||||||
set(is_shared_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>")
|
set(is_shared_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>")
|
||||||
set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>")
|
set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>")
|
||||||
set(is_static_qt_build "$<NOT:$<BOOL:${QT_BUILD_SHARED_LIBS}>>")
|
set(is_static_qt_build "$<NOT:$<BOOL:${QT_BUILD_SHARED_LIBS}>>")
|
||||||
set(is_staitc_lib_during_static_qt_build "$<AND:${is_static_qt_build},${is_static_lib}>")
|
set(is_static_lib_during_static_qt_build "$<AND:${is_static_qt_build},${is_static_lib}>")
|
||||||
set(enable_sse2_condition "$<OR:${is_shared_lib},${is_staitc_lib_during_static_qt_build}>")
|
set(enable_sse2_condition "$<OR:${is_shared_lib},${is_static_lib_during_static_qt_build}>")
|
||||||
set(${out_var} "${enable_sse2_condition}" PARENT_SCOPE)
|
set(${out_var} "${enable_sse2_condition}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
# This function can be used to compile java sources into a jar package.
|
# This function can be used to compile java sources into a jar package.
|
||||||
|
|
||||||
function(qt_internal_add_jar target)
|
function(qt_internal_add_jar target)
|
||||||
|
set(options)
|
||||||
|
set(oneValueArgs OUTPUT_DIR)
|
||||||
|
set(multiValueArgs INCLUDE_JARS SOURCES)
|
||||||
|
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
set(javac_target_version "${QT_ANDROID_JAVAC_TARGET}")
|
set(javac_target_version "${QT_ANDROID_JAVAC_TARGET}")
|
||||||
if (NOT javac_target_version)
|
if (NOT javac_target_version)
|
||||||
@ -18,4 +22,8 @@ function(qt_internal_add_jar target)
|
|||||||
set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}" -Xlint:unchecked -bootclasspath "${QT_ANDROID_JAR}")
|
set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}" -Xlint:unchecked -bootclasspath "${QT_ANDROID_JAR}")
|
||||||
add_jar(${ARGV})
|
add_jar(${ARGV})
|
||||||
|
|
||||||
|
foreach(f IN LISTS arg_SOURCES)
|
||||||
|
_qt_internal_expose_source_file_to_ide(${target} "${f}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -37,7 +37,6 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
|
|||||||
QMAKE_MODULE_CONFIG
|
QMAKE_MODULE_CONFIG
|
||||||
EXTRA_CMAKE_FILES
|
EXTRA_CMAKE_FILES
|
||||||
EXTRA_CMAKE_INCLUDES
|
EXTRA_CMAKE_INCLUDES
|
||||||
NO_PCH_SOURCES
|
|
||||||
EXTERNAL_HEADERS
|
EXTERNAL_HEADERS
|
||||||
POLICIES
|
POLICIES
|
||||||
${__default_private_args}
|
${__default_private_args}
|
||||||
@ -447,6 +446,8 @@ function(qt_internal_add_module target)
|
|||||||
# If EXTERNAL_HEADERS_DIR is set we install the specified directory and keep the structure
|
# If EXTERNAL_HEADERS_DIR is set we install the specified directory and keep the structure
|
||||||
# without taking into the account the CMake source tree and syncqt outputs.
|
# without taking into the account the CMake source tree and syncqt outputs.
|
||||||
if(arg_EXTERNAL_HEADERS_DIR)
|
if(arg_EXTERNAL_HEADERS_DIR)
|
||||||
|
set_property(TARGET ${target}
|
||||||
|
PROPERTY _qt_external_headers_dir "${arg_EXTERNAL_HEADERS_DIR}")
|
||||||
qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/"
|
qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/"
|
||||||
DESTINATION "${module_install_interface_include_dir}"
|
DESTINATION "${module_install_interface_include_dir}"
|
||||||
)
|
)
|
||||||
@ -1186,10 +1187,13 @@ function(qt_internal_collect_module_headers out_var target)
|
|||||||
get_target_property(target_type ${target} TYPE)
|
get_target_property(target_type ${target} TYPE)
|
||||||
if(target_type STREQUAL "INTERFACE_LIBRARY")
|
if(target_type STREQUAL "INTERFACE_LIBRARY")
|
||||||
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}")
|
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
set(binary_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
else()
|
else()
|
||||||
get_target_property(source_dir ${target} SOURCE_DIR)
|
get_target_property(source_dir ${target} SOURCE_DIR)
|
||||||
|
get_target_property(binary_dir ${target} BINARY_DIR)
|
||||||
endif()
|
endif()
|
||||||
get_filename_component(source_dir "${source_dir}" ABSOLUTE)
|
get_filename_component(source_dir "${source_dir}" ABSOLUTE)
|
||||||
|
get_filename_component(binary_dir "${binary_dir}" ABSOLUTE)
|
||||||
|
|
||||||
get_target_property(is_3rdparty_library ${target} _qt_module_is_3rdparty_header_library)
|
get_target_property(is_3rdparty_library ${target} _qt_module_is_3rdparty_header_library)
|
||||||
|
|
||||||
@ -1232,7 +1236,14 @@ function(qt_internal_collect_module_headers out_var target)
|
|||||||
"\nCondition:\n ${condition_string}")
|
"\nCondition:\n ${condition_string}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(file_path MATCHES "3rdparty/.+" AND NOT is_3rdparty_library)
|
if(is_outside_module_source_dir)
|
||||||
|
set(base_dir "${binary_dir}")
|
||||||
|
else()
|
||||||
|
set(base_dir "${source_dir}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(RELATIVE_PATH file_path_rel "${base_dir}" "${file_path}")
|
||||||
|
if(file_path_rel MATCHES "3rdparty/.+" AND NOT is_3rdparty_library)
|
||||||
set(is_3rdparty_header TRUE)
|
set(is_3rdparty_header TRUE)
|
||||||
else()
|
else()
|
||||||
set(is_3rdparty_header FALSE)
|
set(is_3rdparty_header FALSE)
|
||||||
|
@ -51,6 +51,17 @@ function(qt_internal_generate_pkg_config_file module)
|
|||||||
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_INCLUDEDIR}" "\${includedir}")
|
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_INCLUDEDIR}" "\${includedir}")
|
||||||
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_MKSPECSDIR}" "\${mkspecsdir}")
|
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_MKSPECSDIR}" "\${mkspecsdir}")
|
||||||
|
|
||||||
|
# Remove genex wrapping around gc_sections flag because we can't evaluate genexes like
|
||||||
|
# $<CXX_COMPILER_ID> in file(GENERATE). And given that .pc files don't support dynamic
|
||||||
|
# evaluation like the $<CXX_COMPILER_ID> genex, distros will be expected to patch the .pc
|
||||||
|
# files according to which compiler they intend to be used with.
|
||||||
|
get_property(gc_sections_with_genex GLOBAL PROPERTY _qt_internal_gc_sections_with_genex)
|
||||||
|
get_property(gc_sections_without_genex GLOBAL PROPERTY _qt_internal_gc_sections_without_genex)
|
||||||
|
if(loose_link_options AND gc_sections_with_genex AND gc_sections_without_genex)
|
||||||
|
string(REPLACE "${gc_sections_with_genex}" "${gc_sections_without_genex}"
|
||||||
|
loose_link_options "${loose_link_options}")
|
||||||
|
endif()
|
||||||
|
|
||||||
qt_internal_set_pkg_config_cpp_flags(link_options "${loose_link_options}" "")
|
qt_internal_set_pkg_config_cpp_flags(link_options "${loose_link_options}" "")
|
||||||
qt_internal_set_pkg_config_cpp_flags(compile_defs "${loose_compile_defs}" -D)
|
qt_internal_set_pkg_config_cpp_flags(compile_defs "${loose_compile_defs}" -D)
|
||||||
qt_internal_set_pkg_config_cpp_flags(include_dirs "${loose_include_dirs}" -I)
|
qt_internal_set_pkg_config_cpp_flags(include_dirs "${loose_include_dirs}" -I)
|
||||||
|
@ -336,6 +336,8 @@ function(qt_internal_add_plugin target)
|
|||||||
qt_internal_extend_target("${target}"
|
qt_internal_extend_target("${target}"
|
||||||
${arg_NO_UNITY_BUILD}
|
${arg_NO_UNITY_BUILD}
|
||||||
SOURCES ${arg_SOURCES}
|
SOURCES ${arg_SOURCES}
|
||||||
|
NO_PCH_SOURCES
|
||||||
|
${arg_NO_PCH_SOURCES}
|
||||||
NO_UNITY_BUILD_SOURCES
|
NO_UNITY_BUILD_SOURCES
|
||||||
${arg_NO_UNITY_BUILD_SOURCES}
|
${arg_NO_UNITY_BUILD_SOURCES}
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
|
@ -26,9 +26,14 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out
|
|||||||
set(lib_incdir "")
|
set(lib_incdir "")
|
||||||
set(lib_libdir "")
|
set(lib_libdir "")
|
||||||
set(lib_libs "")
|
set(lib_libs "")
|
||||||
|
set(seen_targets "")
|
||||||
while(lib_targets)
|
while(lib_targets)
|
||||||
list(POP_BACK lib_targets lib_target)
|
list(POP_BACK lib_targets lib_target)
|
||||||
if(TARGET ${lib_target})
|
if(TARGET ${lib_target})
|
||||||
|
if(${lib_target} IN_LIST seen_targets)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
list(APPEND seen_targets ${lib_target})
|
||||||
get_target_property(lib_target_type ${lib_target} TYPE)
|
get_target_property(lib_target_type ${lib_target} TYPE)
|
||||||
if(lib_target_type STREQUAL "INTERFACE_LIBRARY")
|
if(lib_target_type STREQUAL "INTERFACE_LIBRARY")
|
||||||
get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES)
|
get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES)
|
||||||
|
@ -55,7 +55,10 @@ if("${MODULE_ROOT}" STREQUAL "")
|
|||||||
set(qtbase_or_top_level_build TRUE)
|
set(qtbase_or_top_level_build TRUE)
|
||||||
else()
|
else()
|
||||||
# If MODULE_ROOT is passed without drive letter, we try to add it to the path.
|
# If MODULE_ROOT is passed without drive letter, we try to add it to the path.
|
||||||
get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}")
|
# The check is necessary; otherwise, `get_filename_component` returns an empty string.
|
||||||
|
if(NOT MODULE_ROOT STREQUAL ".")
|
||||||
|
get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}")
|
||||||
|
endif()
|
||||||
set(qtbase_or_top_level_build FALSE)
|
set(qtbase_or_top_level_build FALSE)
|
||||||
endif()
|
endif()
|
||||||
set(configure_filename "configure.cmake")
|
set(configure_filename "configure.cmake")
|
||||||
@ -136,13 +139,6 @@ while(NOT "${configure_args}" STREQUAL "")
|
|||||||
list(POP_FRONT configure_args version)
|
list(POP_FRONT configure_args version)
|
||||||
is_valid_qt_hex_version("${arg}" "${version}")
|
is_valid_qt_hex_version("${arg}" "${version}")
|
||||||
push("-DQT_DISABLE_DEPRECATED_UP_TO=${version}")
|
push("-DQT_DISABLE_DEPRECATED_UP_TO=${version}")
|
||||||
elseif(arg STREQUAL "-unity-build")
|
|
||||||
push("-DQT_UNITY_BUILD=ON")
|
|
||||||
# QT_UNITY_BUILD_BATCH_SIZE will be set to 8, CMake's default.
|
|
||||||
elseif(arg STREQUAL "-unity-build-batch-size")
|
|
||||||
list(POP_FRONT configure_args unity_build_batch_size)
|
|
||||||
is_non_empty_valid_arg("${arg}" "${unity_build_batch_size}")
|
|
||||||
push("-DQT_UNITY_BUILD_BATCH_SIZE=${unity_build_batch_size}")
|
|
||||||
elseif(arg STREQUAL "--")
|
elseif(arg STREQUAL "--")
|
||||||
# Everything after this argument will be passed to CMake verbatim.
|
# Everything after this argument will be passed to CMake verbatim.
|
||||||
list(APPEND cmake_args "${configure_args}")
|
list(APPEND cmake_args "${configure_args}")
|
||||||
@ -827,6 +823,8 @@ endfunction()
|
|||||||
drop_input(commercial)
|
drop_input(commercial)
|
||||||
drop_input(confirm-license)
|
drop_input(confirm-license)
|
||||||
translate_boolean_input(precompile_header BUILD_WITH_PCH)
|
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(ccache QT_USE_CCACHE)
|
||||||
translate_boolean_input(shared BUILD_SHARED_LIBS)
|
translate_boolean_input(shared BUILD_SHARED_LIBS)
|
||||||
translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS)
|
translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS)
|
||||||
|
@ -221,7 +221,7 @@ function(_qt_internal_find_ios_development_team_id out_var)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(_qt_internal_get_ios_bundle_identifier_prefix out_var)
|
function(_qt_internal_get_apple_bundle_identifier_prefix out_var)
|
||||||
get_property(prefix GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix)
|
get_property(prefix GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix)
|
||||||
get_property(prefix_computed GLOBAL PROPERTY
|
get_property(prefix_computed GLOBAL PROPERTY
|
||||||
_qt_internal_ios_bundle_identifier_prefix_computed)
|
_qt_internal_ios_bundle_identifier_prefix_computed)
|
||||||
@ -269,8 +269,8 @@ function(_qt_internal_escape_rfc_1034_identifier value out_var)
|
|||||||
set("${out_var}" "${value}" PARENT_SCOPE)
|
set("${out_var}" "${value}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(_qt_internal_get_default_ios_bundle_identifier out_var)
|
function(_qt_internal_get_default_apple_bundle_identifier target out_var)
|
||||||
_qt_internal_get_ios_bundle_identifier_prefix(prefix)
|
_qt_internal_get_apple_bundle_identifier_prefix(prefix)
|
||||||
if(NOT prefix)
|
if(NOT prefix)
|
||||||
set(prefix "com.yourcompany")
|
set(prefix "com.yourcompany")
|
||||||
|
|
||||||
@ -281,14 +281,16 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var)
|
|||||||
string(SHA1 hash "${team_id}")
|
string(SHA1 hash "${team_id}")
|
||||||
string(SUBSTRING "${hash}" 0 8 infix)
|
string(SUBSTRING "${hash}" 0 8 infix)
|
||||||
string(APPEND prefix ".${infix}")
|
string(APPEND prefix ".${infix}")
|
||||||
else()
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
message(WARNING
|
message(WARNING
|
||||||
"No organization bundle identifier prefix could be retrieved from Xcode "
|
"No organization bundle identifier prefix could be retrieved from Xcode preferences. \
|
||||||
"preferences. This can lead to code signing issues due to a non-unique bundle "
|
This can lead to code signing issues due to a non-unique bundle \
|
||||||
"identifier. Please set up an organization prefix by creating a new project within "
|
identifier. Please set up an organization prefix by creating a new project within \
|
||||||
"Xcode, or consider providing a custom bundle identifier by specifying the "
|
Xcode, or consider providing a custom bundle identifier by specifying the \
|
||||||
"XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property."
|
MACOSX_BUNDLE_GUI_IDENTIFIER or XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property."
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -299,7 +301,12 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var)
|
|||||||
# that the identifier is invalid.
|
# that the identifier is invalid.
|
||||||
_qt_internal_escape_rfc_1034_identifier("${prefix}" prefix)
|
_qt_internal_escape_rfc_1034_identifier("${prefix}" prefix)
|
||||||
|
|
||||||
set(identifier "${prefix}.\${PRODUCT_NAME:rfc1034identifier}")
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
|
set(identifier "${prefix}.$(PRODUCT_NAME:rfc1034identifier)")
|
||||||
|
else()
|
||||||
|
set(identifier "${prefix}.${target}")
|
||||||
|
endif()
|
||||||
|
|
||||||
set("${out_var}" "${identifier}" PARENT_SCOPE)
|
set("${out_var}" "${identifier}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@ -384,56 +391,72 @@ function(_qt_internal_set_xcode_development_team_id target)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(_qt_internal_set_xcode_bundle_identifier target)
|
function(_qt_internal_set_apple_bundle_identifier target)
|
||||||
# Skip all logic if requested.
|
# Skip all logic if requested.
|
||||||
if(QT_NO_SET_XCODE_BUNDLE_IDENTIFIER)
|
if(QT_NO_SET_XCODE_BUNDLE_IDENTIFIER)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# There are two fields to consider: the CFBundleIdentifier key (CFBI) to be written to
|
# There are two fields to consider: the CFBundleIdentifier key (ie., cmake_bundle_identifier)
|
||||||
# Info.plist
|
# to be written to Info.plist and the PRODUCT_BUNDLE_IDENTIFIER (ie., xcode_bundle_identifier)
|
||||||
# and the PRODUCT_BUNDLE_IDENTIFIER (PBI) property to set in the Xcode project.
|
# property to set in the Xcode project. The `cmake_bundle_identifier` set by
|
||||||
# The following logic enables the best out-of-the-box experience combined with maximum
|
# MACOSX_BUNDLE_GUI_IDENTIFIER applies to both Xcode, and other generators, while
|
||||||
# customization.
|
# `xcode_bundle_identifier` set by XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER is
|
||||||
# 1) If values for both fields are not provided, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI
|
# Xcode specific.
|
||||||
# (which is expanded by xcodebuild at build time and will use the value of PBI) and
|
#
|
||||||
# auto-compute a default PBI from Xcode's ${PRODUCT_NAME}.
|
# If Ninja is the generator, we set the value of `MACOSX_BUNDLE_GUI_IDENTIFIER`
|
||||||
# 2) If CFBI is set and PBI isn't, use given CFBI and keep PBI empty.
|
# and don't touch the `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`.
|
||||||
# 3) If PBI is set and CFBI isn't, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI and use
|
# If Xcode is the generator, we set the value of `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`,
|
||||||
# the given PBI.
|
# and additionally, to silence a Xcode's warning, we set the `MACOSX_BUNDLE_GUI_IDENTIFIER` to
|
||||||
# 4) If both are set, use both given values.
|
# `${PRODUCT_BUNDLE_IDENTIFIER}` so that Xcode could sort it out.
|
||||||
# TLDR:
|
|
||||||
# cfbi pbi -> result_cfbi result_pbi
|
|
||||||
# unset unset computed computed
|
|
||||||
# set unset given_val unset
|
|
||||||
# unset set computed given_val
|
|
||||||
# set set given_val given_val
|
|
||||||
|
|
||||||
get_target_property(existing_cfbi "${target}" MACOSX_BUNDLE_GUI_IDENTIFIER)
|
get_target_property(existing_cmake_bundle_identifier "${target}"
|
||||||
if(NOT MACOSX_BUNDLE_GUI_IDENTIFIER AND NOT existing_cfbi)
|
MACOSX_BUNDLE_GUI_IDENTIFIER)
|
||||||
set(is_cfbi_given FALSE)
|
get_target_property(existing_xcode_bundle_identifier "${target}"
|
||||||
else()
|
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
|
||||||
set(is_cfbi_given TRUE)
|
|
||||||
|
set(is_cmake_bundle_identifier_given FALSE)
|
||||||
|
if(existing_cmake_bundle_identifier)
|
||||||
|
set(is_cmake_bundle_identifier_given TRUE)
|
||||||
|
elseif(MACOSX_BUNDLE_GUI_IDENTIFIER)
|
||||||
|
set(is_cmake_bundle_identifier_given TRUE)
|
||||||
|
set(existing_cmake_bundle_identifier ${MACOSX_BUNDLE_GUI_IDENTIFIER})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT is_cfbi_given)
|
set(is_xcode_bundle_identifier_given FALSE)
|
||||||
|
if(existing_xcode_bundle_identifier)
|
||||||
|
set(is_xcode_bundle_identifier_given TRUE)
|
||||||
|
elseif(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
|
||||||
|
set(is_xcode_bundle_identifier_given TRUE)
|
||||||
|
set(existing_xcode_bundle_identifier ${CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(is_cmake_bundle_identifier_given
|
||||||
|
AND is_xcode_bundle_identifier_given
|
||||||
|
AND NOT existing_cmake_bundle_identifier STREQUAL existing_xcode_bundle_identifier)
|
||||||
|
message(WARNING
|
||||||
|
"MACOSX_BUNDLE_GUI_IDENTIFIER and XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "
|
||||||
|
"are set to different values. You only need to set one of them. ")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT is_xcode_bundle_identifier_given
|
||||||
|
AND NOT is_cmake_bundle_identifier_given)
|
||||||
|
_qt_internal_get_default_apple_bundle_identifier("${target}" bundle_id)
|
||||||
|
elseif(is_cmake_bundle_identifier_given)
|
||||||
|
set(bundle_id ${existing_cmake_bundle_identifier})
|
||||||
|
elseif(is_xcode_bundle_identifier_given)
|
||||||
|
set(bundle_id ${existing_xcode_bundle_identifier})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
set_target_properties("${target}"
|
set_target_properties("${target}"
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
MACOSX_BUNDLE_GUI_IDENTIFIER "\${PRODUCT_BUNDLE_IDENTIFIER}")
|
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}"
|
||||||
endif()
|
MACOSX_BUNDLE_GUI_IDENTIFIER "$(PRODUCT_BUNDLE_IDENTIFIER)")
|
||||||
|
|
||||||
get_target_property(existing_pbi "${target}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
|
|
||||||
if(NOT CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER AND NOT existing_pbi)
|
|
||||||
set(is_pbi_given FALSE)
|
|
||||||
else()
|
else()
|
||||||
set(is_pbi_given TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT is_pbi_given AND NOT is_cfbi_given)
|
|
||||||
_qt_internal_get_default_ios_bundle_identifier(bundle_id)
|
|
||||||
set_target_properties("${target}"
|
set_target_properties("${target}"
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}")
|
MACOSX_BUNDLE_GUI_IDENTIFIER "${bundle_id}")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@ -503,7 +526,7 @@ function(_qt_internal_set_xcode_bundle_name target)
|
|||||||
if(CMAKE_GENERATOR STREQUAL Xcode)
|
if(CMAKE_GENERATOR STREQUAL Xcode)
|
||||||
set_target_properties("${target}"
|
set_target_properties("${target}"
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
MACOSX_BUNDLE_BUNDLE_NAME "\${PRODUCT_NAME}")
|
MACOSX_BUNDLE_BUNDLE_NAME "$(PRODUCT_NAME)")
|
||||||
else()
|
else()
|
||||||
set_target_properties("${target}"
|
set_target_properties("${target}"
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
@ -603,12 +626,13 @@ function(_qt_internal_finalize_apple_app target)
|
|||||||
# This affects things like the version number or application name as reported by Qt API.
|
# This affects things like the version number or application name as reported by Qt API.
|
||||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
_qt_internal_set_xcode_development_team_id("${target}")
|
_qt_internal_set_xcode_development_team_id("${target}")
|
||||||
_qt_internal_set_xcode_bundle_identifier("${target}")
|
|
||||||
_qt_internal_set_xcode_code_sign_style("${target}")
|
_qt_internal_set_xcode_code_sign_style("${target}")
|
||||||
_qt_internal_set_xcode_bundle_display_name("${target}")
|
_qt_internal_set_xcode_bundle_display_name("${target}")
|
||||||
_qt_internal_set_xcode_install_path("${target}")
|
_qt_internal_set_xcode_install_path("${target}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
_qt_internal_set_xcode_bundle_name("${target}")
|
_qt_internal_set_xcode_bundle_name("${target}")
|
||||||
|
_qt_internal_set_apple_bundle_identifier("${target}")
|
||||||
_qt_internal_set_placeholder_apple_bundle_version("${target}")
|
_qt_internal_set_placeholder_apple_bundle_version("${target}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -307,7 +307,17 @@ function(_qt_internal_set_up_static_runtime_library target)
|
|||||||
set_property(TARGET ${target} PROPERTY
|
set_property(TARGET ${target} PROPERTY
|
||||||
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
elseif(MINGW)
|
elseif(MINGW)
|
||||||
target_link_options(${target} INTERFACE "LINKER:-Bstatic")
|
get_target_property(target_type ${target} TYPE)
|
||||||
|
if(target_type STREQUAL "EXECUTABLE")
|
||||||
|
set(link_option PRIVATE)
|
||||||
|
else()
|
||||||
|
set(link_option INTERFACE)
|
||||||
|
endif()
|
||||||
|
if(CLANG)
|
||||||
|
target_link_options(${target} ${link_option} "LINKER:-Bstatic")
|
||||||
|
else()
|
||||||
|
target_link_options(${target} ${link_option} "-static")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
function(qt_internal_get_relative_rpath_base_token out_var)
|
function(qt_internal_get_relative_rpath_base_token out_var)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(rpath_rel_base "@loader_path")
|
set(rpath_rel_base "@loader_path")
|
||||||
elseif(LINUX OR SOLARIS OR FREEBSD OR HURD)
|
elseif(LINUX OR SOLARIS OR FREEBSD OR HURD OR OPENBSD)
|
||||||
set(rpath_rel_base "$ORIGIN")
|
set(rpath_rel_base "$ORIGIN")
|
||||||
else()
|
else()
|
||||||
set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE")
|
set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE")
|
||||||
|
@ -201,7 +201,11 @@ endfunction()
|
|||||||
# Enable separate debug information for the given target
|
# Enable separate debug information for the given target
|
||||||
function(qt_enable_separate_debug_info target installDestination)
|
function(qt_enable_separate_debug_info target installDestination)
|
||||||
set(flags QT_EXECUTABLE)
|
set(flags QT_EXECUTABLE)
|
||||||
set(options)
|
if(APPLE)
|
||||||
|
set(options DSYM_OUTPUT_DIR)
|
||||||
|
else()
|
||||||
|
set(options)
|
||||||
|
endif()
|
||||||
set(multiopts ADDITIONAL_INSTALL_ARGS)
|
set(multiopts ADDITIONAL_INSTALL_ARGS)
|
||||||
cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN})
|
cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN})
|
||||||
|
|
||||||
@ -248,12 +252,20 @@ function(qt_enable_separate_debug_info target installDestination)
|
|||||||
get_target_property(is_framework ${target} FRAMEWORK)
|
get_target_property(is_framework ${target} FRAMEWORK)
|
||||||
if(is_framework)
|
if(is_framework)
|
||||||
qt_internal_get_framework_info(fw ${target})
|
qt_internal_get_framework_info(fw ${target})
|
||||||
set(debug_info_bundle_dir "$<TARGET_BUNDLE_DIR:${target}>.${debug_info_suffix}")
|
|
||||||
set(BUNDLE_ID ${fw_name})
|
set(BUNDLE_ID ${fw_name})
|
||||||
else()
|
else()
|
||||||
set(debug_info_bundle_dir "$<TARGET_FILE:${target}>.${debug_info_suffix}")
|
|
||||||
set(BUNDLE_ID ${target})
|
set(BUNDLE_ID ${target})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT "x${arg_DSYM_OUTPUT_DIR}" STREQUAL "x")
|
||||||
|
set(debug_info_bundle_dir "${arg_DSYM_OUTPUT_DIR}/${target}")
|
||||||
|
elseif(is_framework)
|
||||||
|
set(debug_info_bundle_dir "$<TARGET_BUNDLE_DIR:${target}>")
|
||||||
|
else()
|
||||||
|
set(debug_info_bundle_dir "$<TARGET_FILE:${target}>")
|
||||||
|
endif()
|
||||||
|
set(debug_info_bundle_dir "${debug_info_bundle_dir}.${debug_info_suffix}")
|
||||||
|
|
||||||
set(debug_info_contents_dir "${debug_info_bundle_dir}/Contents")
|
set(debug_info_contents_dir "${debug_info_bundle_dir}/Contents")
|
||||||
set(debug_info_target_dir "${debug_info_contents_dir}/Resources/DWARF")
|
set(debug_info_target_dir "${debug_info_contents_dir}/Resources/DWARF")
|
||||||
configure_file(
|
configure_file(
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
# Set the QT_IS_BUILDING_QT variable so we can verify whether we are building
|
# Set the QT_IS_BUILDING_QT variable so we can verify whether we are building
|
||||||
# Qt from source
|
# Qt from source
|
||||||
set(QT_BUILDING_QT TRUE CACHE
|
set(QT_BUILDING_QT TRUE CACHE BOOL
|
||||||
TYPE STRING "When this is present and set to true, it signals that we are building Qt from source.")
|
"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
|
# 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
|
if(NOT FEATURE_developer_build AND INPUT_developer_build
|
||||||
@ -352,6 +352,8 @@ if(QT_UNITY_BUILD)
|
|||||||
set(CMAKE_UNITY_BUILD_BATCH_SIZE "${QT_UNITY_BUILD_BATCH_SIZE}")
|
set(CMAKE_UNITY_BUILD_BATCH_SIZE "${QT_UNITY_BUILD_BATCH_SIZE}")
|
||||||
endif()
|
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
|
# We need to clean up QT_FEATURE_*, but only once per configuration cycle
|
||||||
get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
|
get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
|
||||||
if(NOT qt_feature_clean)
|
if(NOT qt_feature_clean)
|
||||||
|
@ -139,7 +139,6 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
|||||||
|
|
||||||
set(syncqt_args "${common_syncqt_arguments}")
|
set(syncqt_args "${common_syncqt_arguments}")
|
||||||
list(APPEND syncqt_args
|
list(APPEND syncqt_args
|
||||||
${common_syncqt_arguments}
|
|
||||||
-headers ${module_headers}
|
-headers ${module_headers}
|
||||||
-stagingDir "${syncqt_staging_dir}"
|
-stagingDir "${syncqt_staging_dir}"
|
||||||
-knownModules ${known_modules}
|
-knownModules ${known_modules}
|
||||||
@ -150,6 +149,21 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
|||||||
set(syncqt_args_rsp "${binary_dir_real}/${target}_syncqt_args")
|
set(syncqt_args_rsp "${binary_dir_real}/${target}_syncqt_args")
|
||||||
qt_configure_file(OUTPUT "${syncqt_args_rsp}" CONTENT "${syncqt_args_string}")
|
qt_configure_file(OUTPUT "${syncqt_args_rsp}" CONTENT "${syncqt_args_string}")
|
||||||
|
|
||||||
|
get_target_property(external_headers_dir ${target} _qt_external_headers_dir)
|
||||||
|
if(external_headers_dir)
|
||||||
|
if(NOT IS_ABSOLUTE "${external_headers_dir}")
|
||||||
|
get_filename_component(external_headers_dir "${external_headers_dir}" ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
if(EXISTS "${external_headers_dir}")
|
||||||
|
set(external_headers_dir_copy_cmd
|
||||||
|
COMMAND
|
||||||
|
${CMAKE_COMMAND}
|
||||||
|
-E copy_directory
|
||||||
|
"${external_headers_dir}"
|
||||||
|
"${module_build_interface_include_dir}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT
|
OUTPUT
|
||||||
${syncqt_outputs}
|
${syncqt_outputs}
|
||||||
@ -157,6 +171,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
|||||||
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
|
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
|
||||||
"@${syncqt_args_rsp}"
|
"@${syncqt_args_rsp}"
|
||||||
${build_time_syncqt_arguments}
|
${build_time_syncqt_arguments}
|
||||||
|
${external_headers_dir_copy_cmd}
|
||||||
COMMAND
|
COMMAND
|
||||||
${CMAKE_COMMAND} -E touch "${syncqt_timestamp}"
|
${CMAKE_COMMAND} -E touch "${syncqt_timestamp}"
|
||||||
DEPENDS
|
DEPENDS
|
||||||
@ -167,12 +182,22 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
|||||||
"Running syncqt.cpp for module: ${module}"
|
"Running syncqt.cpp for module: ${module}"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(add_sync_headers_to_all "")
|
||||||
|
if(is_interface_lib)
|
||||||
|
set(add_sync_headers_to_all ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target(${target}_sync_headers
|
add_custom_target(${target}_sync_headers
|
||||||
|
${add_sync_headers_to_all}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${syncqt_outputs}
|
${syncqt_outputs}
|
||||||
)
|
)
|
||||||
add_dependencies(sync_headers ${target}_sync_headers)
|
add_dependencies(sync_headers ${target}_sync_headers)
|
||||||
|
|
||||||
|
if(is_3rd_party_library)
|
||||||
|
add_dependencies(thirdparty_sync_headers ${target}_sync_headers)
|
||||||
|
endif()
|
||||||
# This target is required when building docs, to make all header files and their aliases
|
# This target is required when building docs, to make all header files and their aliases
|
||||||
# available for qdoc.
|
# available for qdoc.
|
||||||
# ${target}_sync_headers is added as dependency to make sure that
|
# ${target}_sync_headers is added as dependency to make sure that
|
||||||
@ -185,6 +210,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
|||||||
COMMAND
|
COMMAND
|
||||||
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
|
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
|
||||||
"@${syncqt_all_args_rsp}"
|
"@${syncqt_all_args_rsp}"
|
||||||
|
${external_headers_dir_copy_cmd}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${module_headers}
|
${module_headers}
|
||||||
${syncqt_all_args_rsp}
|
${syncqt_all_args_rsp}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
# module, these files will raise a warning at configure time if the condition is not met.
|
# module, these files will raise a warning at configure time if the condition is not met.
|
||||||
# COMPILE_FLAGS
|
# COMPILE_FLAGS
|
||||||
# Custom compilation flags.
|
# Custom compilation flags.
|
||||||
|
# EXTRA_LINKER_SCRIPT_CONTENT
|
||||||
|
# Extra content that should be appended to a target linker script. Applicable for ld only.
|
||||||
# NO_PCH_SOURCES
|
# NO_PCH_SOURCES
|
||||||
# Skip the specified source files by PRECOMPILE_HEADERS feature.
|
# Skip the specified source files by PRECOMPILE_HEADERS feature.
|
||||||
function(qt_internal_extend_target target)
|
function(qt_internal_extend_target target)
|
||||||
@ -36,6 +38,7 @@ function(qt_internal_extend_target target)
|
|||||||
)
|
)
|
||||||
set(single_args
|
set(single_args
|
||||||
PRECOMPILED_HEADER
|
PRECOMPILED_HEADER
|
||||||
|
EXTRA_LINKER_SCRIPT_CONTENT
|
||||||
)
|
)
|
||||||
set(multi_args
|
set(multi_args
|
||||||
${__default_public_args}
|
${__default_public_args}
|
||||||
@ -44,7 +47,6 @@ function(qt_internal_extend_target target)
|
|||||||
CONDITION
|
CONDITION
|
||||||
CONDITION_INDEPENDENT_SOURCES
|
CONDITION_INDEPENDENT_SOURCES
|
||||||
COMPILE_FLAGS
|
COMPILE_FLAGS
|
||||||
NO_PCH_SOURCES
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmake_parse_arguments(PARSE_ARGV 1 arg
|
cmake_parse_arguments(PARSE_ARGV 1 arg
|
||||||
@ -237,6 +239,10 @@ function(qt_internal_extend_target target)
|
|||||||
${sources_property} "${arg_CONDITION_INDEPENDENT_SOURCES}")
|
${sources_property} "${arg_CONDITION_INDEPENDENT_SOURCES}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(arg_EXTRA_LINKER_SCRIPT_CONTENT)
|
||||||
|
set_target_properties(${target} PROPERTIES
|
||||||
|
_qt_extra_linker_script_content "${arg_EXTRA_LINKER_SCRIPT_CONTENT}")
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(qt_is_imported_target target out_var)
|
function(qt_is_imported_target target out_var)
|
||||||
@ -1001,6 +1007,15 @@ endfunction()
|
|||||||
# Needed to allow selectively applying certain flags via PlatformXInternal targets.
|
# Needed to allow selectively applying certain flags via PlatformXInternal targets.
|
||||||
function(qt_internal_mark_as_internal_library target)
|
function(qt_internal_mark_as_internal_library target)
|
||||||
set_target_properties(${target} PROPERTIES _qt_is_internal_library TRUE)
|
set_target_properties(${target} PROPERTIES _qt_is_internal_library TRUE)
|
||||||
|
qt_internal_mark_as_internal_target(${target})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Marks a target with a property that it was built using the internal Qt API (qt_internal_*) as
|
||||||
|
# opposed to it being a user project library or executable(qt_add_*, etc).
|
||||||
|
#
|
||||||
|
# Needed to allow selectively applying certain flags via PlatformXInternal targets.
|
||||||
|
function(qt_internal_mark_as_internal_target target)
|
||||||
|
set_target_properties(${target} PROPERTIES _qt_is_internal_target TRUE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(qt_internal_link_internal_platform_for_object_library target)
|
function(qt_internal_link_internal_platform_for_object_library target)
|
||||||
|
@ -214,6 +214,7 @@ function(qt_internal_get_test_arg_definitions optional_args single_value_args mu
|
|||||||
MANUAL
|
MANUAL
|
||||||
NO_BATCH
|
NO_BATCH
|
||||||
NO_INSTALL
|
NO_INSTALL
|
||||||
|
BUNDLE_ANDROID_OPENSSL_LIBS
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
set(${single_value_args}
|
set(${single_value_args}
|
||||||
@ -526,6 +527,21 @@ function(qt_internal_add_test name)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
|
if(arg_BUNDLE_ANDROID_OPENSSL_LIBS)
|
||||||
|
if(NOT OPENSSL_ROOT_DIR)
|
||||||
|
message(WARNING "The argument BUNDLE_ANDROID_OPENSSL_LIBS is set "
|
||||||
|
"but OPENSSL_ROOT_DIR parameter is not set.")
|
||||||
|
else()
|
||||||
|
if(EXISTS "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so")
|
||||||
|
set_property(TARGET ${name} APPEND PROPERTY QT_ANDROID_EXTRA_LIBS
|
||||||
|
"${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so"
|
||||||
|
"${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libssl_3.so")
|
||||||
|
else()
|
||||||
|
message(STATUS "Test should bundle OpenSSL libraries but they are not found."
|
||||||
|
" This is fine if OpenSSL was built statically.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
qt_internal_android_test_arguments("${name}" test_executable extra_test_args)
|
qt_internal_android_test_arguments("${name}" test_executable extra_test_args)
|
||||||
set(test_working_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
set(test_working_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
elseif(QNX)
|
elseif(QNX)
|
||||||
|
@ -15,6 +15,13 @@
|
|||||||
# INSTALL_VERSIONED_LINK
|
# INSTALL_VERSIONED_LINK
|
||||||
# Prefix build only. On installation, create a versioned hard-link of the installed file.
|
# Prefix build only. On installation, create a versioned hard-link of the installed file.
|
||||||
# E.g. create a link of "bin/qmake6" to "bin/qmake".
|
# E.g. create a link of "bin/qmake6" to "bin/qmake".
|
||||||
|
# TRY_RUN
|
||||||
|
# On Windows, it creates a helper batch script that tests whether the tool can be executed
|
||||||
|
# successfully or not. If not, build halts and an error will be show, with tips on what
|
||||||
|
# might be cause, and how to fix it. TRY_RUN is disabled when cross-compiling.
|
||||||
|
# TRY_RUN_FLAGS
|
||||||
|
# Command line flags that are going to be passed to the tool for testing its correctness.
|
||||||
|
# If no flags were given, we default to `-v`.
|
||||||
#
|
#
|
||||||
# One-value Arguments:
|
# One-value Arguments:
|
||||||
# EXTRA_CMAKE_FILES
|
# EXTRA_CMAKE_FILES
|
||||||
@ -42,11 +49,13 @@ function(qt_internal_add_tool target_name)
|
|||||||
USER_FACING
|
USER_FACING
|
||||||
INSTALL_VERSIONED_LINK
|
INSTALL_VERSIONED_LINK
|
||||||
EXCEPTIONS
|
EXCEPTIONS
|
||||||
NO_UNITY_BUILD)
|
NO_UNITY_BUILD
|
||||||
|
TRY_RUN)
|
||||||
set(one_value_keywords
|
set(one_value_keywords
|
||||||
TOOLS_TARGET
|
TOOLS_TARGET
|
||||||
INSTALL_DIR
|
INSTALL_DIR
|
||||||
CORE_LIBRARY
|
CORE_LIBRARY
|
||||||
|
TRY_RUN_FLAGS
|
||||||
${__default_target_info_args})
|
${__default_target_info_args})
|
||||||
set(multi_value_keywords
|
set(multi_value_keywords
|
||||||
EXTRA_CMAKE_FILES
|
EXTRA_CMAKE_FILES
|
||||||
@ -105,6 +114,7 @@ function(qt_internal_add_tool target_name)
|
|||||||
NO_INSTALL
|
NO_INSTALL
|
||||||
${arg_NO_UNITY_BUILD}
|
${arg_NO_UNITY_BUILD}
|
||||||
SOURCES ${arg_SOURCES}
|
SOURCES ${arg_SOURCES}
|
||||||
|
NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
|
||||||
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
${arg_INCLUDE_DIRECTORIES}
|
${arg_INCLUDE_DIRECTORIES}
|
||||||
@ -224,10 +234,62 @@ function(qt_internal_add_tool target_name)
|
|||||||
qt_internal_apply_staging_prefix_build_rpath_workaround()
|
qt_internal_apply_staging_prefix_build_rpath_workaround()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(arg_TRY_RUN AND WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||||
|
if(NOT arg_TRY_RUN_FLAGS)
|
||||||
|
set(arg_TRY_RUN_FLAGS "-v")
|
||||||
|
endif()
|
||||||
|
_qt_internal_add_try_run_post_build("${target_name}" "${arg_TRY_RUN_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
qt_enable_separate_debug_info(${target_name} "${install_dir}" QT_EXECUTABLE)
|
qt_enable_separate_debug_info(${target_name} "${install_dir}" QT_EXECUTABLE)
|
||||||
qt_internal_install_pdb_files(${target_name} "${install_dir}")
|
qt_internal_install_pdb_files(${target_name} "${install_dir}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(_qt_internal_add_try_run_post_build target try_run_flags)
|
||||||
|
qt_internal_get_upper_case_main_cmake_configuration(main_cmake_configuration)
|
||||||
|
get_target_property(target_out_dir ${target}
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_${main_cmake_configuration})
|
||||||
|
get_target_property(target_bin_dir ${target}
|
||||||
|
BINARY_DIR)
|
||||||
|
|
||||||
|
set(try_run_scripts_path "${target_bin_dir}/${target}_try_run.bat")
|
||||||
|
# The only reason -h is passed is because some of the tools, e.g., moc
|
||||||
|
# wait for an input without any arguments.
|
||||||
|
|
||||||
|
qt_configure_file(OUTPUT "${try_run_scripts_path}"
|
||||||
|
CONTENT "@echo off
|
||||||
|
|
||||||
|
${target_out_dir}/${target}.exe ${try_run_flags} > nul 2>&1
|
||||||
|
|
||||||
|
if \"%errorlevel%\" == \"-1073741515\" (
|
||||||
|
echo
|
||||||
|
echo '${target}' is built successfully, but some of the libraries
|
||||||
|
echo necessary for running it are missing. If you are building Qt with
|
||||||
|
echo 3rdparty libraries, make sure that you add their directory to the
|
||||||
|
echo PATH environment variable.
|
||||||
|
echo
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
echo. > ${target_bin_dir}/${target}_try_run_passed"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT
|
||||||
|
${target_bin_dir}/${target}_try_run_passed
|
||||||
|
DEPENDS
|
||||||
|
${target}
|
||||||
|
COMMAND
|
||||||
|
${CMAKE_COMMAND} -E env QT_COMMAND_LINE_PARSER_NO_GUI_MESSAGE_BOXES=1
|
||||||
|
${try_run_scripts_path}
|
||||||
|
COMMENT
|
||||||
|
"Testing ${target} by trying to run it."
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(${target}_try_run ALL
|
||||||
|
DEPENDS ${target_bin_dir}/${target}_try_run_passed)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(qt_export_tools module_name)
|
function(qt_export_tools module_name)
|
||||||
# Bail out when not building tools.
|
# Bail out when not building tools.
|
||||||
if(NOT QT_WILL_BUILD_TOOLS)
|
if(NOT QT_WILL_BUILD_TOOLS)
|
||||||
@ -287,7 +349,7 @@ function(qt_export_tools module_name)
|
|||||||
string(REGEX REPLACE "_native$" "" tool_name ${tool_name})
|
string(REGEX REPLACE "_native$" "" tool_name ${tool_name})
|
||||||
endif()
|
endif()
|
||||||
set(extra_cmake_statements "${extra_cmake_statements}
|
set(extra_cmake_statements "${extra_cmake_statements}
|
||||||
if (NOT QT_NO_CREATE_TARGETS)
|
if(NOT QT_NO_CREATE_TARGETS AND ${INSTALL_CMAKE_NAMESPACE}${target}_FOUND)
|
||||||
__qt_internal_promote_target_to_global(${INSTALL_CMAKE_NAMESPACE}::${tool_name})
|
__qt_internal_promote_target_to_global(${INSTALL_CMAKE_NAMESPACE}::${tool_name})
|
||||||
endif()
|
endif()
|
||||||
")
|
")
|
||||||
|
@ -31,6 +31,14 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
|
|||||||
list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")")
|
list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(QT_QMAKE_TARGET_MKSPEC)
|
||||||
|
list(APPEND init_platform
|
||||||
|
"if(NOT QT_QMAKE_TARGET_MKSPEC)"
|
||||||
|
" set(QT_QMAKE_TARGET_MKSPEC ${QT_QMAKE_TARGET_MKSPEC} CACHE STRING \"\")"
|
||||||
|
"endif()"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86)
|
if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86)
|
||||||
set(__qt_toolchain_common_flags_init "-m32")
|
set(__qt_toolchain_common_flags_init "-m32")
|
||||||
|
|
||||||
@ -121,14 +129,14 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
|
|||||||
endif()
|
endif()
|
||||||
if(__qt_embed_toolchain_compilers)
|
if(__qt_embed_toolchain_compilers)
|
||||||
list(APPEND init_platform "
|
list(APPEND init_platform "
|
||||||
set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\")
|
set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\")
|
||||||
set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\")
|
set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\")
|
||||||
if(NOT DEFINED CMAKE_C_COMPILER AND EXISTS \"\${__qt_initial_c_compiler}\")
|
if(NOT DEFINED CMAKE_C_COMPILER AND EXISTS \"\${__qt_initial_c_compiler}\")
|
||||||
set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\")
|
set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\")
|
||||||
endif()
|
endif()
|
||||||
if(NOT DEFINED CMAKE_CXX_COMPILER AND EXISTS \"\${__qt_initial_cxx_compiler}\")
|
if(NOT DEFINED CMAKE_CXX_COMPILER AND EXISTS \"\${__qt_initial_cxx_compiler}\")
|
||||||
set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\")
|
set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\")
|
||||||
endif()")
|
endif()")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
unset(init_additional_used_variables)
|
unset(init_additional_used_variables)
|
||||||
|
@ -6,17 +6,74 @@
|
|||||||
# This is used for writing the config.opt file.
|
# This is used for writing the config.opt file.
|
||||||
#
|
#
|
||||||
# This script takes the following arguments:
|
# This script takes the following arguments:
|
||||||
# IN_FILE: The input file. The whole command line as one string.
|
# IN_FILE: The input file. The whole command line as one string, or one argument per line.
|
||||||
|
# REDO_FILE: A file containing extra commands to be joined with IN_FILE.
|
||||||
# OUT_FILE: The output file. One argument per line.
|
# OUT_FILE: The output file. One argument per line.
|
||||||
# SKIP_ARGS: Number of arguments to skip from the front of the arguments list.
|
# SKIP_ARGS: Number of arguments to skip from the front of the arguments list.
|
||||||
# IGNORE_ARGS: List of arguments to be ignored, i.e. that are not written.
|
# IGNORE_ARGS: List of arguments to be ignored, i.e. that are not written.
|
||||||
|
#
|
||||||
|
# If the REDO_FILE is given, its parameters will be merged with IN_FILE parameters
|
||||||
|
# and be written into the OUT_FILE.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
# Read arguments from IN_FILE and separate them.
|
# Read arguments from IN_FILE and separate them.
|
||||||
file(READ "${IN_FILE}" raw_args)
|
file(READ "${IN_FILE}" raw_args)
|
||||||
|
# To catch cases where the path ends with an `\`, e.g., `-prefix "C:\Path\"`
|
||||||
|
string(REPLACE "\\\"" "\"" raw_args "${raw_args}")
|
||||||
|
string(REPLACE ";" "[[;]]" raw_args "${raw_args}")
|
||||||
|
|
||||||
separate_arguments(args NATIVE_COMMAND "${raw_args}")
|
separate_arguments(args NATIVE_COMMAND "${raw_args}")
|
||||||
|
|
||||||
|
string(REPLACE "\;" ";" args "${args}")
|
||||||
|
string(REPLACE "[[;]]" "\;" args "${args}")
|
||||||
|
|
||||||
|
if(DEFINED REDO_FILE)
|
||||||
|
file(READ "${REDO_FILE}" raw_redo_args)
|
||||||
|
separate_arguments(redo_args NATIVE_COMMAND "${raw_redo_args}")
|
||||||
|
|
||||||
|
if(args)
|
||||||
|
list(FIND args "--" args_ddash_loc)
|
||||||
|
list(FIND redo_args "--" redo_ddash_loc)
|
||||||
|
if("${redo_ddash_loc}" STREQUAL "-1")
|
||||||
|
if("${args_ddash_loc}" STREQUAL "-1")
|
||||||
|
list(LENGTH args args_ddash_loc)
|
||||||
|
endif()
|
||||||
|
# Avoid adding an empty line for an empty -redo
|
||||||
|
if(NOT "${redo_args}" STREQUAL "")
|
||||||
|
list(INSERT args ${args_ddash_loc} "${redo_args}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Handling redo's configure options
|
||||||
|
list(SUBLIST redo_args 0 ${redo_ddash_loc} redo_config_args)
|
||||||
|
if(redo_config_args)
|
||||||
|
if("${args_ddash_loc}" STREQUAL "-1")
|
||||||
|
list(APPEND args "${redo_config_args}")
|
||||||
|
else()
|
||||||
|
list(INSERT args ${args_ddash_loc} "${redo_config_args}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Handling redo's CMake options
|
||||||
|
list(LENGTH redo_args redo_args_len)
|
||||||
|
math(EXPR redo_ddash_loc "${redo_ddash_loc} + 1")
|
||||||
|
# Catch an unlikely case of -redo being called with an empty --, ie., `-redo --`
|
||||||
|
if(NOT ${redo_ddash_loc} STREQUAL ${redo_args_len})
|
||||||
|
list(SUBLIST redo_args ${redo_ddash_loc} -1 redo_cmake_args)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED redo_cmake_args)
|
||||||
|
if("${args_ddash_loc}" STREQUAL "-1")
|
||||||
|
list(APPEND args "--")
|
||||||
|
endif()
|
||||||
|
list(APPEND args "${redo_cmake_args}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
list(APPEND args "${redo_args}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Skip arguments if requested
|
# Skip arguments if requested
|
||||||
if(DEFINED SKIP_ARGS)
|
if(DEFINED SKIP_ARGS)
|
||||||
foreach(i RANGE 1 ${SKIP_ARGS})
|
foreach(i RANGE 1 ${SKIP_ARGS})
|
||||||
|
@ -17,22 +17,22 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC)
|
#if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC)
|
||||||
/* outside library → inline decl + defi */
|
/* outside library -> inline decl + defi */
|
||||||
/* static builds treat everything as part of the library, so they never inline */
|
/* static builds treat everything as part of the library, so they never inline */
|
||||||
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) inline
|
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) inline
|
||||||
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
|
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
|
||||||
#elif defined(QT_@module_define_infix@_BUILD_REMOVED_API)
|
#elif defined(QT_@module_define_infix@_BUILD_REMOVED_API)
|
||||||
/* inside library, inside removed_api.cpp:
|
/* inside library, inside removed_api.cpp:
|
||||||
* keep deprecated API → non-inline decl;
|
* keep deprecated API -> non-inline decl;
|
||||||
* remove deprecated API → inline decl;
|
* remove deprecated API -> inline decl;
|
||||||
* definition is always available */
|
* definition is always available */
|
||||||
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
|
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
|
||||||
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
|
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
|
||||||
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
|
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
|
||||||
#else
|
#else
|
||||||
/* inside library, outside removed_api.cpp:
|
/* inside library, outside removed_api.cpp:
|
||||||
* keep deprecated API → non-inline decl, no defi;
|
* keep deprecated API -> non-inline decl, no defi;
|
||||||
* remove deprecated API → inline decl, defi */
|
* remove deprecated API -> inline decl, defi */
|
||||||
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
|
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
|
||||||
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
|
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
|
||||||
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) \
|
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) \
|
||||||
|
@ -13,6 +13,11 @@ instructions:
|
|||||||
variableValue: "{{.Env.COMMON_TEST_CMAKE_ARGS}}"
|
variableValue: "{{.Env.COMMON_TEST_CMAKE_ARGS}}"
|
||||||
- !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml"
|
- !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml"
|
||||||
disable_if:
|
disable_if:
|
||||||
condition: property
|
condition: or
|
||||||
property: features
|
conditions:
|
||||||
contains_value: DisableTests
|
- condition: property
|
||||||
|
property: features
|
||||||
|
contains_value: DisableTests
|
||||||
|
- condition: property
|
||||||
|
property: features
|
||||||
|
contains_value: DoNotBuildTests
|
||||||
|
@ -34,6 +34,11 @@ instructions:
|
|||||||
variableValue: "{{.Env.COMMON_TARGET_TEST_CMAKE_ARGS}}"
|
variableValue: "{{.Env.COMMON_TARGET_TEST_CMAKE_ARGS}}"
|
||||||
- !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml"
|
- !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts.yaml"
|
||||||
disable_if:
|
disable_if:
|
||||||
condition: property
|
condition: or
|
||||||
property: features
|
conditions:
|
||||||
contains_value: DisableTests
|
- condition: property
|
||||||
|
property: features
|
||||||
|
contains_value: DisableTests
|
||||||
|
- condition: property
|
||||||
|
property: features
|
||||||
|
contains_value: DoNotBuildTests
|
||||||
|
@ -61,9 +61,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR
|
variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR
|
||||||
variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}host{{.Env.CI_PATH_SEP}}bin"
|
variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}host{{.Env.CI_PATH_SEP}}bin"
|
||||||
@ -73,9 +78,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: DESTDIR
|
variableName: DESTDIR
|
||||||
@ -123,9 +133,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR
|
variableName: COIN_CMAKE_INSTALL_LIBEXEC_DIR
|
||||||
variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}target{{.Env.CI_PATH_SEP}}bin"
|
variableValue: "{{.InstallDir}}{{.Env.CI_PATH_SEP}}target{{.Env.CI_PATH_SEP}}bin"
|
||||||
@ -135,9 +150,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- !include "{{qt/qtbase}}/call_target_install.yaml"
|
- !include "{{qt/qtbase}}/call_target_install.yaml"
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: DESTDIR
|
variableName: DESTDIR
|
||||||
|
@ -47,9 +47,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
||||||
variableValue: "{{.BuildDir}}{{.Env.CI_PATH_SEP}}bin"
|
variableValue: "{{.BuildDir}}{{.Env.CI_PATH_SEP}}bin"
|
||||||
@ -59,9 +64,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: DESTDIR
|
variableName: DESTDIR
|
||||||
@ -124,9 +134,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
||||||
variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin"
|
variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin"
|
||||||
@ -136,9 +151,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- !include "{{qt/qtbase}}/call_target_install.yaml"
|
- !include "{{qt/qtbase}}/call_target_install.yaml"
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: DESTDIR
|
variableName: DESTDIR
|
||||||
|
@ -41,9 +41,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
variableName: COIN_CMAKE_BUILD_LIBEXEC_DIR
|
||||||
variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin"
|
variableValue: "{{.Env.COIN_CMAKE_BUILD_DIR}}{{.Env.CI_PATH_SEP}}bin"
|
||||||
@ -53,9 +58,14 @@ instructions:
|
|||||||
- condition: property
|
- condition: property
|
||||||
property: host.os
|
property: host.os
|
||||||
equals_value: Windows
|
equals_value: Windows
|
||||||
- condition: property
|
- condition: and
|
||||||
property: target.osVersion
|
conditions:
|
||||||
not_in_values: [WebAssembly, Android_ANY]
|
- condition: property
|
||||||
|
property: target.os
|
||||||
|
not_equals_value: QNX
|
||||||
|
- condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
not_in_values: [WebAssembly, Android_ANY]
|
||||||
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
- !include "{{qt/qtbase}}/call_host_install.yaml"
|
||||||
- type: EnvironmentVariable
|
- type: EnvironmentVariable
|
||||||
variableName: DESTDIR
|
variableName: DESTDIR
|
||||||
|
@ -305,6 +305,14 @@ instructions:
|
|||||||
condition: property
|
condition: property
|
||||||
property: target.osVersion
|
property: target.osVersion
|
||||||
in_values: [QEMU]
|
in_values: [QEMU]
|
||||||
|
# This fixes an issue where binfmts is sometimes disabled on the test VMs
|
||||||
|
- type: ExecuteCommand
|
||||||
|
command: sudo update-binfmts --enable
|
||||||
|
userMessageOnFailure: "Failed to enable binfmts"
|
||||||
|
enable_if:
|
||||||
|
condition: property
|
||||||
|
property: target.osVersion
|
||||||
|
equals_value: QEMU
|
||||||
|
|
||||||
# Windows on Arm, cross-compilation with MSVC
|
# Windows on Arm, cross-compilation with MSVC
|
||||||
- type: Group
|
- type: Group
|
||||||
|
300
conanfile.py
@ -1,300 +0,0 @@
|
|||||||
# Copyright (C) 2021 The Qt Company Ltd.
|
|
||||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
from conans import ConanFile, tools
|
|
||||||
from conans.errors import ConanInvalidConfiguration
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import shutil
|
|
||||||
from functools import lru_cache
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Union
|
|
||||||
|
|
||||||
|
|
||||||
class QtConanError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def add_cmake_prefix_path(conan_file: ConanFile, dep: str) -> None:
|
|
||||||
if dep not in conan_file.deps_cpp_info.deps:
|
|
||||||
raise QtConanError("Unable to find dependency: {0}".format(dep))
|
|
||||||
dep_cpp_info = conan_file.deps_cpp_info[dep]
|
|
||||||
cmake_args_str = str(conan_file.options.get_safe("cmake_args_qtbase", default=""))
|
|
||||||
formatted_cmake_args_str = conan_file._shared.append_cmake_arg(
|
|
||||||
cmake_args_str, "CMAKE_PREFIX_PATH", dep_cpp_info.rootpath
|
|
||||||
)
|
|
||||||
print("Adjusted cmake args for qtbase build: {0}".format(formatted_cmake_args_str))
|
|
||||||
setattr(conan_file.options, "cmake_args_qtbase", formatted_cmake_args_str)
|
|
||||||
|
|
||||||
|
|
||||||
def _build_qtbase(conan_file: ConanFile):
|
|
||||||
# we call the Qt's configure(.bat) directly
|
|
||||||
script = Path("configure.bat") if tools.os_info.is_windows else Path("configure")
|
|
||||||
configure = Path(conan_file.build_folder).joinpath(script).resolve(strict=True)
|
|
||||||
|
|
||||||
if conan_file.options.get_safe("icu", default=False):
|
|
||||||
# we need to tell Qt build system where to find the ICU
|
|
||||||
add_cmake_prefix_path(conan_file, dep="icu")
|
|
||||||
|
|
||||||
# convert the Conan options to Qt configure(.bat) arguments
|
|
||||||
parser = conan_file._qt_option_parser
|
|
||||||
qt_configure_options = parser.convert_conan_options_to_qt_options(conan_file.options)
|
|
||||||
cmd = " ".join(
|
|
||||||
[str(configure), " ".join(qt_configure_options), "-prefix", conan_file.package_folder]
|
|
||||||
)
|
|
||||||
cmake_args = parser.get_cmake_args_for_configure(conan_file.options)
|
|
||||||
if cmake_args:
|
|
||||||
cmd += " -- {0}".format(" ".join(cmake_args))
|
|
||||||
conan_file.output.info("Calling: {0}".format(cmd))
|
|
||||||
conan_file.run(cmd)
|
|
||||||
|
|
||||||
cmd = " ".join(["cmake", "--build", ".", "--parallel"])
|
|
||||||
conan_file.output.info("Calling: {0}".format(cmd))
|
|
||||||
conan_file.run(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=8)
|
|
||||||
def _parse_qt_version_by_key(key: str) -> str:
|
|
||||||
with open(Path(__file__).parent.resolve() / ".cmake.conf") as f:
|
|
||||||
m = re.search(fr'{key} .*"(.*)"', f.read())
|
|
||||||
return m.group(1) if m else ""
|
|
||||||
|
|
||||||
|
|
||||||
def _get_qt_minor_version() -> str:
|
|
||||||
return ".".join(_parse_qt_version_by_key("QT_REPO_MODULE_VERSION").split(".")[:2])
|
|
||||||
|
|
||||||
|
|
||||||
class QtBase(ConanFile):
|
|
||||||
name = "qtbase"
|
|
||||||
license = "LGPL-3.0, GPL-2.0+, Commercial Qt License Agreement"
|
|
||||||
author = "The Qt Company <https://www.qt.io/contact-us>"
|
|
||||||
url = "https://code.qt.io/cgit/qt/qtbase.git"
|
|
||||||
description = "Qt6 core framework libraries and tools."
|
|
||||||
topics = ("qt", "qt6")
|
|
||||||
settings = "os", "compiler", "arch", "build_type"
|
|
||||||
_qt_option_parser = None
|
|
||||||
options = None
|
|
||||||
default_options = None
|
|
||||||
exports_sources = "*", "!conan*.*"
|
|
||||||
# use commit ID as the RREV (recipe revision)
|
|
||||||
revision_mode = "scm"
|
|
||||||
python_requires = "qt-conan-common/{0}@qt/everywhere".format(_get_qt_minor_version())
|
|
||||||
short_paths = True
|
|
||||||
_shared = None
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
self._shared = self.python_requires["qt-conan-common"].module
|
|
||||||
self._qt_option_parser = self._shared.QtOptionParser(Path(__file__).parent.resolve())
|
|
||||||
self.options = self._qt_option_parser.get_qt_conan_options()
|
|
||||||
self.default_options = self._qt_option_parser.get_default_qt_conan_options()
|
|
||||||
|
|
||||||
def set_version(self):
|
|
||||||
# Executed during "conan export" i.e. in source tree
|
|
||||||
_ver = _parse_qt_version_by_key("QT_REPO_MODULE_VERSION")
|
|
||||||
_prerelease = _parse_qt_version_by_key("QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT")
|
|
||||||
self.version = _ver + "-" + _prerelease if _prerelease else _ver
|
|
||||||
|
|
||||||
def export(self):
|
|
||||||
self.copy("configure_options.json")
|
|
||||||
self.copy("configure_features.txt")
|
|
||||||
self.copy(".cmake.conf")
|
|
||||||
conf = self._shared.qt_sw_versions_config_folder() / self._shared.qt_sw_versions_config_name()
|
|
||||||
if not conf.exists():
|
|
||||||
# If using "conan export" outside Qt CI provisioned machines
|
|
||||||
print("Warning: Couldn't find '{0}'. 3rd party dependencies skipped.".format(conf))
|
|
||||||
else:
|
|
||||||
shutil.copy2(conf, self.export_folder)
|
|
||||||
|
|
||||||
def requirements(self):
|
|
||||||
# list of tuples, (package_name, fallback version)
|
|
||||||
optional_requirements = [("icu", "56.1")]
|
|
||||||
for req_name, req_ver_fallback in optional_requirements:
|
|
||||||
if self.options.get_safe(req_name, default=False) == True:
|
|
||||||
# Note! If this conan package is being "conan export"ed outside Qt CI and the
|
|
||||||
# sw versions .ini file is not present then it will fall-back to default version
|
|
||||||
ver = self._shared.parse_qt_sw_pkg_dependency(
|
|
||||||
config_folder=Path(self.recipe_folder),
|
|
||||||
package_name=req_name,
|
|
||||||
target_os=str(self.settings.os),
|
|
||||||
)
|
|
||||||
if not ver:
|
|
||||||
print(
|
|
||||||
"Warning: Using fallback version '{0}' for: {1}".format(
|
|
||||||
req_name, req_ver_fallback
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ver = req_ver_fallback
|
|
||||||
requirement = "{0}/{1}@qt/everywhere".format(req_name, ver)
|
|
||||||
print("Setting 3rd party package requirement: {0}".format(requirement))
|
|
||||||
self.requires(requirement)
|
|
||||||
|
|
||||||
def _resolve_qt_host_path(self) -> Union[str, None]:
|
|
||||||
"""
|
|
||||||
Attempt to resolve QT_HOST_PATH.
|
|
||||||
|
|
||||||
When cross-building the user needs to pass 'qt_host_path' which is transformed to
|
|
||||||
QT_HOST_PATH later on. Resolve the exact path if possible.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
string: The resolved QT_HOST_PATH or None if unable to determine it.
|
|
||||||
"""
|
|
||||||
_host_p = self.options.get_safe("qt_host_path")
|
|
||||||
if _host_p:
|
|
||||||
return str(Path(os.path.expandvars(str(_host_p))).expanduser().resolve(strict=True))
|
|
||||||
else:
|
|
||||||
print("Warning: 'qt_host_path' option was not given in cross-build context")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def configure(self):
|
|
||||||
if self.settings.compiler == "gcc" and tools.Version(self.settings.compiler.version) < "8":
|
|
||||||
raise ConanInvalidConfiguration("Qt6 does not support GCC before 8")
|
|
||||||
|
|
||||||
def _set_default_if_not_set(option_name: str, option_value: bool) -> None:
|
|
||||||
# let it fail if option name does not exist, it means the recipe is not up to date
|
|
||||||
if self.options.get_safe(option_name) in [None, "None"]:
|
|
||||||
setattr(self.options, option_name, option_value)
|
|
||||||
|
|
||||||
def _set_build_type(build_type: str) -> None:
|
|
||||||
if self.settings.build_type != build_type:
|
|
||||||
msg = (
|
|
||||||
"The build_type '{0}' changed to '{1}'. Please check your Settings and "
|
|
||||||
"Options. The used Qt options enforce '{2}' as a build_type. ".format(
|
|
||||||
self.settings.build_type, build_type, build_type
|
|
||||||
)
|
|
||||||
)
|
|
||||||
raise QtConanError(msg)
|
|
||||||
self.settings.build_type = build_type
|
|
||||||
|
|
||||||
def _check_mutually_exclusive_options(options: Dict[str, bool]) -> None:
|
|
||||||
if list(options.values()).count(True) > 1:
|
|
||||||
raise QtConanError(
|
|
||||||
"These Qt options are mutually exclusive: {0}"
|
|
||||||
". Choose only one of them and try again.".format(list(options.keys()))
|
|
||||||
)
|
|
||||||
|
|
||||||
default_options = ["shared", "gui", "widgets", "accessibility", "system_proxies", "ico"]
|
|
||||||
|
|
||||||
if self.settings.os == "Macos":
|
|
||||||
default_options.append("framework")
|
|
||||||
|
|
||||||
for item in default_options:
|
|
||||||
_set_default_if_not_set(item, True)
|
|
||||||
|
|
||||||
release = self.options.get_safe("release", default=False)
|
|
||||||
debug = self.options.get_safe("debug", default=False)
|
|
||||||
debug_and_release = self.options.get_safe("debug_and_release", default=False)
|
|
||||||
force_debug_info = self.options.get_safe("force_debug_info", default=False)
|
|
||||||
optimize_size = self.options.get_safe("optimize_size", default=False)
|
|
||||||
|
|
||||||
# these options are mutually exclusive options so do a sanity check
|
|
||||||
_check_mutually_exclusive_options(
|
|
||||||
{"release": release, "debug": debug, "debug_and_release": debug_and_release}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prioritize Qt's configure options over Settings.build_type
|
|
||||||
if debug_and_release == True:
|
|
||||||
# Qt build system will build both debug and release binaries
|
|
||||||
if force_debug_info == True:
|
|
||||||
_set_build_type("RelWithDebInfo")
|
|
||||||
else:
|
|
||||||
_set_build_type("Release")
|
|
||||||
elif release == True:
|
|
||||||
_check_mutually_exclusive_options(
|
|
||||||
{"force_debug_info": force_debug_info, "optimize_size": optimize_size}
|
|
||||||
)
|
|
||||||
if force_debug_info == True:
|
|
||||||
_set_build_type("RelWithDebInfo")
|
|
||||||
elif optimize_size == True:
|
|
||||||
_set_build_type("MinSizeRel")
|
|
||||||
else:
|
|
||||||
_set_build_type("Release")
|
|
||||||
elif debug == True:
|
|
||||||
_set_build_type("Debug")
|
|
||||||
else:
|
|
||||||
# As a fallback set the build type for Qt configure based on the 'build_type'
|
|
||||||
# defined in the conan build settings
|
|
||||||
build_type = self.settings.get_safe("build_type")
|
|
||||||
if build_type in [None, "None"]:
|
|
||||||
# set default that mirror the configure(.bat) default values
|
|
||||||
self.options.release = True
|
|
||||||
self.settings.build_type = "Release"
|
|
||||||
elif build_type == "Release":
|
|
||||||
self.options.release = True
|
|
||||||
elif build_type == "Debug":
|
|
||||||
self.options.debug = True
|
|
||||||
elif build_type == "RelWithDebInfo":
|
|
||||||
self.options.release = True
|
|
||||||
self.options.force_debug_info = True
|
|
||||||
elif build_type == "MinSizeRel":
|
|
||||||
self.options.release = True
|
|
||||||
self.options.optimize_size = True
|
|
||||||
else:
|
|
||||||
raise QtConanError("Unknown build_type: {0}".format(self.settings.build_type))
|
|
||||||
|
|
||||||
if self.settings.os == "Android":
|
|
||||||
if self.options.get_safe("android_sdk_version") == None:
|
|
||||||
cmake_args_qtbase = str(self.options.get_safe("cmake_args_qtbase"))
|
|
||||||
sdk_ver = self._shared.parse_android_sdk_version(cmake_args_qtbase)
|
|
||||||
if sdk_ver:
|
|
||||||
print("'android_sdk_version' not given. Deduced version: {0}".format(sdk_ver))
|
|
||||||
self.options.android_sdk_version = sdk_ver
|
|
||||||
else:
|
|
||||||
# TODO, for now we have no clean means to query the Android SDK version from
|
|
||||||
# Qt build system so we just exclude the "android_sdk" from the package_id.
|
|
||||||
print("Can't deduce 'android_sdk_version'. Excluding it from 'package_id'")
|
|
||||||
delattr(self.info.options, "android_sdk_version")
|
|
||||||
if self.options.get_safe("android_ndk_version") == None:
|
|
||||||
ndk_ver = str(self.options.get_safe("android_ndk"))
|
|
||||||
ndk_ver = self._shared.parse_android_ndk_version(Path(ndk_ver, strict=True))
|
|
||||||
print("'android_ndk_version' not given. Deduced version: {0}".format(ndk_ver))
|
|
||||||
self.options.android_ndk_version = ndk_ver
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
self._shared.build_env_wrap(self, _build_qtbase)
|
|
||||||
|
|
||||||
def package(self):
|
|
||||||
self._shared.call_install(self)
|
|
||||||
|
|
||||||
def package_info(self):
|
|
||||||
self._shared.package_info(self)
|
|
||||||
if tools.cross_building(conanfile=self):
|
|
||||||
qt_host_path = self._resolve_qt_host_path()
|
|
||||||
if qt_host_path:
|
|
||||||
self.env_info.QT_HOST_PATH.append(qt_host_path)
|
|
||||||
|
|
||||||
def package_id(self):
|
|
||||||
# https://docs.conan.io/en/latest/creating_packages/define_abi_compatibility.html
|
|
||||||
|
|
||||||
# The package_revision_mode() is too strict for Qt CI. This mode includes artifacts
|
|
||||||
# checksum in package_id which is problematic in Qt CI re-runs (re-run flaky
|
|
||||||
# build) which contain different build timestamps (cmake) which end up in library
|
|
||||||
# files -> different package_id.
|
|
||||||
self.info.requires.recipe_revision_mode()
|
|
||||||
|
|
||||||
# Enable 'qt-conan-common' updates on client side with $conan install .. --update
|
|
||||||
self.info.python_requires.recipe_revision_mode()
|
|
||||||
|
|
||||||
# Remove those configure(.bat) options which should not affect package_id.
|
|
||||||
# These point to local file system paths and in order to re-use pre-built
|
|
||||||
# binaries (by Qt CI) by others these should not affect the 'package_id'
|
|
||||||
# as those probably differ on each machine
|
|
||||||
rm_list = [
|
|
||||||
"sdk",
|
|
||||||
"qpa",
|
|
||||||
"translationsdir",
|
|
||||||
"headersclean",
|
|
||||||
"qt_host_path",
|
|
||||||
"android_sdk",
|
|
||||||
"android_ndk",
|
|
||||||
]
|
|
||||||
for item in rm_list:
|
|
||||||
if item in self.info.options:
|
|
||||||
delattr(self.info.options, item)
|
|
||||||
# filter also those cmake options that should not end up in the package_id
|
|
||||||
if hasattr(self.info.options, "cmake_args_qtbase"):
|
|
||||||
_filter = self._shared.filter_cmake_args_for_package_id
|
|
||||||
self.info.options.cmake_args_qtbase = _filter(self.info.options.cmake_args_qtbase)
|
|
||||||
|
|
||||||
def deploy(self):
|
|
||||||
self.copy("*") # copy from current package
|
|
||||||
self.copy_deps("*") # copy from dependencies
|
|
144
configure
vendored
@ -8,14 +8,18 @@
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
# the directory of this script is the "source tree"
|
# the directory of this script is the "source tree"
|
||||||
relpath=`dirname $0`
|
relpath=`dirname "$0"`
|
||||||
relpath=`(cd "$relpath"; /bin/pwd)`
|
relpath=`(cd "$relpath"; /bin/pwd)`
|
||||||
# the current directory is the "build tree" or "object tree"
|
# the current directory is the "build tree" or "object tree"
|
||||||
outpath=`/bin/pwd`
|
outpath=`/bin/pwd`
|
||||||
|
outpathPrefix=$outpath
|
||||||
|
|
||||||
# do this early so we don't store it in config.status
|
# do this early so we don't store it in config.status
|
||||||
CFG_TOPLEVEL=
|
CFG_TOPLEVEL=
|
||||||
outpathPrefix=
|
|
||||||
|
SAVED_IFS=$IFS
|
||||||
|
IFS='
|
||||||
|
'
|
||||||
|
|
||||||
checkTopLevelBuild()
|
checkTopLevelBuild()
|
||||||
{
|
{
|
||||||
@ -23,7 +27,7 @@ checkTopLevelBuild()
|
|||||||
if [ x"$1" = x"-top-level" ]; then
|
if [ x"$1" = x"-top-level" ]; then
|
||||||
CFG_TOPLEVEL=yes
|
CFG_TOPLEVEL=yes
|
||||||
relpathMangled=`dirname "$relpath"`
|
relpathMangled=`dirname "$relpath"`
|
||||||
outpathPrefix=../
|
outpathPrefix="$outpathPrefix/.."
|
||||||
else
|
else
|
||||||
if [ -f ../.qmake.super ]; then
|
if [ -f ../.qmake.super ]; then
|
||||||
echo >&2 "ERROR: You cannot configure qtbase separately within a top-level build."
|
echo >&2 "ERROR: You cannot configure qtbase separately within a top-level build."
|
||||||
@ -35,41 +39,26 @@ checkTopLevelBuild()
|
|||||||
OPT_CMDLINE= # expanded version for the script
|
OPT_CMDLINE= # expanded version for the script
|
||||||
determineOptFilePath()
|
determineOptFilePath()
|
||||||
{
|
{
|
||||||
|
> "${outpathPrefix}/config.redo.in"
|
||||||
set -f # suppress globbing in for loop
|
set -f # suppress globbing in for loop
|
||||||
SAVED_IFS=$IFS
|
|
||||||
IFS='
|
|
||||||
'
|
|
||||||
for i in "$@"; do
|
for i in "$@"; do
|
||||||
if [ x"$i" = x"-top-level" ]; then
|
if [ x"$i" = x"-top-level" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
case $i in
|
case $i in
|
||||||
-redo|--redo)
|
-redo|--redo)
|
||||||
optfile=${outpathPrefix}config.opt
|
optfile=${outpathPrefix}/config.opt
|
||||||
if test -n "$CFG_TOPLEVEL" && ! test -f $optfile; then
|
if ! test -f "$optfile"; then
|
||||||
optfile=config.opt
|
|
||||||
fi
|
|
||||||
if ! test -f $optfile; then
|
|
||||||
echo >&2 "No config.opt present - cannot redo configuration."
|
echo >&2 "No config.opt present - cannot redo configuration."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
for a in `cat $optfile`; do
|
|
||||||
OPT_CMDLINE="$OPT_CMDLINE
|
|
||||||
$a"
|
|
||||||
done
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
OPT_CMDLINE="$OPT_CMDLINE
|
# If redo-ing, write the rest of parameters into the config.redo.in file
|
||||||
$i"
|
echo \"$i\" >> "${outpathPrefix}/config.redo.in"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
set --
|
|
||||||
for i in $OPT_CMDLINE; do
|
|
||||||
set -- "$@" "$i"
|
|
||||||
done
|
|
||||||
set +f
|
|
||||||
IFS=$SAVED_IFS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -88,80 +77,10 @@ while [ "$#" -gt 0 ]; do
|
|||||||
CURRENT_OPT="$1"
|
CURRENT_OPT="$1"
|
||||||
case "$1" in
|
case "$1" in
|
||||||
#Autoconf style options
|
#Autoconf style options
|
||||||
--enable-*)
|
|
||||||
VAR=`echo $1 | sed 's,^--enable-\(.*\),\1,'`
|
|
||||||
VAL=yes
|
|
||||||
;;
|
|
||||||
--disable-*)
|
|
||||||
VAR=`echo $1 | sed 's,^--disable-\(.*\),\1,'`
|
|
||||||
VAL=no
|
|
||||||
;;
|
|
||||||
--*=*)
|
|
||||||
VAR=`echo $1 | sed 's,^--\(.*\)=.*,\1,'`
|
|
||||||
VAL=`echo $1 | sed 's,^--.*=\(.*\),\1,'`
|
|
||||||
;;
|
|
||||||
--no-*)
|
|
||||||
VAR=`echo $1 | sed 's,^--no-\(.*\),\1,'`
|
|
||||||
VAL=no
|
|
||||||
;;
|
|
||||||
--*)
|
--*)
|
||||||
VAR=`echo $1 | sed 's,^--\(.*\),\1,'`
|
VAR=`echo $1 | sed 's,^--\(.*\),\1,'`
|
||||||
VAL=yes
|
VAL=yes
|
||||||
;;
|
;;
|
||||||
#Qt plugin options
|
|
||||||
-no-*-*|-plugin-*-*|-qt-*-*)
|
|
||||||
VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'`
|
|
||||||
VAL=`echo $1 | sed 's,^-\([^-]*\).*,\1,'`
|
|
||||||
;;
|
|
||||||
#Qt style no options
|
|
||||||
-no-*)
|
|
||||||
VAR=`echo $1 | sed 's,^-no-\(.*\),\1,'`
|
|
||||||
VAL=no
|
|
||||||
;;
|
|
||||||
#Qt style options that pass an argument
|
|
||||||
-prefix| \
|
|
||||||
-docdir| \
|
|
||||||
-headerdir| \
|
|
||||||
-plugindir| \
|
|
||||||
-qmldir| \
|
|
||||||
-archdatadir| \
|
|
||||||
-datadir| \
|
|
||||||
-libdir| \
|
|
||||||
-bindir| \
|
|
||||||
-libexecdir| \
|
|
||||||
-translationdir| \
|
|
||||||
-sysconfdir| \
|
|
||||||
-examplesdir| \
|
|
||||||
-testsdir| \
|
|
||||||
-hostdatadir| \
|
|
||||||
-extprefix| \
|
|
||||||
-sysroot| \
|
|
||||||
-make| \
|
|
||||||
-nomake| \
|
|
||||||
-skip| \
|
|
||||||
-platform| \
|
|
||||||
-xplatform| \
|
|
||||||
-device| \
|
|
||||||
-device-option| \
|
|
||||||
-sdk| \
|
|
||||||
-android-sdk| \
|
|
||||||
-android-ndk| \
|
|
||||||
-android-ndk-platform| \
|
|
||||||
-android-arch)
|
|
||||||
VAR=`echo $1 | sed 's,^-\(.*\),\1,'`
|
|
||||||
shift
|
|
||||||
VAL="$1"
|
|
||||||
;;
|
|
||||||
#Qt style complex options in one command
|
|
||||||
-enable-*|-disable-*)
|
|
||||||
VAR=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'`
|
|
||||||
VAL=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'`
|
|
||||||
;;
|
|
||||||
#Qt Builtin/System style options
|
|
||||||
-no-*|-system-*|-qt-*)
|
|
||||||
VAR=`echo $1 | sed 's,^-[^-]*-\(.*\),\1,'`
|
|
||||||
VAL=`echo $1 | sed 's,^-\([^-]*\)-.*,\1,'`
|
|
||||||
;;
|
|
||||||
#General options, including Qt style yes options
|
#General options, including Qt style yes options
|
||||||
-*)
|
-*)
|
||||||
VAR=`echo $1 | sed 's,^-\(.*\),\1,'`
|
VAR=`echo $1 | sed 's,^-\(.*\),\1,'`
|
||||||
@ -176,24 +95,16 @@ while [ "$#" -gt 0 ]; do
|
|||||||
|
|
||||||
shift
|
shift
|
||||||
|
|
||||||
UNKNOWN_OPT=no
|
|
||||||
case "$VAR" in
|
case "$VAR" in
|
||||||
h|help)
|
h|help)
|
||||||
if [ "$VAL" = "yes" ]; then
|
if [ "$VAL" = "yes" ]; then
|
||||||
OPT_HELP="$VAL"
|
OPT_HELP="$VAL"
|
||||||
else
|
|
||||||
UNKNOWN_OPT=yes
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
if [ "$UNKNOWN_OPT" = "yes" ]; then
|
|
||||||
echo "${CURRENT_OPT}: invalid command-line switch"
|
|
||||||
ERROR=yes
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
[ "x$ERROR" = "xyes" ] && exit 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@ -222,18 +133,27 @@ parseCommandline "$@"
|
|||||||
handleHelp
|
handleHelp
|
||||||
determineOptFilePath "$@"
|
determineOptFilePath "$@"
|
||||||
|
|
||||||
|
optfilepath=${outpathPrefix}/config.opt
|
||||||
|
opttmpfilepath=${outpathPrefix}/config.opt.in
|
||||||
|
|
||||||
|
redofilepath=${outpathPrefix}/config.redo
|
||||||
|
redotmpfilepath=${outpathPrefix}/config.redo.in
|
||||||
|
|
||||||
fresh_requested_arg=
|
fresh_requested_arg=
|
||||||
optfilename=config.opt
|
|
||||||
if [ -z "$optfile" ]; then # only write optfile if not currently redoing
|
if [ -z "$optfile" ]; then # only write optfile if not currently redoing
|
||||||
optfilepath=${outpathPrefix}${optfilename}
|
> "$opttmpfilepath"
|
||||||
> "$optfilepath"
|
> "$redotmpfilepath"
|
||||||
for arg in "$@"; do
|
|
||||||
if [ "$arg" = "-top-level" ]; then
|
for arg in "$@"; do echo \"$arg\" >> "$opttmpfilepath"; done
|
||||||
continue
|
|
||||||
fi
|
cmake -DIN_FILE="${opttmpfilepath}" -DOUT_FILE="${optfilepath}" -DIGNORE_ARGS=-top-level -P "${relpath}/cmake/QtWriteArgsFile.cmake"
|
||||||
echo $arg >> "$optfilepath"
|
|
||||||
done
|
|
||||||
else
|
else
|
||||||
|
# Rewriting config.opt into config.opt.in anyway. Allows for direct manipulation of config.opt
|
||||||
|
> "$opttmpfilepath"
|
||||||
|
for arg in `cat $optfile`; do echo \"$arg\" >> "$opttmpfilepath"; done
|
||||||
|
|
||||||
|
cmake -DIN_FILE="${opttmpfilepath}" -DREDO_FILE="${redotmpfilepath}" -DOUT_FILE="${redofilepath}" -DIGNORE_ARGS=-top-level -P "${relpath}/cmake/QtWriteArgsFile.cmake"
|
||||||
|
optfilepath=${redofilepath}
|
||||||
fresh_requested_arg=-DFRESH_REQUESTED=TRUE
|
fresh_requested_arg=-DFRESH_REQUESTED=TRUE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -243,4 +163,6 @@ if [ -n "$CFG_TOPLEVEL" ]; then
|
|||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cmake "-DOPTFILE=$optfilename" $top_level_arg $fresh_requested_arg -P "$relpath/cmake/QtProcessConfigureArgs.cmake"
|
cmake "-DOPTFILE=${optfilepath}" ${top_level_arg} ${fresh_requested_arg} -P "${relpath}/cmake/QtProcessConfigureArgs.cmake"
|
||||||
|
|
||||||
|
IFS=$SAVED_IFS
|
||||||
|
@ -65,9 +65,8 @@ goto doneargs
|
|||||||
|
|
||||||
:redo
|
:redo
|
||||||
if not exist "%TOPQTDIR%\config.opt" goto redoerr
|
if not exist "%TOPQTDIR%\config.opt" goto redoerr
|
||||||
set rargs=
|
echo %ARGS% > %TOPQTDIR%\config.redo.in
|
||||||
for /f "usebackq delims=" %%i in ("%TOPQTDIR%\config.opt") do set rargs=!rargs! "%%i"
|
set redoing=""
|
||||||
call :doargs %rargs%
|
|
||||||
goto nextarg
|
goto nextarg
|
||||||
:redoerr
|
:redoerr
|
||||||
echo No config.opt present - cannot redo configuration. >&2
|
echo No config.opt present - cannot redo configuration. >&2
|
||||||
@ -78,15 +77,26 @@ goto doneargs
|
|||||||
cd "%TOPQTDIR%"
|
cd "%TOPQTDIR%"
|
||||||
|
|
||||||
rem Write config.opt if we're not currently -redo'ing
|
rem Write config.opt if we're not currently -redo'ing
|
||||||
|
set OPT_FILE_PATH=%TOPQTDIR%\config.opt
|
||||||
|
set OPT_TMP_FILE_PATH=%TOPQTDIR%\config.opt.in
|
||||||
|
set REDO_FILE_PATH=%TOPQTDIR%\config.redo
|
||||||
|
set REDO_TMP_FILE_PATH=%TOPQTDIR%\config.redo.in
|
||||||
set FRESH_REQUESTED_ARG=
|
set FRESH_REQUESTED_ARG=
|
||||||
if "!rargs!" == "" (
|
if not defined redoing (
|
||||||
echo.%*>config.opt.in
|
echo.%*>"%OPT_TMP_FILE_PATH%"
|
||||||
cmake -DIN_FILE=config.opt.in -DOUT_FILE=config.opt -DIGNORE_ARGS=-top-level -P "%QTSRC%\cmake\QtWriteArgsFile.cmake"
|
|
||||||
) else if NOT "!rargs!" == "" (
|
cmake -DIN_FILE="%OPT_TMP_FILE_PATH%" -DOUT_FILE="%OPT_FILE_PATH%" -DIGNORE_ARGS=-top-level -P "%QTSRC%\cmake\QtWriteArgsFile.cmake"
|
||||||
|
) else (
|
||||||
|
echo. 2> "%OPT_TMP_FILE_PATH%"
|
||||||
|
for /F "usebackq tokens=*" %%A in ("%OPT_FILE_PATH%") do echo "%%A" >> "%OPT_TMP_FILE_PATH%"
|
||||||
|
|
||||||
|
cmake -DIN_FILE="%OPT_TMP_FILE_PATH%" -DREDO_FILE="%REDO_TMP_FILE_PATH%" -DOUT_FILE="%REDO_FILE_PATH%" -DIGNORE_ARGS="-top-level;-redo;--redo" -P "%QTSRC%\cmake\QtWriteArgsFile.cmake"
|
||||||
|
|
||||||
|
set OPT_FILE_PATH=%REDO_FILE_PATH%
|
||||||
set FRESH_REQUESTED_ARG=-DFRESH_REQUESTED=TRUE
|
set FRESH_REQUESTED_ARG=-DFRESH_REQUESTED=TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
rem Launch CMake-based configure
|
rem Launch CMake-based configure
|
||||||
set TOP_LEVEL_ARG=
|
set TOP_LEVEL_ARG=
|
||||||
if %TOPLEVEL% == true set TOP_LEVEL_ARG=-DTOP_LEVEL=TRUE
|
if %TOPLEVEL% == true set TOP_LEVEL_ARG=-DTOP_LEVEL=TRUE
|
||||||
cmake -DOPTFILE=config.opt %TOP_LEVEL_ARG% %FRESH_REQUESTED_ARG% -P "%QTSRC%\cmake\QtProcessConfigureArgs.cmake"
|
cmake -DOPTFILE="%OPT_FILE_PATH%" %TOP_LEVEL_ARG% %FRESH_REQUESTED_ARG% -P "%QTSRC%\cmake\QtProcessConfigureArgs.cmake"
|
||||||
|
@ -22,6 +22,7 @@ qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpen
|
|||||||
# openssl_headers
|
# openssl_headers
|
||||||
# OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1
|
# OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1
|
||||||
qt_config_compile_test(opensslv11_headers
|
qt_config_compile_test(opensslv11_headers
|
||||||
|
LABEL "opensslv11_headers"
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
WrapOpenSSLHeaders::WrapOpenSSLHeaders
|
WrapOpenSSLHeaders::WrapOpenSSLHeaders
|
||||||
CODE
|
CODE
|
||||||
@ -46,6 +47,7 @@ qt_find_package(WrapOpenSSL PROVIDED_TARGETS WrapOpenSSL::WrapOpenSSL MODULE_NAM
|
|||||||
# openssl
|
# openssl
|
||||||
# OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1
|
# OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1
|
||||||
qt_config_compile_test(opensslv11
|
qt_config_compile_test(opensslv11
|
||||||
|
LABEL "opensslv11"
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
WrapOpenSSL::WrapOpenSSL
|
WrapOpenSSL::WrapOpenSSL
|
||||||
CODE
|
CODE
|
||||||
@ -70,6 +72,7 @@ SSL_free(SSL_new(0));
|
|||||||
# opensslv30
|
# opensslv30
|
||||||
# openssl_headers
|
# openssl_headers
|
||||||
qt_config_compile_test(opensslv30_headers
|
qt_config_compile_test(opensslv30_headers
|
||||||
|
LABEL "opensslv30_headers"
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
WrapOpenSSLHeaders::WrapOpenSSLHeaders
|
WrapOpenSSLHeaders::WrapOpenSSLHeaders
|
||||||
CODE
|
CODE
|
||||||
@ -87,6 +90,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
")
|
")
|
||||||
qt_config_compile_test(opensslv30
|
qt_config_compile_test(opensslv30
|
||||||
|
LABEL "opensslv30"
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
WrapOpenSSL::WrapOpenSSL
|
WrapOpenSSL::WrapOpenSSL
|
||||||
CODE
|
CODE
|
||||||
@ -331,11 +335,13 @@ int main(void)
|
|||||||
"# FIXME: qmake: ['TEMPLATE = lib', 'CONFIG += dll bsymbolic_functions', 'isEmpty(QMAKE_LFLAGS_BSYMBOLIC_FUNC): error("Nope")']
|
"# FIXME: qmake: ['TEMPLATE = lib', 'CONFIG += dll bsymbolic_functions', 'isEmpty(QMAKE_LFLAGS_BSYMBOLIC_FUNC): error("Nope")']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(NOT MSVC AND NOT APPLE)
|
||||||
|
qt_config_compile_test("separate_debug_info"
|
||||||
|
LABEL "separate debug information support"
|
||||||
|
PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/separate_debug_info"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
qt_config_compile_test("separate_debug_info"
|
|
||||||
LABEL "separate debug information support"
|
|
||||||
PROJECT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/separate_debug_info"
|
|
||||||
)
|
|
||||||
# signaling_nan
|
# signaling_nan
|
||||||
qt_config_compile_test(signaling_nan
|
qt_config_compile_test(signaling_nan
|
||||||
LABEL "Signaling NaN for doubles"
|
LABEL "Signaling NaN for doubles"
|
||||||
@ -535,7 +541,7 @@ qt_feature("developer-build" PRIVATE
|
|||||||
LABEL "Developer build"
|
LABEL "Developer build"
|
||||||
AUTODETECT OFF
|
AUTODETECT OFF
|
||||||
)
|
)
|
||||||
qt_feature("no-prefix" PRIVATE
|
qt_feature("no-prefix"
|
||||||
LABEL "No prefix build"
|
LABEL "No prefix build"
|
||||||
AUTODETECT NOT QT_WILL_INSTALL
|
AUTODETECT NOT QT_WILL_INSTALL
|
||||||
CONDITION NOT QT_WILL_INSTALL
|
CONDITION NOT QT_WILL_INSTALL
|
||||||
@ -567,7 +573,7 @@ qt_feature_config("force_debug_info" QMAKE_PRIVATE_CONFIG)
|
|||||||
qt_feature("separate_debug_info" PUBLIC
|
qt_feature("separate_debug_info" PUBLIC
|
||||||
LABEL "Split off debug information"
|
LABEL "Split off debug information"
|
||||||
AUTODETECT OFF
|
AUTODETECT OFF
|
||||||
CONDITION ( QT_FEATURE_shared ) AND ( QT_FEATURE_debug OR QT_FEATURE_debug_and_release OR QT_FEATURE_force_debug_info ) AND ( APPLE OR TEST_separate_debug_info )
|
CONDITION ( QT_FEATURE_shared ) AND ( QT_FEATURE_debug OR QT_FEATURE_debug_and_release OR QT_FEATURE_force_debug_info ) AND ( MSVC OR APPLE OR TEST_separate_debug_info )
|
||||||
)
|
)
|
||||||
qt_feature_config("separate_debug_info" QMAKE_PUBLIC_QT_CONFIG)
|
qt_feature_config("separate_debug_info" QMAKE_PUBLIC_QT_CONFIG)
|
||||||
qt_feature("appstore-compliant" PUBLIC
|
qt_feature("appstore-compliant" PUBLIC
|
||||||
@ -1157,6 +1163,18 @@ qt_configure_add_summary_entry(
|
|||||||
ARGS "ccache"
|
ARGS "ccache"
|
||||||
CONDITION UNIX
|
CONDITION UNIX
|
||||||
)
|
)
|
||||||
|
qt_configure_add_summary_entry(
|
||||||
|
TYPE "message" ARGS "Unity Build" MESSAGE "yes" CONDITION QT_UNITY_BUILD
|
||||||
|
)
|
||||||
|
qt_configure_add_summary_entry(
|
||||||
|
TYPE "message" ARGS "Unity Build" MESSAGE "no" CONDITION NOT QT_UNITY_BUILD
|
||||||
|
)
|
||||||
|
qt_configure_add_summary_entry(
|
||||||
|
TYPE "message"
|
||||||
|
ARGS "Unity Build Batch Size"
|
||||||
|
MESSAGE "${QT_UNITY_BUILD_BATCH_SIZE}"
|
||||||
|
CONDITION QT_UNITY_BUILD
|
||||||
|
)
|
||||||
qt_configure_add_summary_entry(
|
qt_configure_add_summary_entry(
|
||||||
TYPE "firstAvailableFeature"
|
TYPE "firstAvailableFeature"
|
||||||
ARGS "use_bfd_linker use_gold_linker use_lld_linker use_mold_linker"
|
ARGS "use_bfd_linker use_gold_linker use_lld_linker use_mold_linker"
|
||||||
@ -1326,3 +1344,11 @@ qt_extra_definition("QT_VERSION_PATCH" ${PROJECT_VERSION_PATCH} PUBLIC)
|
|||||||
|
|
||||||
qt_extra_definition("QT_COPYRIGHT" \"${QT_COPYRIGHT}\" PRIVATE)
|
qt_extra_definition("QT_COPYRIGHT" \"${QT_COPYRIGHT}\" PRIVATE)
|
||||||
qt_extra_definition("QT_COPYRIGHT_YEAR" \"${QT_COPYRIGHT_YEAR}\" PRIVATE)
|
qt_extra_definition("QT_COPYRIGHT_YEAR" \"${QT_COPYRIGHT_YEAR}\" PRIVATE)
|
||||||
|
|
||||||
|
qt_configure_add_report_entry(
|
||||||
|
TYPE WARNING
|
||||||
|
MESSAGE "QT_ALLOW_SYMLINK_IN_PATHS is enabled. This is not recommended, and it may lead to unexpected issues.
|
||||||
|
E.g., When building QtWebEngine, enabling this option may result in build issues in certain platforms.
|
||||||
|
See https://bugreports.qt.io/browse/QTBUG-59769."
|
||||||
|
CONDITION QT_ALLOW_SYMLINK_IN_PATHS
|
||||||
|
)
|
||||||
|
1
doc/config/exampleurl-qtpositioning.qdocconf
Normal file
@ -0,0 +1 @@
|
|||||||
|
url.examples = "https://code.qt.io/cgit/qt/qtpositioning.git/tree/examples/\1?h=$QT_VER"
|
@ -29,6 +29,5 @@ url = https://doc.qt.io/qt
|
|||||||
|
|
||||||
defines += qt6
|
defines += qt6
|
||||||
|
|
||||||
# Uncomment the following two lines to generate documentation marked as \internal
|
# Require Qt modules to define qhp.projects
|
||||||
# alias.internal = disable
|
qhp = true
|
||||||
# macro.internal.HTML = "<span style="color:red">[internal]</span>"
|
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
#specify the CSS file used by this template
|
#specify the CSS file used by this template
|
||||||
HTML.stylesheets = template/style/offline.css \
|
HTML.stylesheets = template/style/offline.css \
|
||||||
template/style/offline-dark.css
|
template/style/offline-dark.css \
|
||||||
|
template/style/tech_preview.svg
|
||||||
|
|
||||||
#for including files into the qch file
|
#for including files into the qch file
|
||||||
qhp.extraFiles += style/offline.css \
|
qhp.extraFiles += style/offline.css \
|
||||||
style/offline-dark.css
|
style/offline-dark.css \
|
||||||
|
style/tech_preview.svg
|
||||||
|
|
||||||
HTML.headerstyles = \
|
HTML.headerstyles = \
|
||||||
" <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n"
|
" <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n"
|
||||||
|
@ -11,8 +11,10 @@ HTML.stylesheets = template/style/online.css \
|
|||||||
template/style/icomoon.woff \
|
template/style/icomoon.woff \
|
||||||
template/style/cookiebar-x.png \
|
template/style/cookiebar-x.png \
|
||||||
template/style/doc_search.png \
|
template/style/doc_search.png \
|
||||||
|
template/style/tech_preview.svg \
|
||||||
template/style/theqtcompany.png
|
template/style/theqtcompany.png
|
||||||
|
|
||||||
|
|
||||||
#for including files into the qch file. Relative to the outputdir of a QDoc build.
|
#for including files into the qch file. Relative to the outputdir of a QDoc build.
|
||||||
qhp.extraFiles += style/online.css \
|
qhp.extraFiles += style/online.css \
|
||||||
style/cookie-confirm.css \
|
style/cookie-confirm.css \
|
||||||
@ -25,6 +27,7 @@ qhp.extraFiles += style/online.css \
|
|||||||
style/icomoon.woff \
|
style/icomoon.woff \
|
||||||
style/cookiebar-x.png \
|
style/cookiebar-x.png \
|
||||||
style/doc_search.png \
|
style/doc_search.png \
|
||||||
|
style/tech_preview.svg \
|
||||||
style/theqtcompany.png
|
style/theqtcompany.png
|
||||||
|
|
||||||
HTML.headerstyles = \
|
HTML.headerstyles = \
|
||||||
|
@ -56,6 +56,19 @@ macro.endqdoc.HTML = "*/"
|
|||||||
macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv"
|
macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv"
|
||||||
macro.examplecategory = "\\meta category {\1}\n\\ingroup category \1"
|
macro.examplecategory = "\\meta category {\1}\n\\ingroup category \1"
|
||||||
|
|
||||||
|
macro.QDS = "Qt Design Studio"
|
||||||
|
macro.QDV = "Qt Design Viewer"
|
||||||
|
macro.QB = "Qt Bridge"
|
||||||
|
macro.QBPS = "Qt Bridge for Adobe Photoshop"
|
||||||
|
macro.QBXD = "Qt Bridge for Adobe XD"
|
||||||
|
macro.QBSK = "Qt Bridge for Sketch"
|
||||||
|
macro.QBF = "Qt Bridge for Figma"
|
||||||
|
macro.QMCU = "Qt for MCUs"
|
||||||
|
macro.QUL = "Qt Quick Ultralite"
|
||||||
|
macro.QtAA = "Qt for Android Automotive"
|
||||||
|
macro.QOI = "Qt Online Installer"
|
||||||
|
macro.QMT = "Qt Maintenance Tool"
|
||||||
|
|
||||||
macro.beginfloatleft.HTML = "<div style=\"float: left; margin-right: 2em\">"
|
macro.beginfloatleft.HTML = "<div style=\"float: left; margin-right: 2em\">"
|
||||||
macro.beginfloatright.HTML = "<div style=\"float: right; margin-left: 2em\">"
|
macro.beginfloatright.HTML = "<div style=\"float: right; margin-left: 2em\">"
|
||||||
macro.endfloat.HTML = "</div>"
|
macro.endfloat.HTML = "</div>"
|
||||||
@ -111,3 +124,8 @@ macro.cmakepropertywebassemblyonly = "\\note This property is used only if targe
|
|||||||
|
|
||||||
macro.cmakepropertyiosonly = "\\note This property is used only if targeting iOS."
|
macro.cmakepropertyiosonly = "\\note This property is used only if targeting iOS."
|
||||||
macro.cmakevariableiosonly = "\\note This variable is used only if targeting iOS."
|
macro.cmakevariableiosonly = "\\note This variable is used only if targeting iOS."
|
||||||
|
|
||||||
|
#Appends the tech preview link to the brief sentence and adds to tech_preview
|
||||||
|
#group.
|
||||||
|
#Must be placed directly under a \brief command
|
||||||
|
macro.techpreview = "(Technical preview)\n\n\\meta status {Technical preview}\n\\ingroup tech_preview\n"
|
||||||
|
@ -94,7 +94,6 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
|
|||||||
"QtQuickControls/Qt Quick Controls - Flat Style" \
|
"QtQuickControls/Qt Quick Controls - Flat Style" \
|
||||||
"QtQuickControls/Qt Quick Controls - Gallery" \
|
"QtQuickControls/Qt Quick Controls - Gallery" \
|
||||||
"QtQuickControls/Qt Quick Controls - Imagine Style Example: Automotive" \
|
"QtQuickControls/Qt Quick Controls - Imagine Style Example: Automotive" \
|
||||||
"QtQuickControls/Qt Quick Controls - Imagine Style Example: Music Player" \
|
|
||||||
"QtQuickControls/Qt Quick Controls - Side Panel" \
|
"QtQuickControls/Qt Quick Controls - Side Panel" \
|
||||||
"QtQuickControls/Qt Quick Controls - Swipe to Remove" \
|
"QtQuickControls/Qt Quick Controls - Swipe to Remove" \
|
||||||
"QtQuickControls/Qt Quick Controls - Text Editor" \
|
"QtQuickControls/Qt Quick Controls - Text Editor" \
|
||||||
@ -166,7 +165,6 @@ manifestmeta.ios.names = "QtCore/Contiguous Cache Example" \
|
|||||||
"QtWidgets/Easing Curves Example" \
|
"QtWidgets/Easing Curves Example" \
|
||||||
"QtWidgets/Move Blocks Example" \
|
"QtWidgets/Move Blocks Example" \
|
||||||
"QtWidgets/States Example" \
|
"QtWidgets/States Example" \
|
||||||
"QtWidgets/Class Wizard Example" \
|
|
||||||
"QtWidgets/Find Files Example" \
|
"QtWidgets/Find Files Example" \
|
||||||
"QtWidgets/License Wizard Example" \
|
"QtWidgets/License Wizard Example" \
|
||||||
"QtWidgets/Standard Dialogs Example" \
|
"QtWidgets/Standard Dialogs Example" \
|
||||||
|
@ -574,6 +574,20 @@ ol.I > li {
|
|||||||
padding: 3px 15px 3px 0
|
padding: 3px 15px 3px 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.status.technical-preview {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
background: center/contain no-repeat url(tech_preview.svg);
|
||||||
|
width: 26px;
|
||||||
|
height: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.memItemRight span.status {
|
||||||
|
margin-top: -10px;
|
||||||
|
right: -10px;
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
.qml {
|
.qml {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
@ -505,6 +505,18 @@ h1,h2,h3,h4,h5,h6 {
|
|||||||
font-size:150%;
|
font-size:150%;
|
||||||
margin-bottom: 1em
|
margin-bottom: 1em
|
||||||
}
|
}
|
||||||
|
span.status.technical-preview {
|
||||||
|
display:inline-block;
|
||||||
|
position:relative;
|
||||||
|
background:center/contain no-repeat url(tech_preview.svg);
|
||||||
|
width:26px;
|
||||||
|
height:23px
|
||||||
|
}
|
||||||
|
td.memItemRight span.status {
|
||||||
|
margin-top:-10px;
|
||||||
|
right:-10px;
|
||||||
|
top:6px
|
||||||
|
}
|
||||||
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
|
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
|
||||||
display:block
|
display:block
|
||||||
}
|
}
|
||||||
|
1
doc/global/template/style/tech_preview.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="43" viewBox="0 0 13 11" stroke="#09102b"><path d="M12.82 11.125L.155 11.121 6.491.155z" opacity=".999" fill="#ffe353" stroke-linejoin="round" stroke-width=".31"/><path d="M4.914 7.071L3.521 8.302l1.287 1.084m1.144.027l1.394-1.231-1.287-1.084m-.283-.539l-.788 2.974" fill="none" stroke-linecap="round" stroke-width=".151"/><path d="M7.287 9.358l-.013.259 1.695.025-.021-.297-1.662.013zm.706.017L7.989 5.7l.367-.004.017 3.658m.33-3.512l-.238.008.004.255.238.033-.004-.297zm-.221.05l-3.199.008.004.238 3.165-.021.029-.226zm-2.965.255l.025.447.28-.15.23.163-.267.313m-.23-.322l-.242-.046-.084.163.288.226" fill="#41cd52" stroke-width=".151"/></svg>
|
After Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 222 KiB |
@ -5,7 +5,6 @@ qt_examples_build_begin(EXTERNAL_BUILD)
|
|||||||
|
|
||||||
add_subdirectory(corelib)
|
add_subdirectory(corelib)
|
||||||
add_subdirectory(embedded)
|
add_subdirectory(embedded)
|
||||||
add_subdirectory(qpa)
|
|
||||||
if(TARGET Qt6::DBus)
|
if(TARGET Qt6::DBus)
|
||||||
add_subdirectory(dbus)
|
add_subdirectory(dbus)
|
||||||
endif()
|
endif()
|
||||||
|
@ -6,9 +6,6 @@ add_subdirectory(mimetypes)
|
|||||||
add_subdirectory(serialization)
|
add_subdirectory(serialization)
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
add_subdirectory(platform)
|
add_subdirectory(platform)
|
||||||
if(QT_FEATURE_permissions)
|
|
||||||
add_subdirectory(permissions)
|
|
||||||
endif()
|
|
||||||
if(QT_FEATURE_thread)
|
if(QT_FEATURE_thread)
|
||||||
add_subdirectory(threads)
|
add_subdirectory(threads)
|
||||||
endif()
|
endif()
|
||||||
|
@ -38,8 +38,7 @@ double BindableSubscription::calculateDiscount() const
|
|||||||
case Yearly:
|
case Yearly:
|
||||||
return 0.6;
|
return 0.6;
|
||||||
}
|
}
|
||||||
Q_ASSERT(false);
|
Q_UNREACHABLE_RETURN(-1);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BindableSubscription::basePrice() const
|
int BindableSubscription::basePrice() const
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
#include <QProperty>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTimeEdit>
|
||||||
|
#include <QBindable>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -19,6 +23,8 @@ int main(int argc, char *argv[])
|
|||||||
BindableSubscription subscription(&user);
|
BindableSubscription subscription(&user);
|
||||||
|
|
||||||
SubscriptionWindow w;
|
SubscriptionWindow w;
|
||||||
|
// clazy:excludeall=lambda-in-connect
|
||||||
|
// when subscription is out of scope so is window
|
||||||
|
|
||||||
// Initialize subscription data
|
// Initialize subscription data
|
||||||
QRadioButton *monthly = w.findChild<QRadioButton *>("btnMonthly");
|
QRadioButton *monthly = w.findChild<QRadioButton *>("btnMonthly");
|
||||||
@ -49,9 +55,8 @@ int main(int argc, char *argv[])
|
|||||||
});
|
});
|
||||||
|
|
||||||
QSpinBox *ageSpinBox = w.findChild<QSpinBox *>("ageSpinBox");
|
QSpinBox *ageSpinBox = w.findChild<QSpinBox *>("ageSpinBox");
|
||||||
QObject::connect(ageSpinBox, &QSpinBox::valueChanged, [&](int value) {
|
QBindable<int> ageBindable(ageSpinBox, "value");
|
||||||
user.setAge(value);
|
user.bindableAge().setBinding([ageBindable](){ return ageBindable.value();});
|
||||||
});
|
|
||||||
|
|
||||||
QLabel *priceDisplay = w.findChild<QLabel *>("priceDisplay");
|
QLabel *priceDisplay = w.findChild<QLabel *>("priceDisplay");
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
/*!
|
/*!
|
||||||
\title Qt Android Notifier
|
\title Qt Android Notifier
|
||||||
\example platform/androidnotifier
|
\example platform/androidnotifier
|
||||||
|
\examplecategory {Mobile}
|
||||||
\brief Demonstrates calling Java code from Qt in an Android application.
|
\brief Demonstrates calling Java code from Qt in an Android application.
|
||||||
|
|
||||||
\image androidnotifier.png
|
\image androidnotifier.png
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
# Copyright (C) 2022 The Qt Company Ltd.
|
# Copyright (C) 2022 The Qt Company Ltd.
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
qt_internal_add_example(cbordump)
|
if(NOT ANDROID)
|
||||||
qt_internal_add_example(convert)
|
qt_internal_add_example(cbordump)
|
||||||
qt_internal_add_example(savegame)
|
qt_internal_add_example(convert)
|
||||||
if(TARGET Qt6::Network AND TARGET Qt6::Widgets)
|
qt_internal_add_example(savegame)
|
||||||
qt_internal_add_example(rsslisting)
|
|
||||||
endif()
|
endif()
|
||||||
if(TARGET Qt6::Widgets)
|
if(TARGET Qt6::Widgets)
|
||||||
qt_internal_add_example(streambookmarks)
|
qt_internal_add_example(streambookmarks)
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(cbordump LANGUAGES CXX)
|
project(cbordump LANGUAGES CXX)
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
message(FATAL_ERROR "This project cannot be built on Android.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||||
set(INSTALL_EXAMPLESDIR "examples")
|
set(INSTALL_EXAMPLESDIR "examples")
|
||||||
endif()
|
endif()
|
||||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 19 KiB |
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example serialization/cbordump
|
\example serialization/cbordump
|
||||||
\examplecategory {Input/Output}
|
\examplecategory {Data Processing & I/O}
|
||||||
|
\meta tag {network}
|
||||||
\title Parsing and displaying CBOR data
|
\title Parsing and displaying CBOR data
|
||||||
|
|
||||||
\brief A demonstration of how to parse files in CBOR format.
|
\brief A demonstration of how to parse files in CBOR format.
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To regenerate:
|
* To regenerate:
|
||||||
* curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
|
* curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
|
||||||
@ -33,7 +35,7 @@
|
|||||||
struct CborTagDescription
|
struct CborTagDescription
|
||||||
{
|
{
|
||||||
QCborTag tag;
|
QCborTag tag;
|
||||||
const char *description; // with space and parentheses
|
const char *description; // with space and parentheses
|
||||||
};
|
};
|
||||||
|
|
||||||
// CBOR Tags
|
// CBOR Tags
|
||||||
@ -216,22 +218,18 @@ static const CborTagDescription tagDescriptions[] = {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
// See RFC 7049 section 2.
|
// See RFC 7049 section 2.
|
||||||
SmallValueBitLength = 5,
|
SmallValueBitLength = 5,
|
||||||
SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
|
SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
|
||||||
Value8Bit = 24,
|
Value8Bit = 24,
|
||||||
Value16Bit = 25,
|
Value16Bit = 25,
|
||||||
Value32Bit = 26,
|
Value32Bit = 26,
|
||||||
Value64Bit = 27
|
Value64Bit = 27
|
||||||
};
|
};
|
||||||
|
|
||||||
//! [0]
|
//! [0]
|
||||||
struct CborDumper
|
struct CborDumper
|
||||||
{
|
{
|
||||||
enum DumpOption {
|
enum DumpOption { ShowCompact = 0x01, ShowWidthIndicators = 0x02, ShowAnnotated = 0x04 };
|
||||||
ShowCompact = 0x01,
|
|
||||||
ShowWidthIndicators = 0x02,
|
|
||||||
ShowAnnotated = 0x04
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(DumpOptions, DumpOption)
|
Q_DECLARE_FLAGS(DumpOptions, DumpOption)
|
||||||
|
|
||||||
CborDumper(QFile *f, DumpOptions opts_);
|
CborDumper(QFile *f, DumpOptions opts_);
|
||||||
@ -268,8 +266,7 @@ static int cborNumberSize(quint64 value)
|
|||||||
return normalSize;
|
return normalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
CborDumper::CborDumper(QFile *f, DumpOptions opts_)
|
CborDumper::CborDumper(QFile *f, DumpOptions opts_) : opts(opts_)
|
||||||
: opts(opts_)
|
|
||||||
{
|
{
|
||||||
// try to mmap the file, this is faster
|
// try to mmap the file, this is faster
|
||||||
char *ptr = reinterpret_cast<char *>(f->map(0, f->size(), QFile::MapPrivateOption));
|
char *ptr = reinterpret_cast<char *>(f->map(0, f->size(), QFile::MapPrivateOption));
|
||||||
@ -316,7 +313,8 @@ QCborError CborDumper::dump()
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> static inline bool canConvertTo(double v)
|
template<typename T>
|
||||||
|
static inline bool canConvertTo(double v)
|
||||||
{
|
{
|
||||||
using TypeInfo = std::numeric_limits<T>;
|
using TypeInfo = std::numeric_limits<T>;
|
||||||
// The [conv.fpint] (7.10 Floating-integral conversions) section of the
|
// The [conv.fpint] (7.10 Floating-integral conversions) section of the
|
||||||
@ -337,31 +335,32 @@ template <typename T> static inline bool canConvertTo(double v)
|
|||||||
return v == floor(v);
|
return v == floor(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString fpToString(double v, const char *suffix)
|
static QString fpToString(double v, QLatin1StringView suffix = ""_L1)
|
||||||
{
|
{
|
||||||
if (qIsInf(v))
|
if (qIsInf(v))
|
||||||
return v < 0 ? QStringLiteral("-inf") : QStringLiteral("inf");
|
return v < 0 ? "-inf"_L1 : "inf"_L1;
|
||||||
if (qIsNaN(v))
|
if (qIsNaN(v))
|
||||||
return QStringLiteral("nan");
|
return "nan"_L1;
|
||||||
if (canConvertTo<qint64>(v))
|
if (canConvertTo<qint64>(v))
|
||||||
return QString::number(qint64(v)) + ".0" + suffix;
|
return QString::number(qint64(v)) + ".0"_L1 + suffix;
|
||||||
if (canConvertTo<quint64>(v))
|
if (canConvertTo<quint64>(v))
|
||||||
return QString::number(quint64(v)) + ".0" + suffix;
|
return QString::number(quint64(v)) + ".0"_L1 + suffix;
|
||||||
|
|
||||||
QString s = QString::number(v, 'g', QLocale::FloatingPointShortest);
|
QString s = QString::number(v, 'g', QLocale::FloatingPointShortest);
|
||||||
if (!s.contains('.') && !s.contains('e'))
|
if (!s.contains(u'.') && !s.contains(u'e'))
|
||||||
s += '.';
|
s += u'.';
|
||||||
s += suffix;
|
if (suffix.size())
|
||||||
|
s += suffix;
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
void CborDumper::dumpOne(int nestingLevel)
|
void CborDumper::dumpOne(int nestingLevel)
|
||||||
{
|
{
|
||||||
QString indent(1, QLatin1Char(' '));
|
QString indent(1, u' ');
|
||||||
QString indented = indent;
|
QString indented = indent;
|
||||||
if (!opts.testFlag(ShowCompact)) {
|
if (!opts.testFlag(ShowCompact)) {
|
||||||
indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' '));
|
indent = u'\n' + QString(4 * nestingLevel, u' ');
|
||||||
indented = QLatin1Char('\n') + QString(4 + 4 * nestingLevel, QLatin1Char(' '));
|
indented = u'\n' + QString(4 + 4 * nestingLevel, u' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (reader.type()) {
|
switch (reader.type()) {
|
||||||
@ -401,7 +400,7 @@ void CborDumper::dumpOne(int nestingLevel)
|
|||||||
printStringWidthIndicator(r.data.size());
|
printStringWidthIndicator(r.data.size());
|
||||||
|
|
||||||
r = reader.readByteArray();
|
r = reader.readByteArray();
|
||||||
comma = QLatin1Char(',') + indented;
|
comma = u',' + indented;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto r = reader.readString();
|
auto r = reader.readString();
|
||||||
@ -410,7 +409,7 @@ void CborDumper::dumpOne(int nestingLevel)
|
|||||||
printStringWidthIndicator(r.data.toUtf8().size());
|
printStringWidthIndicator(r.data.toUtf8().size());
|
||||||
|
|
||||||
r = reader.readString();
|
r = reader.readString();
|
||||||
comma = QLatin1Char(',') + indented;
|
comma = u',' + indented;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +465,7 @@ void CborDumper::dumpOne(int nestingLevel)
|
|||||||
if (reader.next()) {
|
if (reader.next()) {
|
||||||
printWidthIndicator(quint64(tag));
|
printWidthIndicator(quint64(tag));
|
||||||
printf("(");
|
printf("(");
|
||||||
dumpOne(nestingLevel); // same level!
|
dumpOne(nestingLevel); // same level!
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,15 +497,15 @@ void CborDumper::dumpOne(int nestingLevel)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QCborStreamReader::Float16:
|
case QCborStreamReader::Float16:
|
||||||
printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16")));
|
printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16"_L1)));
|
||||||
reader.next();
|
reader.next();
|
||||||
break;
|
break;
|
||||||
case QCborStreamReader::Float:
|
case QCborStreamReader::Float:
|
||||||
printf("%s", qPrintable(fpToString(reader.toFloat(), "f")));
|
printf("%s", qPrintable(fpToString(reader.toFloat(), "f"_L1)));
|
||||||
reader.next();
|
reader.next();
|
||||||
break;
|
break;
|
||||||
case QCborStreamReader::Double:
|
case QCborStreamReader::Double:
|
||||||
printf("%s", qPrintable(fpToString(reader.toDouble(), "")));
|
printf("%s", qPrintable(fpToString(reader.toDouble())));
|
||||||
reader.next();
|
reader.next();
|
||||||
break;
|
break;
|
||||||
case QCborStreamReader::Invalid:
|
case QCborStreamReader::Invalid:
|
||||||
@ -559,7 +558,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto printFp = [=](const char *descr, double d) {
|
auto printFp = [=](const char *descr, double d) {
|
||||||
QString s = fpToString(d, "");
|
QString s = fpToString(d);
|
||||||
if (s.size() <= 6)
|
if (s.size() <= 6)
|
||||||
return print(descr, "%s", qPrintable(s));
|
return print(descr, "%s", qPrintable(s));
|
||||||
return print(descr, "%a", d);
|
return print(descr, "%a", d);
|
||||||
@ -574,7 +573,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
|
|||||||
|
|
||||||
qsizetype size = reader.currentStringChunkSize();
|
qsizetype size = reader.currentStringChunkSize();
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
return; // error
|
return; // error
|
||||||
if (size >= ChunkSizeLimit) {
|
if (size >= ChunkSizeLimit) {
|
||||||
fprintf(stderr, "String length too big, %lli\n", qint64(size));
|
fprintf(stderr, "String length too big, %lli\n", qint64(size));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -619,7 +618,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
|
|||||||
printf(" %s%s", indent.constData(), section.toHex(' ').constData());
|
printf(" %s%s", indent.constData(), section.toHex(' ').constData());
|
||||||
|
|
||||||
// print the decode
|
// print the decode
|
||||||
QByteArray spaces(width > 0 ? width - section.size() * 3 + 1: 0, ' ');
|
QByteArray spaces(width > 0 ? width - section.size() * 3 + 1 : 0, ' ');
|
||||||
printf("%s # \"", spaces.constData());
|
printf("%s # \"", spaces.constData());
|
||||||
auto ptr = reinterpret_cast<const uchar *>(section.constData());
|
auto ptr = reinterpret_cast<const uchar *>(section.constData());
|
||||||
for (int j = 0; j < section.size(); ++j)
|
for (int j = 0; j < section.size(); ++j)
|
||||||
@ -631,7 +630,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
|
|||||||
// get the next chunk
|
// get the next chunk
|
||||||
size = reader.currentStringChunkSize();
|
size = reader.currentStringChunkSize();
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
return; // error
|
return; // error
|
||||||
if (size >= ChunkSizeLimit) {
|
if (size >= ChunkSizeLimit) {
|
||||||
fprintf(stderr, "String length too big, %lli\n", qint64(size));
|
fprintf(stderr, "String length too big, %lli\n", qint64(size));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -770,7 +769,9 @@ void CborDumper::printByteArray(const QByteArray &ba)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case quint8(QCborKnownTags::ExpectedBase64url):
|
case quint8(QCborKnownTags::ExpectedBase64url):
|
||||||
printf("b64'%s'", ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals).constData());
|
printf("b64'%s'",
|
||||||
|
ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)
|
||||||
|
.constData());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -811,23 +812,20 @@ int main(int argc, char *argv[])
|
|||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription(QStringLiteral("CBOR Dumper tool"));
|
parser.setApplicationDescription("CBOR Dumper tool"_L1);
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
||||||
QCommandLineOption compact({QStringLiteral("c"), QStringLiteral("compact")},
|
QCommandLineOption compact({"c"_L1, "compact"_L1}, "Use compact form (no line breaks)"_L1);
|
||||||
QStringLiteral("Use compact form (no line breaks)"));
|
|
||||||
parser.addOption(compact);
|
parser.addOption(compact);
|
||||||
|
|
||||||
QCommandLineOption showIndicators({QStringLiteral("i"), QStringLiteral("indicators")},
|
QCommandLineOption showIndicators({ "i"_L1, "indicators"_L1 },
|
||||||
QStringLiteral("Show indicators for width of lengths and integrals"));
|
"Show indicators for width of lengths and integrals"_L1);
|
||||||
parser.addOption(showIndicators);
|
parser.addOption(showIndicators);
|
||||||
|
|
||||||
QCommandLineOption verbose({QStringLiteral("a"), QStringLiteral("annotated")},
|
QCommandLineOption verbose({"a"_L1, "annotated"_L1}, "Show bytes and annotated decoding"_L1);
|
||||||
QStringLiteral("Show bytes and annotated decoding"));
|
|
||||||
parser.addOption(verbose);
|
parser.addOption(verbose);
|
||||||
|
|
||||||
parser.addPositionalArgument(QStringLiteral("[source]"),
|
parser.addPositionalArgument("[source]"_L1, "CBOR file to read from"_L1);
|
||||||
QStringLiteral("CBOR file to read from"));
|
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(convert LANGUAGES CXX)
|
project(convert LANGUAGES CXX)
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
message(FATAL_ERROR "This project cannot be built on Android.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||||
set(INSTALL_EXAMPLESDIR "examples")
|
set(INSTALL_EXAMPLESDIR "examples")
|
||||||
endif()
|
endif()
|
||||||
@ -18,6 +22,7 @@ qt_add_executable(convert
|
|||||||
cborconverter.cpp cborconverter.h
|
cborconverter.cpp cborconverter.h
|
||||||
converter.h
|
converter.h
|
||||||
datastreamconverter.cpp datastreamconverter.h
|
datastreamconverter.cpp datastreamconverter.h
|
||||||
|
debugtextdumper.cpp debugtextdumper.h
|
||||||
jsonconverter.cpp jsonconverter.h
|
jsonconverter.cpp jsonconverter.h
|
||||||
main.cpp
|
main.cpp
|
||||||
nullconverter.cpp nullconverter.h
|
nullconverter.cpp nullconverter.h
|
||||||
|
@ -3,19 +3,21 @@
|
|||||||
|
|
||||||
#include "cborconverter.h"
|
#include "cborconverter.h"
|
||||||
|
|
||||||
|
#include <QCborArray>
|
||||||
|
#include <QCborMap>
|
||||||
#include <QCborStreamReader>
|
#include <QCborStreamReader>
|
||||||
#include <QCborStreamWriter>
|
#include <QCborStreamWriter>
|
||||||
#include <QCborMap>
|
|
||||||
#include <QCborArray>
|
|
||||||
#include <QCborValue>
|
#include <QCborValue>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QFloat16>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFloat16>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
static CborConverter cborConverter;
|
static CborConverter cborConverter;
|
||||||
static CborDiagnosticDumper cborDiagnosticDumper;
|
static CborDiagnosticDumper cborDiagnosticDumper;
|
||||||
|
|
||||||
@ -118,33 +120,33 @@ static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrim
|
|||||||
}
|
}
|
||||||
//! [1]
|
//! [1]
|
||||||
|
|
||||||
QString CborDiagnosticDumper::name()
|
QString CborDiagnosticDumper::name() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("cbor-dump");
|
return "cbor-dump"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction CborDiagnosticDumper::directions()
|
Converter::Directions CborDiagnosticDumper::directions() const
|
||||||
{
|
{
|
||||||
return Out;
|
return Direction::Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options CborDiagnosticDumper::outputOptions()
|
Converter::Options CborDiagnosticDumper::outputOptions() const
|
||||||
{
|
{
|
||||||
return SupportsArbitraryMapKeys;
|
return SupportsArbitraryMapKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CborDiagnosticDumper::optionsHelp()
|
const char *CborDiagnosticDumper::optionsHelp() const
|
||||||
{
|
{
|
||||||
return diagnosticHelp;
|
return diagnosticHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CborDiagnosticDumper::probeFile(QIODevice *f)
|
bool CborDiagnosticDumper::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(f);
|
Q_UNUSED(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant CborDiagnosticDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
Q_UNUSED(f);
|
Q_UNUSED(f);
|
||||||
@ -152,7 +154,8 @@ QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverte
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
QCborValue::DiagnosticNotationOptions opts = QCborValue::LineWrapped;
|
QCborValue::DiagnosticNotationOptions opts = QCborValue::LineWrapped;
|
||||||
for (const QString &s : options) {
|
for (const QString &s : options) {
|
||||||
@ -181,8 +184,7 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
QTextStream out(f);
|
QTextStream out(f);
|
||||||
out << convertFromVariant(contents, Double).toDiagnosticNotation(opts)
|
out << convertFromVariant(contents, Double).toDiagnosticNotation(opts) << Qt::endl;
|
||||||
<< Qt::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CborConverter::CborConverter()
|
CborConverter::CborConverter()
|
||||||
@ -190,37 +192,37 @@ CborConverter::CborConverter()
|
|||||||
qRegisterMetaType<QCborTag>();
|
qRegisterMetaType<QCborTag>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CborConverter::name()
|
QString CborConverter::name() const
|
||||||
{
|
{
|
||||||
return "cbor";
|
return "cbor";
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction CborConverter::directions()
|
Converter::Directions CborConverter::directions() const
|
||||||
{
|
{
|
||||||
return InOut;
|
return Direction::InOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options CborConverter::outputOptions()
|
Converter::Options CborConverter::outputOptions() const
|
||||||
{
|
{
|
||||||
return SupportsArbitraryMapKeys;
|
return SupportsArbitraryMapKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CborConverter::optionsHelp()
|
const char *CborConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return cborOptionHelp;
|
return cborOptionHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CborConverter::probeFile(QIODevice *f)
|
bool CborConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||||
if (file->fileName().endsWith(QLatin1String(".cbor")))
|
if (file->fileName().endsWith(".cbor"_L1))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return f->isReadable() && f->peek(3) == QByteArray("\xd9\xd9\xf7", 3);
|
return f->isReadable() && f->peek(3) == QByteArray("\xd9\xd9\xf7", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! [2]
|
//! [2]
|
||||||
QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant CborConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
const char *ptr = nullptr;
|
const char *ptr = nullptr;
|
||||||
if (auto file = qobject_cast<QFile *>(f))
|
if (auto file = qobject_cast<QFile *>(f))
|
||||||
@ -256,7 +258,7 @@ QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
|||||||
}
|
}
|
||||||
//! [2]
|
//! [2]
|
||||||
//! [3]
|
//! [3]
|
||||||
void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) const
|
||||||
{
|
{
|
||||||
//! [3]
|
//! [3]
|
||||||
bool useSignature = true;
|
bool useSignature = true;
|
||||||
@ -318,8 +320,9 @@ void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStri
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
//! [4]
|
//! [4]
|
||||||
QCborValue v = convertFromVariant(contents,
|
QCborValue v =
|
||||||
useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double);
|
convertFromVariant(contents,
|
||||||
|
useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double);
|
||||||
QCborStreamWriter writer(f);
|
QCborStreamWriter writer(f);
|
||||||
if (useSignature)
|
if (useSignature)
|
||||||
writer.append(QCborKnownTags::Signature);
|
writer.append(QCborKnownTags::Signature);
|
||||||
|
@ -10,13 +10,14 @@ class CborDiagnosticDumper : public Converter
|
|||||||
{
|
{
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CborConverter : public Converter
|
class CborConverter : public Converter
|
||||||
@ -26,13 +27,14 @@ public:
|
|||||||
|
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CBORCONVERTER_H
|
#endif // CBORCONVERTER_H
|
||||||
|
@ -12,17 +12,19 @@ INSTALLS += target
|
|||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
cborconverter.cpp \
|
cborconverter.cpp \
|
||||||
jsonconverter.cpp \
|
|
||||||
datastreamconverter.cpp \
|
datastreamconverter.cpp \
|
||||||
|
debugtextdumper.cpp \
|
||||||
|
jsonconverter.cpp \
|
||||||
|
nullconverter.cpp \
|
||||||
textconverter.cpp \
|
textconverter.cpp \
|
||||||
xmlconverter.cpp \
|
xmlconverter.cpp
|
||||||
nullconverter.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
converter.h \
|
converter.h \
|
||||||
cborconverter.h \
|
cborconverter.h \
|
||||||
jsonconverter.h \
|
|
||||||
datastreamconverter.h \
|
datastreamconverter.h \
|
||||||
|
debugtextdumper.h \
|
||||||
|
jsonconverter.h \
|
||||||
|
nullconverter.h \
|
||||||
textconverter.h \
|
textconverter.h \
|
||||||
xmlconverter.h \
|
xmlconverter.h
|
||||||
nullconverter.h
|
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#define CONVERTER_H
|
#define CONVERTER_H
|
||||||
|
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
|
#include <QList>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
class VariantOrderedMap : public QList<QPair<QVariant, QVariant>>
|
class VariantOrderedMap : public QList<QPair<QVariant, QVariant>>
|
||||||
{
|
{
|
||||||
@ -32,26 +32,25 @@ protected:
|
|||||||
public:
|
public:
|
||||||
static Converter *null;
|
static Converter *null;
|
||||||
|
|
||||||
enum Direction {
|
enum class Direction { In = 1, Out = 2, InOut = In | Out };
|
||||||
In = 1, Out = 2, InOut = 3
|
Q_DECLARE_FLAGS(Directions, Direction)
|
||||||
};
|
|
||||||
|
|
||||||
enum Option {
|
enum Option { SupportsArbitraryMapKeys = 0x01 };
|
||||||
SupportsArbitraryMapKeys = 0x01
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
Q_DECLARE_FLAGS(Options, Option)
|
||||||
|
|
||||||
virtual ~Converter() = 0;
|
virtual ~Converter() = 0;
|
||||||
|
|
||||||
virtual QString name() = 0;
|
virtual QString name() const = 0;
|
||||||
virtual Direction directions() = 0;
|
virtual Directions directions() const = 0;
|
||||||
virtual Options outputOptions() = 0;
|
virtual Options outputOptions() const = 0;
|
||||||
virtual const char *optionsHelp() = 0;
|
virtual const char *optionsHelp() const = 0;
|
||||||
virtual bool probeFile(QIODevice *f) = 0;
|
virtual bool probeFile(QIODevice *f) const = 0;
|
||||||
virtual QVariant loadFile(QIODevice *f, Converter *&outputConverter) = 0;
|
virtual QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const = 0;
|
||||||
virtual void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) = 0;
|
virtual void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Directions)
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options)
|
||||||
|
|
||||||
#endif // CONVERTER_H
|
#endif // CONVERTER_H
|
||||||
|
@ -2,20 +2,21 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
#include "datastreamconverter.h"
|
#include "datastreamconverter.h"
|
||||||
|
#include "debugtextdumper.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
|
||||||
#include <QTextStream>
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
static const char dataStreamOptionHelp[] =
|
static const char dataStreamOptionHelp[] =
|
||||||
"byteorder=host|big|little Byte order to use.\n"
|
"byteorder=host|big|little Byte order to use.\n"
|
||||||
"version=<n> QDataStream version (default: Qt 5.0).\n"
|
"version=<n> QDataStream version (default: Qt 6.0).\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char signature[] = "qds";
|
static const char signature[] = "qds";
|
||||||
|
|
||||||
static DataStreamDumper dataStreamDumper;
|
static DataStreamConverter dataStreamConverter;
|
||||||
static DataStreamConverter DataStreamConverter;
|
static DebugTextDumper debugTextDumper;
|
||||||
|
|
||||||
QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map)
|
QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map)
|
||||||
{
|
{
|
||||||
@ -42,123 +43,43 @@ QDataStream &operator>>(QDataStream &ds, VariantOrderedMap &map)
|
|||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static QString dumpVariant(const QVariant &v, const QString &indent = QLatin1String("\n"))
|
|
||||||
{
|
|
||||||
QString result;
|
|
||||||
QString indented = indent + QLatin1String(" ");
|
|
||||||
|
|
||||||
int type = v.userType();
|
|
||||||
if (type == qMetaTypeId<VariantOrderedMap>() || type == QMetaType::QVariantMap) {
|
|
||||||
const auto map = (type == QMetaType::QVariantMap) ?
|
|
||||||
VariantOrderedMap(v.toMap()) : qvariant_cast<VariantOrderedMap>(v);
|
|
||||||
|
|
||||||
result = QLatin1String("Map {");
|
|
||||||
for (const auto &pair : map) {
|
|
||||||
result += indented + dumpVariant(pair.first, indented);
|
|
||||||
result.chop(1); // remove comma
|
|
||||||
result += QLatin1String(" => ") + dumpVariant(pair.second, indented);
|
|
||||||
|
|
||||||
}
|
|
||||||
result.chop(1); // remove comma
|
|
||||||
result += indent + QLatin1String("},");
|
|
||||||
} else if (type == QMetaType::QVariantList) {
|
|
||||||
const QVariantList list = v.toList();
|
|
||||||
|
|
||||||
result = QLatin1String("List [");
|
|
||||||
for (const auto &item : list)
|
|
||||||
result += indented + dumpVariant(item, indented);
|
|
||||||
result.chop(1); // remove comma
|
|
||||||
result += indent + QLatin1String("],");
|
|
||||||
} else {
|
|
||||||
QDebug debug(&result);
|
|
||||||
debug.nospace() << v << ',';
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DataStreamDumper::name()
|
|
||||||
{
|
|
||||||
return QStringLiteral("datastream-dump");
|
|
||||||
}
|
|
||||||
|
|
||||||
Converter::Direction DataStreamDumper::directions()
|
|
||||||
{
|
|
||||||
return Out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Converter::Options DataStreamDumper::outputOptions()
|
|
||||||
{
|
|
||||||
return SupportsArbitraryMapKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *DataStreamDumper::optionsHelp()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataStreamDumper::probeFile(QIODevice *f)
|
|
||||||
{
|
|
||||||
Q_UNUSED(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant DataStreamDumper::loadFile(QIODevice *f, Converter *&outputConverter)
|
|
||||||
{
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
Q_UNUSED(f);
|
|
||||||
Q_UNUSED(outputConverter);
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataStreamDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
|
||||||
{
|
|
||||||
Q_UNUSED(options);
|
|
||||||
QString s = dumpVariant(contents);
|
|
||||||
s[s.size() - 1] = QLatin1Char('\n'); // replace the comma with newline
|
|
||||||
|
|
||||||
QTextStream out(f);
|
|
||||||
out << s;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataStreamConverter::DataStreamConverter()
|
DataStreamConverter::DataStreamConverter()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<VariantOrderedMap>();
|
qRegisterMetaType<VariantOrderedMap>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DataStreamConverter::name()
|
QString DataStreamConverter::name() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("datastream");
|
return "datastream"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction DataStreamConverter::directions()
|
Converter::Directions DataStreamConverter::directions() const
|
||||||
{
|
{
|
||||||
return InOut;
|
return Direction::InOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options DataStreamConverter::outputOptions()
|
Converter::Options DataStreamConverter::outputOptions() const
|
||||||
{
|
{
|
||||||
return SupportsArbitraryMapKeys;
|
return SupportsArbitraryMapKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *DataStreamConverter::optionsHelp()
|
const char *DataStreamConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return dataStreamOptionHelp;
|
return dataStreamOptionHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataStreamConverter::probeFile(QIODevice *f)
|
bool DataStreamConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
return f->isReadable() && f->peek(sizeof(signature) - 1) == signature;
|
return f->isReadable() && f->peek(sizeof(signature) - 1) == signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant DataStreamConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
if (!outputConverter)
|
if (!outputConverter)
|
||||||
outputConverter = &dataStreamDumper;
|
outputConverter = &debugTextDumper;
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
if (f->read(sizeof(signature) -1) != signature ||
|
if (f->read(sizeof(signature) - 1) != signature || !f->getChar(&c) || (c != 'l' && c != 'B')) {
|
||||||
!f->getChar(&c) || (c != 'l' && c != 'B')) {
|
|
||||||
fprintf(stderr, "Could not load QDataStream file: invalid signature.\n");
|
fprintf(stderr, "Could not load QDataStream file: invalid signature.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -175,9 +96,10 @@ QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
QDataStream::Version version = QDataStream::Qt_5_0;
|
QDataStream::Version version = QDataStream::Qt_6_0;
|
||||||
auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
|
auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
|
||||||
for (const QString &option : options) {
|
for (const QString &option : options) {
|
||||||
const QStringList pair = option.split('=');
|
const QStringList pair = option.split('=');
|
||||||
@ -213,7 +135,7 @@ void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char c = order == QDataStream::LittleEndian ? 'l' : 'B';
|
char c = order == QDataStream::LittleEndian ? 'l' : 'B';
|
||||||
f->write(signature);
|
f->write(signature);
|
||||||
f->write(&c, 1);
|
f->write(&c, 1);
|
||||||
|
|
||||||
|
@ -6,19 +6,6 @@
|
|||||||
|
|
||||||
#include "converter.h"
|
#include "converter.h"
|
||||||
|
|
||||||
class DataStreamDumper : public Converter
|
|
||||||
{
|
|
||||||
// Converter interface
|
|
||||||
public:
|
|
||||||
QString name() override;
|
|
||||||
Direction directions() override;
|
|
||||||
Options outputOptions() override;
|
|
||||||
const char *optionsHelp() override;
|
|
||||||
bool probeFile(QIODevice *f) override;
|
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataStreamConverter : public Converter
|
class DataStreamConverter : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -26,13 +13,14 @@ public:
|
|||||||
|
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DATASTREAMCONVERTER_H
|
#endif // DATASTREAMCONVERTER_H
|
||||||
|
89
examples/corelib/serialization/convert/debugtextdumper.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (C) 2018 Intel Corporation.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
|
#include "debugtextdumper.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
// Static instance is declared in datastreamconverter.cpp, since it uses it.
|
||||||
|
|
||||||
|
static QString dumpVariant(const QVariant &v, const QString &indent = "\n"_L1)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QString indented = indent + " "_L1;
|
||||||
|
|
||||||
|
int type = v.userType();
|
||||||
|
if (type == qMetaTypeId<VariantOrderedMap>() || type == QMetaType::QVariantMap) {
|
||||||
|
const auto map = (type == QMetaType::QVariantMap) ? VariantOrderedMap(v.toMap())
|
||||||
|
: qvariant_cast<VariantOrderedMap>(v);
|
||||||
|
|
||||||
|
result = "Map {"_L1;
|
||||||
|
for (const auto &pair : map) {
|
||||||
|
result += indented + dumpVariant(pair.first, indented);
|
||||||
|
result.chop(1); // remove comma
|
||||||
|
result += " => "_L1 + dumpVariant(pair.second, indented);
|
||||||
|
}
|
||||||
|
result.chop(1); // remove comma
|
||||||
|
result += indent + "},"_L1;
|
||||||
|
} else if (type == QMetaType::QVariantList) {
|
||||||
|
const QVariantList list = v.toList();
|
||||||
|
|
||||||
|
result = "List ["_L1;
|
||||||
|
for (const auto &item : list)
|
||||||
|
result += indented + dumpVariant(item, indented);
|
||||||
|
result.chop(1); // remove comma
|
||||||
|
result += indent + "],"_L1;
|
||||||
|
} else {
|
||||||
|
QDebug debug(&result);
|
||||||
|
debug.nospace() << v << ',';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DebugTextDumper::name() const
|
||||||
|
{
|
||||||
|
return "debugtext-dump"_L1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Converter::Directions DebugTextDumper::directions() const
|
||||||
|
{
|
||||||
|
return Direction::Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Converter::Options DebugTextDumper::outputOptions() const
|
||||||
|
{
|
||||||
|
return SupportsArbitraryMapKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *DebugTextDumper::optionsHelp() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugTextDumper::probeFile(QIODevice *f) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant DebugTextDumper::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
|
{
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
Q_UNUSED(f);
|
||||||
|
Q_UNUSED(outputConverter);
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugTextDumper::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(options);
|
||||||
|
QString s = dumpVariant(contents);
|
||||||
|
s[s.size() - 1] = u'\n'; // replace the comma with newline
|
||||||
|
|
||||||
|
QTextStream out(f);
|
||||||
|
out << s;
|
||||||
|
}
|
23
examples/corelib/serialization/convert/debugtextdumper.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (C) 2018 Intel Corporation.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
|
#ifndef DEBUGTEXTDUMPER_H
|
||||||
|
#define DEBUGTEXTDUMPER_H
|
||||||
|
|
||||||
|
#include "converter.h"
|
||||||
|
|
||||||
|
class DebugTextDumper : public Converter
|
||||||
|
{
|
||||||
|
// Converter interface
|
||||||
|
public:
|
||||||
|
QString name() const override;
|
||||||
|
Directions directions() const override;
|
||||||
|
Options outputOptions() const override;
|
||||||
|
const char *optionsHelp() const override;
|
||||||
|
bool probeFile(QIODevice *f) const override;
|
||||||
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEBUGTEXTDUMPER_H
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example serialization/convert
|
\example serialization/convert
|
||||||
\examplecategory {Input/Output}
|
\examplecategory {Data Processing & I/O}
|
||||||
|
\meta tag {network}
|
||||||
\title Convert Example
|
\title Convert Example
|
||||||
|
|
||||||
\brief The Convert example demonstrates how to convert between different
|
\brief The Convert example demonstrates how to convert between different
|
||||||
@ -59,7 +60,7 @@
|
|||||||
\section1 The DataStreamConverter Class
|
\section1 The DataStreamConverter Class
|
||||||
|
|
||||||
The DataStreamConverter class is used to serialize to and from the
|
The DataStreamConverter class is used to serialize to and from the
|
||||||
QDataStream format. There is also the DataStreamDumper class for outputting
|
QDataStream format. There is also the DebugTextDumper class for outputting
|
||||||
the data lossless in a non-standardized human readable format.
|
the data lossless in a non-standardized human readable format.
|
||||||
|
|
||||||
\section1 The JsonConverter Class
|
\section1 The JsonConverter Class
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
static JsonConverter jsonConverter;
|
static JsonConverter jsonConverter;
|
||||||
|
|
||||||
static const char jsonOptionHelp[] =
|
static const char jsonOptionHelp[] = "compact=no|yes Use compact JSON form.\n";
|
||||||
"compact=no|yes Use compact JSON form.\n";
|
|
||||||
|
|
||||||
static QJsonDocument convertFromVariant(const QVariant &v)
|
static QJsonDocument convertFromVariant(const QVariant &v)
|
||||||
{
|
{
|
||||||
@ -24,34 +25,30 @@ static QJsonDocument convertFromVariant(const QVariant &v)
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonConverter::JsonConverter()
|
QString JsonConverter::name() const
|
||||||
{
|
{
|
||||||
|
return "json"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString JsonConverter::name()
|
Converter::Directions JsonConverter::directions() const
|
||||||
{
|
{
|
||||||
return "json";
|
return Direction::InOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction JsonConverter::directions()
|
Converter::Options JsonConverter::outputOptions() const
|
||||||
{
|
|
||||||
return InOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
Converter::Options JsonConverter::outputOptions()
|
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *JsonConverter::optionsHelp()
|
const char *JsonConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return jsonOptionHelp;
|
return jsonOptionHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonConverter::probeFile(QIODevice *f)
|
bool JsonConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||||
if (file->fileName().endsWith(QLatin1String(".json")))
|
if (file->fileName().endsWith(".json"_L1))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +59,7 @@ bool JsonConverter::probeFile(QIODevice *f)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant JsonConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
if (!outputConverter)
|
if (!outputConverter)
|
||||||
outputConverter = this;
|
outputConverter = this;
|
||||||
@ -87,13 +84,14 @@ QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
|||||||
return doc.toVariant();
|
return doc.toVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void JsonConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
QJsonDocument::JsonFormat format = QJsonDocument::Indented;
|
QJsonDocument::JsonFormat format = QJsonDocument::Indented;
|
||||||
for (const QString &s : options) {
|
for (const QString &s : options) {
|
||||||
if (s == QLatin1String("compact=no")) {
|
if (s == "compact=no"_L1) {
|
||||||
format = QJsonDocument::Indented;
|
format = QJsonDocument::Indented;
|
||||||
} else if (s == QLatin1String("compact=yes")) {
|
} else if (s == "compact=yes"_L1) {
|
||||||
format = QJsonDocument::Compact;
|
format = QJsonDocument::Compact;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown option '%s' to JSON output. Valid options are:\n%s",
|
fprintf(stderr, "Unknown option '%s' to JSON output. Valid options are:\n%s",
|
||||||
|
@ -8,18 +8,16 @@
|
|||||||
|
|
||||||
class JsonConverter : public Converter
|
class JsonConverter : public Converter
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
JsonConverter();
|
|
||||||
|
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // JSONCONVERTER_H
|
#endif // JSONCONVERTER_H
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static QList<Converter *> *availableConverters;
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
static QList<const Converter *> *availableConverters;
|
||||||
|
|
||||||
Converter::Converter()
|
Converter::Converter()
|
||||||
{
|
{
|
||||||
if (!availableConverters)
|
if (!availableConverters)
|
||||||
availableConverters = new QList<Converter *>;
|
availableConverters = new QList<const Converter *>;
|
||||||
availableConverters->append(this);
|
availableConverters->append(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,64 +33,68 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
QStringList inputFormats;
|
QStringList inputFormats;
|
||||||
QStringList outputFormats;
|
QStringList outputFormats;
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
auto direction = conv->directions();
|
auto direction = conv->directions();
|
||||||
QString name = conv->name();
|
QString name = conv->name();
|
||||||
if (direction & Converter::In)
|
if (direction.testFlag(Converter::Direction::In))
|
||||||
inputFormats << name;
|
inputFormats << name;
|
||||||
if (direction & Converter::Out)
|
if (direction.testFlag(Converter::Direction::Out))
|
||||||
outputFormats << name;
|
outputFormats << name;
|
||||||
}
|
}
|
||||||
inputFormats.sort();
|
inputFormats.sort();
|
||||||
outputFormats.sort();
|
outputFormats.sort();
|
||||||
inputFormats.prepend("auto");
|
inputFormats.prepend("auto"_L1);
|
||||||
outputFormats.prepend("auto");
|
outputFormats.prepend("auto"_L1);
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription(QStringLiteral("Qt file format conversion tool"));
|
parser.setApplicationDescription("Qt file format conversion tool"_L1);
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
||||||
QCommandLineOption inputFormatOption(QStringList{"I", "input-format"});
|
QCommandLineOption inputFormatOption(QStringList{ "I"_L1, "input-format"_L1 });
|
||||||
inputFormatOption.setDescription(QLatin1String("Select the input format for the input file. Available formats: ") +
|
inputFormatOption.setDescription(
|
||||||
inputFormats.join(", "));
|
"Select the input format for the input file. Available formats: "_L1
|
||||||
inputFormatOption.setValueName("format");
|
+ inputFormats.join(", "_L1));
|
||||||
|
inputFormatOption.setValueName("format"_L1);
|
||||||
inputFormatOption.setDefaultValue(inputFormats.constFirst());
|
inputFormatOption.setDefaultValue(inputFormats.constFirst());
|
||||||
parser.addOption(inputFormatOption);
|
parser.addOption(inputFormatOption);
|
||||||
|
|
||||||
QCommandLineOption outputFormatOption(QStringList{"O", "output-format"});
|
QCommandLineOption outputFormatOption(QStringList{ "O"_L1, "output-format"_L1 });
|
||||||
outputFormatOption.setDescription(QLatin1String("Select the output format for the output file. Available formats: ") +
|
outputFormatOption.setDescription(
|
||||||
outputFormats.join(", "));
|
"Select the output format for the output file. Available formats: "_L1
|
||||||
outputFormatOption.setValueName("format");
|
+ outputFormats.join(", "_L1));
|
||||||
|
outputFormatOption.setValueName("format"_L1);
|
||||||
outputFormatOption.setDefaultValue(outputFormats.constFirst());
|
outputFormatOption.setDefaultValue(outputFormats.constFirst());
|
||||||
parser.addOption(outputFormatOption);
|
parser.addOption(outputFormatOption);
|
||||||
|
|
||||||
QCommandLineOption optionOption(QStringList{"o", "option"});
|
QCommandLineOption optionOption(QStringList{ "o"_L1, "option"_L1 });
|
||||||
optionOption.setDescription(QStringLiteral("Format-specific options. Use --format-options to find out what options are available."));
|
optionOption.setDescription(
|
||||||
optionOption.setValueName("options...");
|
"Format-specific options. Use --format-options to find out what options are available."_L1);
|
||||||
|
optionOption.setValueName("options..."_L1);
|
||||||
optionOption.setDefaultValues({});
|
optionOption.setDefaultValues({});
|
||||||
parser.addOption(optionOption);
|
parser.addOption(optionOption);
|
||||||
|
|
||||||
QCommandLineOption formatOptionsOption("format-options");
|
QCommandLineOption formatOptionsOption("format-options"_L1);
|
||||||
formatOptionsOption.setDescription(QStringLiteral("Prints the list of valid options for --option for the converter format <format>."));
|
formatOptionsOption.setDescription(
|
||||||
formatOptionsOption.setValueName("format");
|
"Prints the list of valid options for --option for the converter format <format>."_L1);
|
||||||
|
formatOptionsOption.setValueName("format"_L1);
|
||||||
parser.addOption(formatOptionsOption);
|
parser.addOption(formatOptionsOption);
|
||||||
|
|
||||||
parser.addPositionalArgument(QStringLiteral("[source]"),
|
parser.addPositionalArgument("[source]"_L1, "File to read from (stdin if none)"_L1);
|
||||||
QStringLiteral("File to read from (stdin if none)"));
|
parser.addPositionalArgument("[destination]"_L1, "File to write to (stdout if none)"_L1);
|
||||||
parser.addPositionalArgument(QStringLiteral("[destination]"),
|
|
||||||
QStringLiteral("File to write to (stdout if none)"));
|
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
if (parser.isSet(formatOptionsOption)) {
|
if (parser.isSet(formatOptionsOption)) {
|
||||||
QString format = parser.value(formatOptionsOption);
|
QString format = parser.value(formatOptionsOption);
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
if (conv->name() == format) {
|
if (conv->name() == format) {
|
||||||
const char *help = conv->optionsHelp();
|
const char *help = conv->optionsHelp();
|
||||||
if (help)
|
if (help) {
|
||||||
printf("The following options are available for format '%s':\n\n%s", qPrintable(format), help);
|
printf("The following options are available for format '%s':\n\n%s",
|
||||||
else
|
qPrintable(format), help);
|
||||||
|
} else {
|
||||||
printf("Format '%s' supports no options.\n", qPrintable(format));
|
printf("Format '%s' supports no options.\n", qPrintable(format));
|
||||||
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,10 +103,10 @@ int main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter *inconv = nullptr;
|
const Converter *inconv = nullptr;
|
||||||
QString format = parser.value(inputFormatOption);
|
QString format = parser.value(inputFormatOption);
|
||||||
if (format != "auto") {
|
if (format != "auto"_L1) {
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
if (conv->name() == format) {
|
if (conv->name() == format) {
|
||||||
inconv = conv;
|
inconv = conv;
|
||||||
break;
|
break;
|
||||||
@ -113,10 +119,10 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter *outconv = nullptr;
|
const Converter *outconv = nullptr;
|
||||||
format = parser.value(outputFormatOption);
|
format = parser.value(outputFormatOption);
|
||||||
if (format != "auto") {
|
if (format != "auto"_L1) {
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
if (conv->name() == format) {
|
if (conv->name() == format) {
|
||||||
outconv = conv;
|
outconv = conv;
|
||||||
break;
|
break;
|
||||||
@ -155,8 +161,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (!inconv) {
|
if (!inconv) {
|
||||||
// probe the input to find a file format
|
// probe the input to find a file format
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
if (conv->directions() & Converter::In && conv->probeFile(&input)) {
|
if (conv->directions().testFlag(Converter::Direction::In)
|
||||||
|
&& conv->probeFile(&input)) {
|
||||||
inconv = conv;
|
inconv = conv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -170,8 +177,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (!outconv) {
|
if (!outconv) {
|
||||||
// probe the output to find a file format
|
// probe the output to find a file format
|
||||||
for (Converter *conv : std::as_const(*availableConverters)) {
|
for (const Converter *conv : std::as_const(*availableConverters)) {
|
||||||
if (conv->directions() & Converter::Out && conv->probeFile(&output)) {
|
if (conv->directions().testFlag(Converter::Direction::Out)
|
||||||
|
&& conv->probeFile(&output)) {
|
||||||
outconv = conv;
|
outconv = conv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3,36 +3,38 @@
|
|||||||
|
|
||||||
#include "nullconverter.h"
|
#include "nullconverter.h"
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
static NullConverter nullConverter;
|
static NullConverter nullConverter;
|
||||||
Converter* Converter::null = &nullConverter;
|
Converter *Converter::null = &nullConverter;
|
||||||
|
|
||||||
QString NullConverter::name()
|
QString NullConverter::name() const
|
||||||
{
|
{
|
||||||
return QLatin1String("null");
|
return "null"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction NullConverter::directions()
|
Converter::Directions NullConverter::directions() const
|
||||||
{
|
{
|
||||||
return Out;
|
return Direction::Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options NullConverter::outputOptions()
|
Converter::Options NullConverter::outputOptions() const
|
||||||
{
|
{
|
||||||
return SupportsArbitraryMapKeys;
|
return SupportsArbitraryMapKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *NullConverter::optionsHelp()
|
const char *NullConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NullConverter::probeFile(QIODevice *f)
|
bool NullConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(f);
|
Q_UNUSED(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant NullConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(f);
|
Q_UNUSED(f);
|
||||||
Q_UNUSED(outputConverter);
|
Q_UNUSED(outputConverter);
|
||||||
@ -40,10 +42,12 @@ QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void NullConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
if (!options.isEmpty()) {
|
if (!options.isEmpty()) {
|
||||||
fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n", qPrintable(options.first()));
|
fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n",
|
||||||
|
qPrintable(options.first()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,14 @@ class NullConverter : public Converter
|
|||||||
{
|
{
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NULLCONVERTER_H
|
#endif // NULLCONVERTER_H
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
static void dumpVariant(QTextStream &out, const QVariant &v)
|
static void dumpVariant(QTextStream &out, const QVariant &v)
|
||||||
{
|
{
|
||||||
switch (v.userType()) {
|
switch (v.userType()) {
|
||||||
@ -42,67 +44,62 @@ static void dumpVariant(QTextStream &out, const QVariant &v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TextConverter::name()
|
QString TextConverter::name() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("text");
|
return "text"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction TextConverter::directions()
|
Converter::Directions TextConverter::directions() const
|
||||||
{
|
{
|
||||||
return InOut;
|
return Direction::InOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options TextConverter::outputOptions()
|
Converter::Options TextConverter::outputOptions() const
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *TextConverter::optionsHelp()
|
const char *TextConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextConverter::probeFile(QIODevice *f)
|
bool TextConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
if (QFile *file = qobject_cast<QFile *>(f))
|
if (QFile *file = qobject_cast<QFile *>(f))
|
||||||
return file->fileName().endsWith(QLatin1String(".txt"));
|
return file->fileName().endsWith(".txt"_L1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TextConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant TextConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
if (!outputConverter)
|
if (!outputConverter)
|
||||||
outputConverter = this;
|
outputConverter = this;
|
||||||
|
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
QTextStream in(f);
|
QTextStream in(f);
|
||||||
QString line ;
|
QString line;
|
||||||
while (!in.atEnd()) {
|
while (!in.atEnd()) {
|
||||||
in.readLineInto(&line);
|
in.readLineInto(&line);
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
qint64 v = line.toLongLong(&ok);
|
|
||||||
if (ok) {
|
if (qint64 v = line.toLongLong(&ok); ok)
|
||||||
list.append(v);
|
list.append(v);
|
||||||
continue;
|
else if (double d = line.toDouble(&ok); ok)
|
||||||
}
|
|
||||||
|
|
||||||
double d = line.toDouble(&ok);
|
|
||||||
if (ok) {
|
|
||||||
list.append(d);
|
list.append(d);
|
||||||
continue;
|
else
|
||||||
}
|
list.append(line);
|
||||||
|
|
||||||
list.append(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void TextConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
if (!options.isEmpty()) {
|
if (!options.isEmpty()) {
|
||||||
fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n", qPrintable(options.first()));
|
fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n",
|
||||||
|
qPrintable(options.first()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,16 +8,16 @@
|
|||||||
|
|
||||||
class TextConverter : public Converter
|
class TextConverter : public Converter
|
||||||
{
|
{
|
||||||
|
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TEXTCONVERTER_H
|
#endif // TEXTCONVERTER_H
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
static const char xmlOptionHelp[] =
|
using namespace Qt::StringLiterals;
|
||||||
"compact=no|yes Use compact XML form.\n";
|
|
||||||
|
static const char xmlOptionHelp[] = "compact=no|yes Use compact XML form.\n";
|
||||||
|
|
||||||
static XmlConverter xmlConverter;
|
static XmlConverter xmlConverter;
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
|||||||
static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options)
|
static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||||
{
|
{
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("list"))) {
|
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "list"_L1)) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
switch (xml.tokenType()) {
|
switch (xml.tokenType()) {
|
||||||
case QXmlStreamReader::StartElement:
|
case QXmlStreamReader::StartElement:
|
||||||
@ -47,8 +48,7 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||||
xml.lineNumber(), xml.columnNumber(),
|
|
||||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -57,10 +57,11 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Converter::Options options)
|
static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml,
|
||||||
|
Converter::Options options)
|
||||||
{
|
{
|
||||||
QVariant key, value;
|
QVariant key, value;
|
||||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("entry"))) {
|
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "entry"_L1)) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
switch (xml.tokenType()) {
|
switch (xml.tokenType()) {
|
||||||
case QXmlStreamReader::StartElement:
|
case QXmlStreamReader::StartElement:
|
||||||
@ -89,8 +90,7 @@ static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Conv
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||||
xml.lineNumber(), xml.columnNumber(),
|
|
||||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -103,11 +103,11 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
|||||||
QVariantMap map1;
|
QVariantMap map1;
|
||||||
VariantOrderedMap map2;
|
VariantOrderedMap map2;
|
||||||
|
|
||||||
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("map"))) {
|
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == "map"_L1)) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
switch (xml.tokenType()) {
|
switch (xml.tokenType()) {
|
||||||
case QXmlStreamReader::StartElement:
|
case QXmlStreamReader::StartElement:
|
||||||
if (xml.name() == QLatin1String("entry")) {
|
if (xml.name() == "entry"_L1) {
|
||||||
auto pair = mapEntryFromXml(xml, options);
|
auto pair = mapEntryFromXml(xml, options);
|
||||||
if (options & Converter::SupportsArbitraryMapKeys)
|
if (options & Converter::SupportsArbitraryMapKeys)
|
||||||
map2.append(pair);
|
map2.append(pair);
|
||||||
@ -134,8 +134,7 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||||
xml.lineNumber(), xml.columnNumber(),
|
|
||||||
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -149,18 +148,18 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
|
|||||||
static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options)
|
static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options)
|
||||||
{
|
{
|
||||||
QStringView name = xml.name();
|
QStringView name = xml.name();
|
||||||
if (name == QLatin1String("list"))
|
if (name == "list"_L1)
|
||||||
return listFromXml(xml, options);
|
return listFromXml(xml, options);
|
||||||
if (name == QLatin1String("map"))
|
if (name == "map"_L1)
|
||||||
return mapFromXml(xml, options);
|
return mapFromXml(xml, options);
|
||||||
if (name != QLatin1String("value")) {
|
if (name != "value"_L1) {
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML key '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML key '%s'.\n",
|
||||||
xml.lineNumber(), xml.columnNumber(), qPrintable(name.toString()));
|
xml.lineNumber(), xml.columnNumber(), qPrintable(name.toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QStringView type = attrs.value(QLatin1String("type"));
|
QStringView type = attrs.value("type"_L1);
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
@ -169,8 +168,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
|||||||
if (xml.isCDATA() || xml.isCharacters() || xml.isEndElement())
|
if (xml.isCDATA() || xml.isCharacters() || xml.isEndElement())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||||
xml.lineNumber(), xml.columnNumber(),
|
|
||||||
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -180,45 +178,45 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
|||||||
text = text.trimmed();
|
text = text.trimmed();
|
||||||
|
|
||||||
QVariant result;
|
QVariant result;
|
||||||
bool ok;
|
|
||||||
if (type.isEmpty()) {
|
if (type.isEmpty()) {
|
||||||
// ok
|
// ok
|
||||||
} else if (type == QLatin1String("number")) {
|
} else if (type == "number"_L1) {
|
||||||
// try integer first
|
// try integer first
|
||||||
|
bool ok;
|
||||||
qint64 v = text.toLongLong(&ok);
|
qint64 v = text.toLongLong(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
result = v;
|
result = v;
|
||||||
} else {
|
} else {
|
||||||
// let's see floating point
|
// let's see floating point
|
||||||
double d = text.toDouble(&ok);
|
double d = text.toDouble(&ok);
|
||||||
result = d;
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML: could not interpret '%s' as a number.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML: could not interpret '%s' as a number.\n",
|
||||||
xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString()));
|
xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
result = d;
|
||||||
}
|
}
|
||||||
} else if (type == QLatin1String("bytes")) {
|
} else if (type == "bytes"_L1) {
|
||||||
QByteArray data = text.toLatin1();
|
QByteArray data = text.toLatin1();
|
||||||
QStringView encoding = attrs.value("encoding");
|
QStringView encoding = attrs.value("encoding");
|
||||||
if (encoding == QLatin1String("base64url")) {
|
if (encoding == "base64url"_L1) {
|
||||||
result = QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding);
|
result = QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding);
|
||||||
} else if (encoding == QLatin1String("hex")) {
|
} else if (encoding == "hex"_L1) {
|
||||||
result = QByteArray::fromHex(data);
|
result = QByteArray::fromHex(data);
|
||||||
} else if (encoding.isEmpty() || encoding == QLatin1String("base64")) {
|
} else if (encoding.isEmpty() || encoding == "base64"_L1) {
|
||||||
result = QByteArray::fromBase64(data);
|
result = QByteArray::fromBase64(data);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML: unknown encoding '%s' for bytes.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML: unknown encoding '%s' for bytes.\n",
|
||||||
xml.lineNumber(), xml.columnNumber(), qPrintable(encoding.toString()));
|
xml.lineNumber(), xml.columnNumber(), qPrintable(encoding.toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (type == QLatin1String("string")) {
|
} else if (type == "string"_L1) {
|
||||||
result = text.toString();
|
result = text.toString();
|
||||||
} else if (type == QLatin1String("null")) {
|
} else if (type == "null"_L1) {
|
||||||
result = QVariant::fromValue(nullptr);
|
result = QVariant::fromValue(nullptr);
|
||||||
} else if (type == QLatin1String("CBOR simple type")) {
|
} else if (type == "CBOR simple type"_L1) {
|
||||||
result = QVariant::fromValue(QCborSimpleType(text.toShort()));
|
result = QVariant::fromValue(QCborSimpleType(text.toShort()));
|
||||||
} else if (type == QLatin1String("bits")) {
|
} else if (type == "bits"_L1) {
|
||||||
QBitArray ba;
|
QBitArray ba;
|
||||||
ba.resize(text.size());
|
ba.resize(text.size());
|
||||||
qsizetype n = 0;
|
qsizetype n = 0;
|
||||||
@ -238,13 +236,13 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
|||||||
result = ba;
|
result = ba;
|
||||||
} else {
|
} else {
|
||||||
int id = QMetaType::UnknownType;
|
int id = QMetaType::UnknownType;
|
||||||
if (type == QLatin1String("datetime"))
|
if (type == "datetime"_L1)
|
||||||
id = QMetaType::QDateTime;
|
id = QMetaType::QDateTime;
|
||||||
else if (type == QLatin1String("url"))
|
else if (type == "url"_L1)
|
||||||
id = QMetaType::QUrl;
|
id = QMetaType::QUrl;
|
||||||
else if (type == QLatin1String("uuid"))
|
else if (type == "uuid"_L1)
|
||||||
id = QMetaType::QUuid;
|
id = QMetaType::QUuid;
|
||||||
else if (type == QLatin1String("regex"))
|
else if (type == "regex"_L1)
|
||||||
id = QMetaType::QRegularExpression;
|
id = QMetaType::QRegularExpression;
|
||||||
else
|
else
|
||||||
id = QMetaType::fromName(type.toLatin1()).id();
|
id = QMetaType::fromName(type.toLatin1()).id();
|
||||||
@ -267,8 +265,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
|
|||||||
} while (xml.isComment() || xml.isWhitespace());
|
} while (xml.isComment() || xml.isWhitespace());
|
||||||
|
|
||||||
if (!xml.isEndElement()) {
|
if (!xml.isEndElement()) {
|
||||||
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
|
fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n", xml.lineNumber(), xml.columnNumber(),
|
||||||
xml.lineNumber(), xml.columnNumber(),
|
|
||||||
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
qPrintable(xml.tokenString()), qPrintable(name.toString()));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -287,9 +284,9 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
|||||||
variantToXml(xml, v);
|
variantToXml(xml, v);
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
} else if (type == QMetaType::QVariantMap || type == qMetaTypeId<VariantOrderedMap>()) {
|
} else if (type == QMetaType::QVariantMap || type == qMetaTypeId<VariantOrderedMap>()) {
|
||||||
const VariantOrderedMap map = (type == QMetaType::QVariantMap) ?
|
const VariantOrderedMap map = (type == QMetaType::QVariantMap)
|
||||||
VariantOrderedMap(v.toMap()) :
|
? VariantOrderedMap(v.toMap())
|
||||||
qvariant_cast<VariantOrderedMap>(v);
|
: qvariant_cast<VariantOrderedMap>(v);
|
||||||
|
|
||||||
xml.writeStartElement("map");
|
xml.writeStartElement("map");
|
||||||
for (const auto &pair : map) {
|
for (const auto &pair : map) {
|
||||||
@ -301,7 +298,7 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
|||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
} else {
|
} else {
|
||||||
xml.writeStartElement("value");
|
xml.writeStartElement("value");
|
||||||
QString typeString = QStringLiteral("type");
|
QString typeString = "type"_L1;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QMetaType::Short:
|
case QMetaType::Short:
|
||||||
case QMetaType::UShort:
|
case QMetaType::UShort:
|
||||||
@ -399,37 +396,37 @@ static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString XmlConverter::name()
|
QString XmlConverter::name() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("xml");
|
return "xml"_L1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Direction XmlConverter::directions()
|
Converter::Directions XmlConverter::directions() const
|
||||||
{
|
{
|
||||||
return InOut;
|
return Direction::InOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter::Options XmlConverter::outputOptions()
|
Converter::Options XmlConverter::outputOptions() const
|
||||||
{
|
{
|
||||||
return SupportsArbitraryMapKeys;
|
return SupportsArbitraryMapKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *XmlConverter::optionsHelp()
|
const char *XmlConverter::optionsHelp() const
|
||||||
{
|
{
|
||||||
return xmlOptionHelp;
|
return xmlOptionHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XmlConverter::probeFile(QIODevice *f)
|
bool XmlConverter::probeFile(QIODevice *f) const
|
||||||
{
|
{
|
||||||
if (QFile *file = qobject_cast<QFile *>(f)) {
|
if (QFile *file = qobject_cast<QFile *>(f)) {
|
||||||
if (file->fileName().endsWith(QLatin1String(".xml")))
|
if (file->fileName().endsWith(".xml"_L1))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return f->isReadable() && f->peek(5) == "<?xml";
|
return f->isReadable() && f->peek(5) == "<?xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant XmlConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
QVariant XmlConverter::loadFile(QIODevice *f, const Converter *&outputConverter) const
|
||||||
{
|
{
|
||||||
if (!outputConverter)
|
if (!outputConverter)
|
||||||
outputConverter = this;
|
outputConverter = this;
|
||||||
@ -445,13 +442,14 @@ QVariant XmlConverter::loadFile(QIODevice *f, Converter *&outputConverter)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmlConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
|
void XmlConverter::saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const
|
||||||
{
|
{
|
||||||
bool compact = false;
|
bool compact = false;
|
||||||
for (const QString &s : options) {
|
for (const QString &s : options) {
|
||||||
if (s == QLatin1String("compact=no")) {
|
if (s == "compact=no"_L1) {
|
||||||
compact = false;
|
compact = false;
|
||||||
} else if (s == QLatin1String("compact=yes")) {
|
} else if (s == "compact=yes"_L1) {
|
||||||
compact = true;
|
compact = true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown option '%s' to XML output. Valid options are:\n%s",
|
fprintf(stderr, "Unknown option '%s' to XML output. Valid options are:\n%s",
|
||||||
|
@ -10,13 +10,14 @@ class XmlConverter : public Converter
|
|||||||
{
|
{
|
||||||
// Converter interface
|
// Converter interface
|
||||||
public:
|
public:
|
||||||
QString name() override;
|
QString name() const override;
|
||||||
Direction directions() override;
|
Directions directions() const override;
|
||||||
Options outputOptions() override;
|
Options outputOptions() const override;
|
||||||
const char *optionsHelp() override;
|
const char *optionsHelp() const override;
|
||||||
bool probeFile(QIODevice *f) override;
|
bool probeFile(QIODevice *f) const override;
|
||||||
QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
|
QVariant loadFile(QIODevice *f, const Converter *&outputConverter) const override;
|
||||||
void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
|
void saveFile(QIODevice *f, const QVariant &contents,
|
||||||
|
const QStringList &options) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // XMLCONVERTER_H
|
#endif // XMLCONVERTER_H
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
||||||
|
|
||||||
/*
|
|
||||||
main.cpp
|
|
||||||
|
|
||||||
Provides the main function for the RSS news reader example.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
|
|
||||||
#include "rsslisting.h"
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Create an application and a main widget. Open the main widget for
|
|
||||||
user input, and exit with an appropriate return value when it is
|
|
||||||
closed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
QApplication app(argc, argv);
|
|
||||||
RSSListing *rsslisting = new RSSListing;
|
|
||||||
rsslisting->show();
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
@ -1,211 +0,0 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
||||||
|
|
||||||
/*
|
|
||||||
rsslisting.cpp
|
|
||||||
|
|
||||||
Provides a widget for displaying news items from RDF news sources.
|
|
||||||
RDF is an XML-based format for storing items of information (see
|
|
||||||
http://www.w3.org/RDF/ for details).
|
|
||||||
|
|
||||||
The widget itself provides a simple user interface for specifying
|
|
||||||
the URL of a news source, and controlling the downloading of news.
|
|
||||||
|
|
||||||
The widget downloads and parses the XML asynchronously, feeding the
|
|
||||||
data to an XML reader in pieces. This allows the user to interrupt
|
|
||||||
its operation, and also allows very large data sources to be read.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <QtCore>
|
|
||||||
#include <QtWidgets>
|
|
||||||
#include <QtNetwork>
|
|
||||||
|
|
||||||
#include "rsslisting.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Constructs an RSSListing widget with a simple user interface, and sets
|
|
||||||
up the XML reader to use a custom handler class.
|
|
||||||
|
|
||||||
The user interface consists of a line edit, a push button, and a
|
|
||||||
list view widget. The line edit is used for entering the URLs of news
|
|
||||||
sources; the push button starts the process of reading the
|
|
||||||
news.
|
|
||||||
*/
|
|
||||||
|
|
||||||
RSSListing::RSSListing(QWidget *parent)
|
|
||||||
: QWidget(parent), currentReply(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
lineEdit = new QLineEdit(this);
|
|
||||||
lineEdit->setText("http://blog.qt.io/feed/");
|
|
||||||
|
|
||||||
fetchButton = new QPushButton(tr("Fetch"), this);
|
|
||||||
|
|
||||||
treeWidget = new QTreeWidget(this);
|
|
||||||
connect(treeWidget, &QTreeWidget::itemActivated,
|
|
||||||
this, &RSSListing::itemActivated);
|
|
||||||
QStringList headerLabels;
|
|
||||||
headerLabels << tr("Title") << tr("Link");
|
|
||||||
treeWidget->setHeaderLabels(headerLabels);
|
|
||||||
treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
||||||
|
|
||||||
connect(&manager, &QNetworkAccessManager::finished,
|
|
||||||
this, &RSSListing::finished);
|
|
||||||
|
|
||||||
connect(lineEdit, &QLineEdit::returnPressed, this, &RSSListing::fetch);
|
|
||||||
connect(fetchButton, &QPushButton::clicked, this, &RSSListing::fetch);
|
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
|
||||||
|
|
||||||
QHBoxLayout *hboxLayout = new QHBoxLayout;
|
|
||||||
|
|
||||||
hboxLayout->addWidget(lineEdit);
|
|
||||||
hboxLayout->addWidget(fetchButton);
|
|
||||||
|
|
||||||
layout->addLayout(hboxLayout);
|
|
||||||
layout->addWidget(treeWidget);
|
|
||||||
|
|
||||||
setWindowTitle(tr("RSS listing example"));
|
|
||||||
resize(640,480);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Starts the network request and connects the needed signals
|
|
||||||
*/
|
|
||||||
void RSSListing::get(const QUrl &url)
|
|
||||||
{
|
|
||||||
QNetworkRequest request(url);
|
|
||||||
if (currentReply) {
|
|
||||||
currentReply->disconnect(this);
|
|
||||||
currentReply->deleteLater();
|
|
||||||
}
|
|
||||||
currentReply = manager.get(request);
|
|
||||||
connect(currentReply, &QNetworkReply::readyRead, this, &RSSListing::readyRead);
|
|
||||||
connect(currentReply, &QNetworkReply::metaDataChanged, this, &RSSListing::metaDataChanged);
|
|
||||||
connect(currentReply, &QNetworkReply::errorOccurred, this, &RSSListing::error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Starts fetching data from a news source specified in the line
|
|
||||||
edit widget.
|
|
||||||
|
|
||||||
The line edit is made read only to prevent the user from modifying its
|
|
||||||
contents during the fetch; this is only for cosmetic purposes.
|
|
||||||
The fetch button is disabled, the list view is cleared, and we
|
|
||||||
define the last list view item to be 0, meaning that there are no
|
|
||||||
existing items in the list.
|
|
||||||
|
|
||||||
A URL is created with the raw contents of the line edit and
|
|
||||||
a get is initiated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void RSSListing::fetch()
|
|
||||||
{
|
|
||||||
lineEdit->setReadOnly(true);
|
|
||||||
fetchButton->setEnabled(false);
|
|
||||||
treeWidget->clear();
|
|
||||||
|
|
||||||
xml.clear();
|
|
||||||
|
|
||||||
QUrl url(lineEdit->text());
|
|
||||||
get(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RSSListing::metaDataChanged()
|
|
||||||
{
|
|
||||||
QUrl redirectionTarget = currentReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
|
||||||
if (redirectionTarget.isValid()) {
|
|
||||||
get(redirectionTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Reads data received from the RDF source.
|
|
||||||
|
|
||||||
We read all the available data, and pass it to the XML
|
|
||||||
stream reader. Then we call the XML parsing function.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void RSSListing::readyRead()
|
|
||||||
{
|
|
||||||
int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (statusCode >= 200 && statusCode < 300) {
|
|
||||||
QByteArray data = currentReply->readAll();
|
|
||||||
xml.addData(data);
|
|
||||||
parseXml();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Finishes processing an HTTP request.
|
|
||||||
|
|
||||||
The default behavior is to keep the text edit read only.
|
|
||||||
|
|
||||||
If an error has occurred, the user interface is made available
|
|
||||||
to the user for further input, allowing a new fetch to be
|
|
||||||
started.
|
|
||||||
|
|
||||||
If the HTTP get request has finished, we make the
|
|
||||||
user interface available to the user for further input.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void RSSListing::finished(QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
Q_UNUSED(reply);
|
|
||||||
lineEdit->setReadOnly(false);
|
|
||||||
fetchButton->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Parses the XML data and creates treeWidget items accordingly.
|
|
||||||
*/
|
|
||||||
void RSSListing::parseXml()
|
|
||||||
{
|
|
||||||
while (!xml.atEnd()) {
|
|
||||||
xml.readNext();
|
|
||||||
if (xml.isStartElement()) {
|
|
||||||
if (xml.name() == u"item")
|
|
||||||
linkString = xml.attributes().value("rss:about").toString();
|
|
||||||
currentTag = xml.name().toString();
|
|
||||||
} else if (xml.isEndElement()) {
|
|
||||||
if (xml.name() == u"item") {
|
|
||||||
|
|
||||||
QTreeWidgetItem *item = new QTreeWidgetItem;
|
|
||||||
item->setText(0, titleString);
|
|
||||||
item->setText(1, linkString);
|
|
||||||
treeWidget->addTopLevelItem(item);
|
|
||||||
|
|
||||||
titleString.clear();
|
|
||||||
linkString.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (xml.isCharacters() && !xml.isWhitespace()) {
|
|
||||||
if (currentTag == "title")
|
|
||||||
titleString += xml.text();
|
|
||||||
else if (currentTag == "link")
|
|
||||||
linkString += xml.text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
|
|
||||||
qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Open the link in the browser
|
|
||||||
*/
|
|
||||||
void RSSListing::itemActivated(QTreeWidgetItem * item)
|
|
||||||
{
|
|
||||||
QDesktopServices::openUrl(QUrl(item->text(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RSSListing::error(QNetworkReply::NetworkError)
|
|
||||||
{
|
|
||||||
qWarning("error retrieving RSS feed");
|
|
||||||
currentReply->disconnect(this);
|
|
||||||
currentReply->deleteLater();
|
|
||||||
currentReply = 0;
|
|
||||||
}
|
|
@ -4,6 +4,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(savegame LANGUAGES CXX)
|
project(savegame LANGUAGES CXX)
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
message(FATAL_ERROR "This project cannot be built on Android.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||||
set(INSTALL_EXAMPLESDIR "examples")
|
set(INSTALL_EXAMPLESDIR "examples")
|
||||||
endif()
|
endif()
|
||||||
|
@ -6,15 +6,10 @@
|
|||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
Character::Character()
|
Character::Character() = default;
|
||||||
= default;
|
|
||||||
|
|
||||||
Character::Character(const QString &name,
|
Character::Character(const QString &name, int level, Character::ClassType classType)
|
||||||
int level,
|
: mName(name), mLevel(level), mClassType(classType)
|
||||||
Character::ClassType classType) :
|
|
||||||
mName(name),
|
|
||||||
mLevel(level),
|
|
||||||
mClassType(classType)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,35 +43,41 @@ void Character::setClassType(Character::ClassType classType)
|
|||||||
mClassType = classType;
|
mClassType = classType;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! [0]
|
//! [fromJson]
|
||||||
void Character::read(const QJsonObject &json)
|
Character Character::fromJson(const QJsonObject &json)
|
||||||
{
|
{
|
||||||
if (json.contains("name") && json["name"].isString())
|
Character result;
|
||||||
mName = json["name"].toString();
|
|
||||||
|
|
||||||
if (json.contains("level") && json["level"].isDouble())
|
if (const QJsonValue v = json["name"]; v.isString())
|
||||||
mLevel = json["level"].toInt();
|
result.mName = v.toString();
|
||||||
|
|
||||||
if (json.contains("classType") && json["classType"].isDouble())
|
if (const QJsonValue v = json["level"]; v.isDouble())
|
||||||
mClassType = ClassType(json["classType"].toInt());
|
result.mLevel = v.toInt();
|
||||||
|
|
||||||
|
if (const QJsonValue v = json["classType"]; v.isDouble())
|
||||||
|
result.mClassType = ClassType(v.toInt());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
//! [0]
|
//! [fromJson]
|
||||||
|
|
||||||
//! [1]
|
//! [toJson]
|
||||||
void Character::write(QJsonObject &json) const
|
QJsonObject Character::toJson() const
|
||||||
{
|
{
|
||||||
|
QJsonObject json;
|
||||||
json["name"] = mName;
|
json["name"] = mName;
|
||||||
json["level"] = mLevel;
|
json["level"] = mLevel;
|
||||||
json["classType"] = mClassType;
|
json["classType"] = mClassType;
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
//! [1]
|
//! [toJson]
|
||||||
|
|
||||||
void Character::print(int indentation) const
|
void Character::print(QTextStream &s, int indentation) const
|
||||||
{
|
{
|
||||||
const QString indent(indentation * 2, ' ');
|
const QString indent(indentation * 2, ' ');
|
||||||
QTextStream(stdout) << indent << "Name:\t" << mName << "\n";
|
const QString className = QMetaEnum::fromType<ClassType>().valueToKey(mClassType);
|
||||||
QTextStream(stdout) << indent << "Level:\t" << mLevel << "\n";
|
|
||||||
|
|
||||||
QString className = QMetaEnum::fromType<ClassType>().valueToKey(mClassType);
|
s << indent << "Name:\t" << mName << "\n"
|
||||||
QTextStream(stdout) << indent << "Class:\t" << className << "\n";
|
<< indent << "Level:\t" << mLevel << "\n"
|
||||||
|
<< indent << "Class:\t" << className << "\n";
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,15 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QTextStream)
|
||||||
|
|
||||||
//! [0]
|
//! [0]
|
||||||
class Character
|
class Character
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ClassType {
|
enum ClassType { Warrior, Mage, Archer };
|
||||||
Warrior, Mage, Archer
|
|
||||||
};
|
|
||||||
Q_ENUM(ClassType)
|
Q_ENUM(ClassType)
|
||||||
|
|
||||||
Character();
|
Character();
|
||||||
@ -31,10 +31,11 @@ public:
|
|||||||
ClassType classType() const;
|
ClassType classType() const;
|
||||||
void setClassType(ClassType classType);
|
void setClassType(ClassType classType);
|
||||||
|
|
||||||
void read(const QJsonObject &json);
|
static Character fromJson(const QJsonObject &json);
|
||||||
void write(QJsonObject &json) const;
|
QJsonObject toJson() const;
|
||||||
|
|
||||||
|
void print(QTextStream &s, int indentation = 0) const;
|
||||||
|
|
||||||
void print(int indentation = 0) const;
|
|
||||||
private:
|
private:
|
||||||
QString mName;
|
QString mName;
|
||||||
int mLevel = 0;
|
int mLevel = 0;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\example serialization/savegame
|
\example serialization/savegame
|
||||||
\examplecategory {Input/Output}
|
\examplecategory {Data Processing & I/O}
|
||||||
\title JSON Save Game Example
|
\title JSON Save Game Example
|
||||||
|
|
||||||
\brief The JSON Save Game example demonstrates how to save and load a
|
\brief The JSON Save Game example demonstrates how to save and load a
|
||||||
@ -11,11 +11,12 @@
|
|||||||
|
|
||||||
Many games provide save functionality, so that the player's progress through
|
Many games provide save functionality, so that the player's progress through
|
||||||
the game can be saved and loaded at a later time. The process of saving a
|
the game can be saved and loaded at a later time. The process of saving a
|
||||||
game generally involves serializing each game object's member variables
|
game generally involves serializing each game object's member variables to a
|
||||||
to a file. Many formats can be used for this purpose, one of which is JSON.
|
file. Many formats can be used for this purpose, one of which is JSON. With
|
||||||
With QJsonDocument, you also have the ability to serialize a document in a
|
QJsonDocument, you also have the ability to serialize a document in a \l
|
||||||
\l {RFC 7049} {CBOR} format, which is great if you
|
{RFC 7049} {CBOR} format, which is great if you don't want the save file to
|
||||||
don't want the save file to be readable, or if you need to keep the file size down.
|
be easy to read (but see \l {Parsing and displaying CBOR data} for how it \e
|
||||||
|
can be read), or if you need to keep the file size down.
|
||||||
|
|
||||||
In this example, we'll demonstrate how to save and load a simple game to
|
In this example, we'll demonstrate how to save and load a simple game to
|
||||||
and from JSON and binary formats.
|
and from JSON and binary formats.
|
||||||
@ -25,45 +26,83 @@
|
|||||||
The Character class represents a non-player character (NPC) in our game, and
|
The Character class represents a non-player character (NPC) in our game, and
|
||||||
stores the player's name, level, and class type.
|
stores the player's name, level, and class type.
|
||||||
|
|
||||||
It provides read() and write() functions to serialise its member variables.
|
It provides static fromJson() and non-static toJson() functions to
|
||||||
|
serialise itself.
|
||||||
|
|
||||||
|
\note This pattern (fromJson()/toJson()) works because QJsonObjects can be
|
||||||
|
constructed independent of an owning QJsonDocument, and because the data
|
||||||
|
types being (de)serialized here are value types, so can be copied. When
|
||||||
|
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()
|
||||||
|
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.
|
||||||
|
|
||||||
\snippet serialization/savegame/character.h 0
|
\snippet serialization/savegame/character.h 0
|
||||||
|
|
||||||
Of particular interest to us are the read and write function
|
Of particular interest to us are the fromJson() and toJson() function
|
||||||
implementations:
|
implementations:
|
||||||
|
|
||||||
\snippet serialization/savegame/character.cpp 0
|
\snippet serialization/savegame/character.cpp fromJson
|
||||||
|
|
||||||
In the read() function, we assign Character's members values from the
|
In the fromJson() function, we construct a local \c result Character object
|
||||||
QJsonObject argument. You can use either \l QJsonObject::operator[]() or
|
and assign \c{result}'s members values from the QJsonObject argument. You
|
||||||
QJsonObject::value() to access values within the JSON object; both are
|
can use either \l QJsonObject::operator[]() or QJsonObject::value() to
|
||||||
const functions and return QJsonValue::Undefined if the key is invalid. We
|
access values within the JSON object; both are const functions and return
|
||||||
check if the keys are valid before attempting to read them with
|
QJsonValue::Undefined if the key is invalid. In particular, the \c{is...}
|
||||||
QJsonObject::contains().
|
functions (for example \l QJsonValue::isString(), \l
|
||||||
|
QJsonValue::isDouble()) return \c false for QJsonValue::Undefined, so we
|
||||||
|
can check for existence as well as the correct type in a single lookup.
|
||||||
|
|
||||||
\snippet serialization/savegame/character.cpp 1
|
If a value does not exist in the JSON object, or has the wrong type, we
|
||||||
|
don't write to the corresponding \c result member, either, thereby
|
||||||
|
preserving any values the default constructor may have set. This means
|
||||||
|
default values are centrally defined in one location (the default
|
||||||
|
constructor) and need not be repeated in serialisation code
|
||||||
|
(\l{https://en.wikipedia.org/wiki/Don%27t_repeat_yourself}{DRY}).
|
||||||
|
|
||||||
In the write() function, we do the reverse of the read() function; assign
|
Observe the use of
|
||||||
values from the Character object to the JSON object. As with accessing
|
\l{https://en.cppreference.com/w/cpp/language/if#If_statements_with_initializer}
|
||||||
values, there are two ways to set values on a QJsonObject:
|
{C++17 if-with-initializer} to separate scoping and checking of the variable \c v.
|
||||||
\l QJsonObject::operator[]() and QJsonObject::insert(). Both will override
|
This means we can keep the variable name short, because its scope is limited.
|
||||||
any existing value at the given key.
|
|
||||||
|
|
||||||
Next up is the Level class:
|
Compare that to the naïve approach using \c QJsonObject::contains():
|
||||||
|
|
||||||
|
\badcode
|
||||||
|
if (json.contains("name") && json["name"].isString())
|
||||||
|
result.mName = json["name"].toString();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
which, beside being less readable, requires a total of three lookups (no,
|
||||||
|
the compiler will \e not optimize these into one), so is three times
|
||||||
|
slower and repeats \c{"name"} three times (violating the DRY principle).
|
||||||
|
|
||||||
|
\snippet serialization/savegame/character.cpp toJson
|
||||||
|
|
||||||
|
In the toJson() function, we do the reverse of the fromJson() function;
|
||||||
|
assign values from the Character object to a new JSON object we then
|
||||||
|
return. As with accessing values, there are two ways to set values on a
|
||||||
|
QJsonObject: \l QJsonObject::operator[]() and \l QJsonObject::insert().
|
||||||
|
Both will override any existing value at the given key.
|
||||||
|
|
||||||
|
\section1 The Level Class
|
||||||
|
|
||||||
\snippet serialization/savegame/level.h 0
|
\snippet serialization/savegame/level.h 0
|
||||||
|
|
||||||
We want to have several levels in our game, each with several NPCs, so we
|
We want the levels in our game to each each have several NPCs, so we keep a QList
|
||||||
keep a QList of Character objects. We also provide the familiar read() and
|
of Character objects. We also provide the familiar fromJson() and toJson()
|
||||||
write() functions.
|
functions.
|
||||||
|
|
||||||
\snippet serialization/savegame/level.cpp 0
|
\snippet serialization/savegame/level.cpp fromJson
|
||||||
|
|
||||||
Containers can be written and read to and from JSON using QJsonArray. In our
|
Containers can be written to and read from JSON using QJsonArray. In our
|
||||||
case, we construct a QJsonArray from the value associated with the key
|
case, we construct a QJsonArray from the value associated with the key
|
||||||
\c "npcs". Then, for each QJsonValue element in the array, we call
|
\c "npcs". Then, for each QJsonValue element in the array, we call
|
||||||
toObject() to get the Character's JSON object. The Character object can then
|
toObject() to get the Character's JSON object. Character::fromJson() can
|
||||||
read their JSON and be appended to our NPC array.
|
then turn that QJSonObject into a Character object to append to our NPC array.
|
||||||
|
|
||||||
\note \l{Container Classes}{Associate containers} can be written by storing
|
\note \l{Container Classes}{Associate containers} can be written by storing
|
||||||
the key in each value object (if it's not already). With this approach, the
|
the key in each value object (if it's not already). With this approach, the
|
||||||
@ -71,11 +110,13 @@
|
|||||||
element is used as the key to construct the container when reading it back
|
element is used as the key to construct the container when reading it back
|
||||||
in.
|
in.
|
||||||
|
|
||||||
\snippet serialization/savegame/level.cpp 1
|
\snippet serialization/savegame/level.cpp toJson
|
||||||
|
|
||||||
Again, the write() function is similar to the read() function, except
|
Again, the toJson() function is similar to the fromJson() function, except
|
||||||
reversed.
|
reversed.
|
||||||
|
|
||||||
|
\section1 The Game Class
|
||||||
|
|
||||||
Having established the Character and Level classes, we can move on to
|
Having established the Character and Level classes, we can move on to
|
||||||
the Game class:
|
the Game class:
|
||||||
|
|
||||||
@ -87,26 +128,43 @@
|
|||||||
Next, we provide accessors for the player and levels. We then expose three
|
Next, we provide accessors for the player and levels. We then expose three
|
||||||
functions: newGame(), saveGame() and loadGame().
|
functions: newGame(), saveGame() and loadGame().
|
||||||
|
|
||||||
The read() and write() functions are used by saveGame() and loadGame().
|
The read() and toJson() functions are used by saveGame() and loadGame().
|
||||||
|
|
||||||
\snippet serialization/savegame/game.cpp 0
|
\div{class="admonition note"}\b{Note:}
|
||||||
|
Despite \c Game being a value class, we assume that the author wants a game to have
|
||||||
|
identity, much like your main window would have. We therefore don't use a
|
||||||
|
static fromJson() function, which would create a new object, but a read()
|
||||||
|
function we can call on existing objects. There's a 1:1 correspondence
|
||||||
|
between read() and fromJson(), in that one can be implemented in terms of
|
||||||
|
the other:
|
||||||
|
|
||||||
|
\code
|
||||||
|
void read(const QJsonObject &json) { *this = fromJson(json); }
|
||||||
|
static Game fromObject(const QJsonObject &json) { Game g; g.read(json); return g; }
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
We just use what's more convenient for callers of the functions.
|
||||||
|
\enddiv
|
||||||
|
|
||||||
|
\snippet serialization/savegame/game.cpp newGame
|
||||||
|
|
||||||
To setup a new game, we create the player and populate the levels and their
|
To setup a new game, we create the player and populate the levels and their
|
||||||
NPCs.
|
NPCs.
|
||||||
|
|
||||||
\snippet serialization/savegame/game.cpp 1
|
\snippet serialization/savegame/game.cpp read
|
||||||
|
|
||||||
The first thing we do in the read() function is tell the player to read
|
The read() function starts by replacing the player with the
|
||||||
itself. We then clear the level array so that calling loadGame() on the
|
one read from JSON. We then clear() the level array so that calling
|
||||||
same Game object twice doesn't result in old levels hanging around.
|
loadGame() on the same Game object twice doesn't result in old levels
|
||||||
|
hanging around.
|
||||||
|
|
||||||
We then populate the level array by reading each Level from a QJsonArray.
|
We then populate the level array by reading each Level from a QJsonArray.
|
||||||
|
|
||||||
\snippet serialization/savegame/game.cpp 2
|
\snippet serialization/savegame/game.cpp toJson
|
||||||
|
|
||||||
We write the game to JSON similarly to how we write Level.
|
Writing the game to JSON is similar to writing a level.
|
||||||
|
|
||||||
\snippet serialization/savegame/game.cpp 3
|
\snippet serialization/savegame/game.cpp loadGame
|
||||||
|
|
||||||
When loading a saved game in loadGame(), the first thing we do is open the
|
When loading a saved game in loadGame(), the first thing we do is open the
|
||||||
save file based on which format it was saved to; \c "save.json" for JSON,
|
save file based on which format it was saved to; \c "save.json" for JSON,
|
||||||
@ -120,14 +178,16 @@
|
|||||||
After constructing the QJsonDocument, we instruct the Game object to read
|
After constructing the QJsonDocument, we instruct the Game object to read
|
||||||
itself and then return \c true to indicate success.
|
itself and then return \c true to indicate success.
|
||||||
|
|
||||||
\snippet serialization/savegame/game.cpp 4
|
\snippet serialization/savegame/game.cpp saveGame
|
||||||
|
|
||||||
Not surprisingly, saveGame() looks very much like loadGame(). We determine
|
Not surprisingly, saveGame() looks very much like loadGame(). We determine
|
||||||
the file extension based on the format, print a warning and return \c false
|
the file extension based on the format, print a warning and return \c false
|
||||||
if the opening of the file fails. We then write the Game object to a
|
if the opening of the file fails. We then write the Game object to a
|
||||||
QJsonDocument, and call either QJsonDocument::toJson() or to
|
QJsonObject. To save the game in the format that was specified, we
|
||||||
QJsonDocument::toBinaryData() to save the game, depending on which format
|
convert the JSON object into either a QJsonDocument for a subsequent
|
||||||
was specified.
|
QJsonDocument::toJson() call, or a QCborValue for QCborValue::toCbor().
|
||||||
|
|
||||||
|
\section1 Tying It All Together
|
||||||
|
|
||||||
We are now ready to enter main():
|
We are now ready to enter main():
|
||||||
|
|
||||||
|