diff options
141 files changed, 2115 insertions, 2127 deletions
diff --git a/config.tests/common/verifyspec/verifyspec.pro b/config.tests/common/verifyspec/verifyspec.pro index d78ed2985a..11a280e4ce 100644 --- a/config.tests/common/verifyspec/verifyspec.pro +++ b/config.tests/common/verifyspec/verifyspec.pro @@ -1 +1,37 @@ SOURCES = verifyspec.cpp + +# Provide a function to be used by mkspecs +defineTest(deviceSanityCheckCompiler) { + equals(QMAKE_HOST.os, Windows): \ + sfx = .exe + else: \ + sfx = + + # Build the compiler filename using the first value in QMAKE_CXX in order to + # support tools like ccache, which give QMAKE_CXX values of the form: + # ccache <path_to_compiler> + compiler = $$first(QMAKE_CXX)$$sfx + + # Check if the binary exists with an absolute path. Do this check + # before the CROSS_COMPILE empty check below to allow the mkspec + # to derive the compiler path from other device options. + exists($$compiler): return() + + # Check for possible reasons of failure + # check if CROSS_COMPILE device-option is set + isEmpty(CROSS_COMPILE): \ + error("CROSS_COMPILE needs to be set via -device-option CROSS_COMPILE=<path>") + + # Check if QMAKE_CXX points to an executable. + ensurePathEnv() + for (dir, QMAKE_PATH_ENV) { + exists($$dir/$${compiler}): \ + return() + } + + # QMAKE_CXX does not point to a compiler. + error("Compiler $$QMAKE_CXX not found. Check the value of CROSS_COMPILE -device-option") +} + +defined(qtConfSanitizeMkspec, test): \ + qtConfSanitizeMkspec() diff --git a/config_help.txt b/config_help.txt index 28634be947..bf50491110 100644 --- a/config_help.txt +++ b/config_help.txt @@ -85,7 +85,6 @@ Build options: -framework ........... Build Qt framework bundles [yes] (Apple only) -platform <target> ... Select host mkspec [detected] - -host-option <key=value> ..... Add option for the host mkspec -xplatform <target> .. Select target mkspec when cross-compiling [PLATFORM] -device <name> ....... Cross-compile for device <name> -device-option <key=value> ... Add option for the device mkspec @@ -84,9 +84,8 @@ if [ x"$1" = x"-top-level" ]; then shift fi -CFG_REDO=no -OPT_CMDLINE= # excluding -verbose (for config.opt) -QMAKE_CMDLINE= # including -verbose (for actual parsing) +OPT_CMDLINE= # expanded version for the script +QMAKE_CMDLINE= # verbatim version for qmake call set -f # suppress globbing in for loop SAVED_IFS=$IFS IFS=' @@ -105,13 +104,7 @@ for i in "$@"; do for a in `cat $optfile`; do OPT_CMDLINE="$OPT_CMDLINE $a" - QMAKE_CMDLINE="$QMAKE_CMDLINE -$a" done - CFG_REDO=yes # suppress repeated config.opt writeout - continue - ;; - -v|-verbose|--verbose|-no-v|-no-verbose|--no-verbose) ;; *) OPT_CMDLINE="$OPT_CMDLINE @@ -122,43 +115,16 @@ $i" $i" done set -- -for i in $QMAKE_CMDLINE; do +for i in $OPT_CMDLINE; do set -- "$@" "$i" done set +f IFS=$SAVED_IFS -# initialize global variables -DEVICE_VARS_FILE=.device.vars -HOST_VARS_FILE=.host.vars - -:> "$DEVICE_VARS_FILE" -:> "$HOST_VARS_FILE" - #------------------------------------------------------------------------------- # utility functions #------------------------------------------------------------------------------- -makeabs() -{ - local FILE="$1" - local RES="$FILE" - if [ -z "${FILE##/*}" ]; then - true - elif [ "$OSTYPE" = "msys" -a -z "${FILE##[a-zA-Z]:[/\\]*}" ]; then - true - else - RES=$PWD/$FILE - fi - RES=$RES/ - while true; do - nres=`echo "$RES" | sed 's,/[^/][^/]*/\.\./,/,g; s,/\./,/,g'` - test x"$nres" = x"$RES" && break - RES=$nres - done - echo "$RES" | sed 's,//,/,g; s,/$,,' -} - # Helper function for getQMakeConf. It parses include statements in # qmake.conf and prints out the expanded file expandQMakeConf() @@ -172,15 +138,7 @@ expandQMakeConf() echo "WARNING: Unable to find file $conf_file" >&2 continue fi - expandQMakeConf "$conf_file" "$2" - ;; - *load\(device_config\)*) - conf_file="$2" - if [ ! -f "$conf_file" ]; then - echo "WARNING: Unable to find file $conf_file" >&2 - continue - fi - expandQMakeConf "$conf_file" "$2" + expandQMakeConf "$conf_file" ;; *) echo "$line" @@ -195,12 +153,6 @@ BEGIN { values["LITERAL_WHITESPACE"] = " " values["LITERAL_DOLLAR"] = "$" } -/^!?host_build:/ { - scopeStart = index($0, ":") + 1 - condition = substr($0, 0, scopeStart - 2) - if (condition != "'"$1"'") { next } - $0 = substr($0, scopeStart) -} /^[_A-Z0-9.]+[ \t]*\+?=/ { valStart = index($0, "=") + 1 @@ -325,72 +277,12 @@ macSDKify() getQMakeConf() { if [ -z "$specvals" ]; then - specvals=`expandQMakeConf "$QMAKESPEC/qmake.conf" "$HOST_VARS_FILE" | extractQMakeVariables "host_build"` + specvals=`expandQMakeConf "$QMAKESPEC/qmake.conf" | extractQMakeVariables` if [ "$BUILD_ON_MAC" = "yes" ]; then specvals=$(macSDKify "$specvals"); fi fi getSingleQMakeVariable "$1" "$specvals" } -getXQMakeConf() -{ - if [ -z "$xspecvals" ]; then - xspecvals=`expandQMakeConf "$XQMAKESPEC/qmake.conf" "$DEVICE_VARS_FILE" | extractQMakeVariables "!host_build"` - if [ "$XPLATFORM_MAC" = "yes" ]; then xspecvals=$(macSDKify "$xspecvals"); fi - fi - getSingleQMakeVariable "$1" "$xspecvals" -} - -#------------------------------------------------------------------------------- -# device options -#------------------------------------------------------------------------------- -DeviceVar() -{ - case "$1" in - set) - eq="=" - ;; - *) - echo >&2 "BUG: wrong command to DeviceVar: $1" - ;; - esac - - echo "$2" "$eq" "$3" >> "$DEVICE_VARS_FILE" -} - -resolveDeviceMkspec() -{ - result=$(find "$relpath/mkspecs/devices/" -type d -name "*$1*" | sed "s,^$relpath/mkspecs/,,") - match_count=$(echo "$result" | wc -w) - if [ "$match_count" -gt 1 ]; then - echo >&2 "Error: Multiple matches for device '$1'. Candidates are:" - tabbed_result=$(echo "$result" | sed 's,^, ,') - echo >&2 "$tabbed_result" - echo "undefined" - elif [ "$match_count" -eq 0 ]; then - echo >&2 "Error: No device matching '$1'" - echo "undefined" - else - echo "$result" - fi -} - -#------------------------------------------------------------------------------- -# Host options -#------------------------------------------------------------------------------- -HostVar() -{ - case "$1" in - set) - eq="=" - ;; - *) - echo >&2 "BUG: wrong command to HostVar: $1" - ;; - esac - - echo "$2" "$eq" "$3" >> "$HOST_VARS_FILE" -} - #------------------------------------------------------------------------------- # operating system detection #------------------------------------------------------------------------------- @@ -452,83 +344,18 @@ fi # initalize variables #------------------------------------------------------------------------------- -# Use CC/CXX to run config.tests -mkdir -p "$outpath/config.tests" -rm -f "$outpath/config.tests/.qmake.cache" -: > "$outpath/config.tests/.qmake.cache" - # QTDIR may be set and point to an old or system-wide Qt installation unset QTDIR # initalize internal variables CFG_RELEASE_TOOLS=no - -XPLATFORM= # This seems to be the QMAKESPEC, like "linux-g++" -XPLATFORM_MAC=no # Whether target platform is macOS, iOS, tvOS, or watchOS -XPLATFORM_IOS=no # Whether target platform is iOS -XPLATFORM_TVOS=no # Whether target platform is tvOS -XPLATFORM_WATCHOS=no # Whether target platform is watchOS -XPLATFORM_ANDROID=no -XPLATFORM_MINGW=no # Whether target platform is MinGW (win32-g++*) PLATFORM= -OPT_CONFIRM_LICENSE=no OPT_SHADOW=maybe OPT_VERBOSE=no OPT_HELP= CFG_SILENT=no -OPT_MAC_SDK= -COMMERCIAL_USER=ask CFG_DEV=no -# initalize variables used for installation -QT_INSTALL_PREFIX= -QT_INSTALL_DOCS= -QT_INSTALL_HEADERS= -QT_INSTALL_LIBS= -QT_INSTALL_BINS= -QT_INSTALL_LIBEXECS= -QT_INSTALL_PLUGINS= -QT_INSTALL_IMPORTS= -QT_INSTALL_QML= -QT_INSTALL_ARCHDATA= -QT_INSTALL_DATA= -QT_INSTALL_TRANSLATIONS= -QT_INSTALL_SETTINGS= -QT_INSTALL_EXAMPLES= -QT_INSTALL_TESTS= -CFG_SYSROOT= -QT_HOST_PREFIX= -QT_HOST_BINS= -QT_HOST_LIBS= -QT_HOST_DATA= -QT_EXT_PREFIX= - -# Android vars -if [ -z "$ANDROID_SDK_ROOT" ]; then - if [ "$UNAME_SYSTEM" = "Darwin" ] && [ -d "$HOME/Library/Android/sdk" ]; then - ANDROID_SDK_ROOT="$HOME/Library/Android/sdk" - elif [ "$UNAME_SYSTEM" = "Linux" ] && [ -d "$HOME/Android/Sdk" ]; then - ANDROID_SDK_ROOT="$HOME/Android/Sdk" - fi -fi - -if [ -z "$ANDROID_NDK_ROOT" ]; then - if [ -d "$ANDROID_SDK_ROOT/ndk-bundle" ]; then - ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/ndk-bundle" - elif [ "$UNAME_SYSTEM" = "Darwin" ] && [ -d "$HOME/Library/Android/sdk/ndk-bundle" ]; then - ANDROID_NDK_ROOT="$HOME/Library/Android/sdk/ndk-bundle" - elif [ "$UNAME_SYSTEM" = "Linux" ] && [ -d "$HOME/Android/Sdk/ndk-bundle" ]; then - ANDROID_NDK_ROOT="$HOME/Android/Sdk/ndk-bundle" - fi -fi - -CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT -CFG_DEFAULT_ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT -CFG_DEFAULT_ANDROID_PLATFORM=android-16 -CFG_DEFAULT_ANDROID_TARGET_ARCH=armeabi-v7a -CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION=4.9 -CFG_DEFAULT_ANDROID_NDK_HOST=$ANDROID_NDK_HOST - #------------------------------------------------------------------------------- # parse command line arguments #------------------------------------------------------------------------------- @@ -597,7 +424,6 @@ while [ "$#" -gt 0 ]; do -xplatform| \ -device| \ -device-option| \ - -host-option| \ -sdk| \ -android-sdk| \ -android-ndk| \ @@ -646,101 +472,12 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=no case "$VAR" in - prefix) - QT_INSTALL_PREFIX="$VAL" - ;; - hostprefix) - QT_HOST_PREFIX="$VAL" - ;; - hostdatadir) - QT_HOST_DATA="$VAL" - ;; - hostbindir) - QT_HOST_BINS="$VAL" - ;; - hostlibdir) - QT_HOST_LIBS="$VAL" - ;; - extprefix) - QT_EXT_PREFIX="$VAL" - ;; - docdir) - QT_INSTALL_DOCS="$VAL" - ;; - headerdir) - QT_INSTALL_HEADERS="$VAL" - ;; - plugindir) - QT_INSTALL_PLUGINS="$VAL" - ;; - importdir) - QT_INSTALL_IMPORTS="$VAL" - ;; - qmldir) - QT_INSTALL_QML="$VAL" - ;; - archdatadir) - QT_INSTALL_ARCHDATA="$VAL" - ;; - datadir) - QT_INSTALL_DATA="$VAL" - ;; - libdir) - QT_INSTALL_LIBS="$VAL" - ;; - translationdir) - QT_INSTALL_TRANSLATIONS="$VAL" - ;; - sysconfdir|settingsdir) - QT_INSTALL_SETTINGS="$VAL" - ;; - examplesdir) - QT_INSTALL_EXAMPLES="$VAL" - ;; - testsdir) - QT_INSTALL_TESTS="$VAL" - ;; - sysroot) - CFG_SYSROOT="$VAL" - ;; external-hostbindir) CFG_HOST_QT_TOOLS_PATH="$VAL" - HostVar set HOST_QT_TOOLS "$VAL" - ;; - bindir) - QT_INSTALL_BINS="$VAL" ;; - libexecdir) - QT_INSTALL_LIBEXECS="$VAL" - ;; - sdk) - if [ "$BUILD_ON_MAC" = "yes" ]; then - DeviceVar set !host_build:QMAKE_MAC_SDK "$VAL" - OPT_MAC_SDK="$VAL" - else - UNKNOWN_OPT=yes - fi - ;; platform) PLATFORM="$VAL" ;; - xplatform) - XPLATFORM="$VAL" - ;; - device) - XPLATFORM=`resolveDeviceMkspec $VAL` - [ "$XPLATFORM" = "undefined" ] && exit 101 - ;; - device-option) - DEV_VAR=`echo $VAL | cut -d '=' -f 1` - DEV_VAL=`echo $VAL | cut -d '=' -f 2-` - DeviceVar set $DEV_VAR "$DEV_VAL" - ;; - host-option) - HOST_VAR=`echo $VAL | cut -d '=' -f 1` - HOST_VAL=`echo $VAL | cut -d '=' -f 2-` - HostVar set $HOST_VAR "$HOST_VAL" - ;; optimized-qmake|optimized-tools) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_RELEASE_TOOLS="$VAL" @@ -749,19 +486,6 @@ while [ "$#" -gt 0 ]; do developer-build) CFG_DEV="yes" ;; - commercial) - COMMERCIAL_USER="yes" - ;; - opensource) - COMMERCIAL_USER="no" - ;; - confirm-license) - if [ "$VAL" = "yes" ]; then - OPT_CONFIRM_LICENSE="$VAL" - else - UNKNOWN_OPT=yes - fi - ;; h|help) if [ "$VAL" = "yes" ]; then OPT_HELP="$VAL" @@ -782,24 +506,6 @@ while [ "$#" -gt 0 ]; do # need to keep this here, to ensure qmake is built silently CFG_SILENT="$VAL" ;; - android-sdk) - CFG_DEFAULT_ANDROID_SDK_ROOT="$VAL" - ;; - android-ndk) - CFG_DEFAULT_ANDROID_NDK_ROOT="$VAL" - ;; - android-ndk-platform) - CFG_DEFAULT_ANDROID_PLATFORM="$VAL" - ;; - android-ndk-host) - CFG_DEFAULT_ANDROID_NDK_HOST="$VAL" - ;; - android-arch) - CFG_DEFAULT_ANDROID_TARGET_ARCH="$VAL" - ;; - android-toolchain-version) - CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION="$VAL" - ;; *) ;; esac @@ -973,115 +679,18 @@ if [ -z "$PLATFORM" ]; then esac fi -[ -z "$XPLATFORM" ] && XPLATFORM="$PLATFORM" - -case "$XPLATFORM" in - *win32-g++*) - XPLATFORM_MINGW=yes - ;; - *qnx-*) - ;; - *haiku-*) - ;; - *ios*) - XPLATFORM_MAC=yes - XPLATFORM_IOS=yes - ;; - *tvos*) - XPLATFORM_MAC=yes - XPLATFORM_TVOS=yes - ;; - *watchos*) - XPLATFORM_MAC=yes - XPLATFORM_WATCHOS=yes - ;; - *macx*) - XPLATFORM_MAC=yes - ;; - *integrity*) - ;; - # XPLATFORM_ANDROID should not be set for unsupported/android-g++ - *unsupported*) - ;; - *android-g++*) - XPLATFORM_ANDROID=g++ - ;; - *android-clang*) - XPLATFORM_ANDROID=clang - ;; -esac - #------------------------------------------------------------------------------- # command line and environment validation #------------------------------------------------------------------------------- -if [ "$XPLATFORM_ANDROID" != "no" ]; then - if [ -z "$CFG_DEFAULT_ANDROID_NDK_HOST" ]; then - case $PLATFORM in - linux-*) - if [ -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt/linux-x86" ]; then - CFG_DEFAULT_ANDROID_NDK_HOST=linux-x86 - elif [ -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt/linux-x86_64" ]; then - CFG_DEFAULT_ANDROID_NDK_HOST=linux-x86_64 - fi - ;; - macx-*) - CFG_DEFAULT_ANDROID_NDK_HOST=darwin-x86 - if [ -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt/darwin-x86_64" ]; then - CFG_DEFAULT_ANDROID_NDK_HOST=darwin-x86_64 - fi - ;; - win32-*) - CFG_DEFAULT_ANDROID_NDK_HOST=windows - if [ -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt/windows-x86_64" ]; then - CFG_DEFAULT_ANDROID_NDK_HOST=windows-x86_64 - fi - ;; - esac - fi - - if [ -z "$CFG_DEFAULT_ANDROID_NDK_ROOT" ]; then - echo - echo "Can not find Android NDK. Please use -android-ndk option to specify one" - exit 1 - fi - if [ -z "$CFG_DEFAULT_ANDROID_SDK_ROOT" ]; then - echo - echo "Can not find Android SDK. Please use -android-sdk option to specify one" - exit 1 - fi - if [ -z "CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION" ] || [ ! -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt" ]; then - echo - echo "Can not detect Android NDK toolchain. Please use -android-toolchain-version to specify" - exit 1 - fi - if [ -z "$CFG_DEFAULT_ANDROID_NDK_HOST" ] || [ ! -d "$CFG_DEFAULT_ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION/prebuilt/$CFG_DEFAULT_ANDROID_NDK_HOST" ]; then - echo - echo "Can not detect the android host. Please use -android-ndk-host option to specify one" - exit 1 - fi - - DeviceVar set DEFAULT_ANDROID_SDK_ROOT "$CFG_DEFAULT_ANDROID_SDK_ROOT" - DeviceVar set DEFAULT_ANDROID_NDK_ROOT "$CFG_DEFAULT_ANDROID_NDK_ROOT" - DeviceVar set DEFAULT_ANDROID_PLATFORM "$CFG_DEFAULT_ANDROID_PLATFORM" - DeviceVar set DEFAULT_ANDROID_NDK_HOST "$CFG_DEFAULT_ANDROID_NDK_HOST" - DeviceVar set DEFAULT_ANDROID_TARGET_ARCH "$CFG_DEFAULT_ANDROID_TARGET_ARCH" - DeviceVar set DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION "$CFG_DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION" -fi - if [ -d "$PLATFORM" ]; then QMAKESPEC="$PLATFORM" else QMAKESPEC="$relpath/mkspecs/${PLATFORM}" fi -if [ -d "$XPLATFORM" ]; then - XQMAKESPEC="$XPLATFORM" -else - XQMAKESPEC="$relpath/mkspecs/${XPLATFORM}" -fi if [ "$BUILD_ON_MAC" = "yes" ]; then - if [ `basename $QMAKESPEC` = "macx-xcode" ] || [ `basename $XQMAKESPEC` = "macx-xcode" ]; then + if [ `basename $QMAKESPEC` = "macx-xcode" ]; then echo >&2 echo " Platform 'macx-xcode' should not be used when building Qt/Mac." >&2 echo " Please build Qt/Mac with 'macx-clang' or 'macx-g++', then use" >&2 @@ -1103,26 +712,6 @@ if [ '!' -d "$QMAKESPEC" ]; then echo exit 2 fi -if [ '!' -d "$XQMAKESPEC" ]; then - echo - echo " The specified system/compiler is not supported:" - echo - echo " $XQMAKESPEC" - echo - echo " Please see the README file for a complete list." - echo - exit 2 -fi -if [ '!' -f "${XQMAKESPEC}/qplatformdefs.h" ]; then - echo - echo " The specified system/compiler port is not complete:" - echo - echo " $XQMAKESPEC/qplatformdefs.h" - echo - echo " Please information use the contact form at http://www.qt.io/contact-us" - echo - exit 2 -fi #------------------------------------------------------------------------------- # build tree initialization @@ -1156,283 +745,6 @@ if [ "$OPT_SHADOW" = "yes" ]; then mkdir -p "$outpath/mkspecs" fi -if [ "$XPLATFORM_ANDROID" = "no" ]; then - TEST_COMPILER=`getXQMakeConf QMAKE_CXX` - GCC_MACHINE_DUMP= - case "$TEST_COMPILER" in *g++) GCC_MACHINE_DUMP=$($TEST_COMPILER -dumpmachine);; esac - if [ -n "$GCC_MACHINE_DUMP" ]; then - DeviceVar set GCC_MACHINE_DUMP $($TEST_COMPILER -dumpmachine) - fi -fi - -#------------------------------------------------------------------------------- -# postprocess installation and deployment paths -#------------------------------------------------------------------------------- - -if [ -z "$QT_INSTALL_PREFIX" ]; then - if [ "$CFG_DEV" = "yes" ]; then - QT_INSTALL_PREFIX="$outpath" # In Development, we use sandboxed builds by default - else - QT_INSTALL_PREFIX="/usr/local/Qt-${QT_VERSION}" # the default install prefix is /usr/local/Qt-$QT_VERSION - fi -fi -QT_INSTALL_PREFIX=`makeabs "$QT_INSTALL_PREFIX"` - -if [ -z "$QT_EXT_PREFIX" ]; then - QT_EXT_PREFIX=$QT_INSTALL_PREFIX - if [ -n "$CFG_SYSROOT" ]; then - QMAKE_SYSROOTIFY=true - else - QMAKE_SYSROOTIFY=false - fi -else - QT_EXT_PREFIX=`makeabs "$QT_EXT_PREFIX"` - QMAKE_SYSROOTIFY=false -fi - -if [ -z "$QT_HOST_PREFIX" ]; then - if $QMAKE_SYSROOTIFY; then - QT_HOST_PREFIX=$CFG_SYSROOT$QT_EXT_PREFIX - else - QT_HOST_PREFIX=$QT_EXT_PREFIX - fi - HAVE_HOST_PATH=false -else - QT_HOST_PREFIX=`makeabs "$QT_HOST_PREFIX"` - HAVE_HOST_PATH=true -fi - -#------- make the paths relative to the prefixes -------- - -PREFIX_COMPLAINTS= -PREFIX_REMINDER=false -while read basevar baseoption var option; do - eval path=\$QT_${basevar}_$var - [ -z "$path" ] && continue - path=`makeabs "$path"` - eval base=\$QT_${basevar}_PREFIX - rel=${path##$base} - if [ x"$rel" = x"$path" ]; then - if [ x"$option" != x"sysconf" ]; then - PREFIX_COMPLAINTS="$PREFIX_COMPLAINTS - NOTICE: -${option}dir is not a subdirectory of ${baseoption}prefix." - eval \$HAVE_${basevar}_PATH || PREFIX_REMINDER=true - fi - eval QT_REL_${basevar}_$var=\$rel - elif [ -z "$rel" ]; then - eval QT_REL_${basevar}_$var=. - else - eval QT_REL_${basevar}_$var=\${rel#/} - fi -done <<EOF -INSTALL - DOCS doc -INSTALL - HEADERS header -INSTALL - LIBS lib -INSTALL - LIBEXECS libexec -INSTALL - BINS bin -INSTALL - PLUGINS plugin -INSTALL - IMPORTS import -INSTALL - QML qml -INSTALL - ARCHDATA archdata -INSTALL - DATA data -INSTALL - TRANSLATIONS translation -INSTALL - EXAMPLES examples -INSTALL - TESTS tests -INSTALL - SETTINGS sysconf -HOST -host BINS hostbin -HOST -host LIBS hostlib -HOST -host DATA hostdata -EOF -$PREFIX_REMINDER && PREFIX_COMPLAINTS="$PREFIX_COMPLAINTS - Maybe you forgot to specify -prefix/-hostprefix?" - -if [ -z "$QT_REL_INSTALL_HEADERS" ]; then - QT_REL_INSTALL_HEADERS=include -fi - -if [ -z "$QT_REL_INSTALL_LIBS" ]; then - QT_REL_INSTALL_LIBS=lib -fi - -if [ -z "$QT_REL_INSTALL_BINS" ]; then - QT_REL_INSTALL_BINS=bin -fi - -if [ -z "$QT_REL_INSTALL_ARCHDATA" ]; then - QT_REL_INSTALL_ARCHDATA=. -fi -if [ x"$QT_REL_INSTALL_ARCHDATA" != x. ]; then - QT_REL_INSTALL_ARCHDATA_PREFIX=$QT_REL_INSTALL_ARCHDATA/ -fi - -if [ -z "$QT_REL_INSTALL_LIBEXECS" ]; then - if [ "$XPLATFORM_MINGW" = "yes" ]; then - QT_REL_INSTALL_LIBEXECS=${QT_REL_INSTALL_ARCHDATA_PREFIX}bin - else - QT_REL_INSTALL_LIBEXECS=${QT_REL_INSTALL_ARCHDATA_PREFIX}libexec - fi -fi - -if [ -z "$QT_REL_INSTALL_PLUGINS" ]; then - QT_REL_INSTALL_PLUGINS=${QT_REL_INSTALL_ARCHDATA_PREFIX}plugins -fi - -if [ -z "$QT_REL_INSTALL_IMPORTS" ]; then - QT_REL_INSTALL_IMPORTS=${QT_REL_INSTALL_ARCHDATA_PREFIX}imports -fi - -if [ -z "$QT_REL_INSTALL_QML" ]; then - QT_REL_INSTALL_QML=${QT_REL_INSTALL_ARCHDATA_PREFIX}qml -fi - -if [ -z "$QT_REL_INSTALL_DATA" ]; then - QT_REL_INSTALL_DATA=. -fi -if [ x"$QT_REL_INSTALL_DATA" != x. ]; then - QT_REL_INSTALL_DATA_PREFIX=$QT_REL_INSTALL_DATA/ -fi - -if [ -z "$QT_REL_INSTALL_DOCS" ]; then - QT_REL_INSTALL_DOCS=${QT_REL_INSTALL_DATA_PREFIX}doc -fi - -if [ -z "$QT_REL_INSTALL_TRANSLATIONS" ]; then - QT_REL_INSTALL_TRANSLATIONS=${QT_REL_INSTALL_DATA_PREFIX}translations -fi - -if [ -z "$QT_REL_INSTALL_EXAMPLES" ]; then - QT_REL_INSTALL_EXAMPLES=examples -fi - -if [ -z "$QT_REL_INSTALL_TESTS" ]; then - QT_REL_INSTALL_TESTS=tests -fi - -if [ -z "$QT_REL_INSTALL_SETTINGS" ]; then - if [ "$XPLATFORM_MAC" = "yes" ]; then - QT_REL_INSTALL_SETTINGS=/Library/Preferences/Qt - else - QT_REL_INSTALL_SETTINGS=etc/xdg - fi -fi - -#------- host paths -------- - -if [ -z "$QT_REL_HOST_BINS" ]; then - if $HAVE_HOST_PATH; then - QT_REL_HOST_BINS=bin - else - QT_REL_HOST_BINS=$QT_REL_INSTALL_BINS - fi -fi - -if [ -z "$QT_REL_HOST_LIBS" ]; then - if $HAVE_HOST_PATH; then - QT_REL_HOST_LIBS=lib - else - QT_REL_HOST_LIBS=$QT_REL_INSTALL_LIBS - fi -fi - -if [ -z "$QT_REL_HOST_DATA" ]; then - if $HAVE_HOST_PATH; then - QT_REL_HOST_DATA=. - else - QT_REL_HOST_DATA=$QT_REL_INSTALL_ARCHDATA - fi -fi - -shortxspec=`echo $XQMAKESPEC | sed "s,^${relpath}/mkspecs/,,"` -shortspec=`echo $QMAKESPEC | sed "s,^${relpath}/mkspecs/,,"` - -QT_CONFIGURE_STR_OFF=0 - -addConfStr() -{ - QT_CONFIGURE_STR_OFFSETS="$QT_CONFIGURE_STR_OFFSETS $QT_CONFIGURE_STR_OFF," - QT_CONFIGURE_STRS="$QT_CONFIGURE_STRS \"$1\\0\" -" - count=`echo "$1" | wc -c` - QT_CONFIGURE_STR_OFF=`expr $QT_CONFIGURE_STR_OFF + $count` -} - -QT_CONFIGURE_STR_OFFSETS= -QT_CONFIGURE_STRS= -addConfStr "$QT_REL_INSTALL_DOCS" -addConfStr "$QT_REL_INSTALL_HEADERS" -addConfStr "$QT_REL_INSTALL_LIBS" -addConfStr "$QT_REL_INSTALL_LIBEXECS" -addConfStr "$QT_REL_INSTALL_BINS" -addConfStr "$QT_REL_INSTALL_PLUGINS" -addConfStr "$QT_REL_INSTALL_IMPORTS" -addConfStr "$QT_REL_INSTALL_QML" -addConfStr "$QT_REL_INSTALL_ARCHDATA" -addConfStr "$QT_REL_INSTALL_DATA" -addConfStr "$QT_REL_INSTALL_TRANSLATIONS" -addConfStr "$QT_REL_INSTALL_EXAMPLES" -addConfStr "$QT_REL_INSTALL_TESTS" -QT_CONFIGURE_STR_OFFSETS_ALL=$QT_CONFIGURE_STR_OFFSETS -QT_CONFIGURE_STRS_ALL=$QT_CONFIGURE_STRS - -QT_CONFIGURE_STR_OFFSETS= -QT_CONFIGURE_STRS= -addConfStr "$CFG_SYSROOT" -addConfStr "$QT_REL_HOST_BINS" -addConfStr "$QT_REL_HOST_LIBS" -addConfStr "$QT_REL_HOST_DATA" -addConfStr "$shortxspec" -addConfStr "$shortspec" - -#------------------------------------------------------------------------------- -# generate qconfig.cpp -#------------------------------------------------------------------------------- -[ -d "$outpath/src/corelib/global" ] || mkdir -p "$outpath/src/corelib/global" - -cat > "$outpath/src/corelib/global/qconfig.cpp.new" <<EOF -/* Installation date */ -static const char qt_configure_installation [12+11] = "qt_instdate=2012-12-20"; - -/* Installation Info */ -static const char qt_configure_prefix_path_str [256 + 12] = "qt_prfxpath=$QT_INSTALL_PREFIX"; -#ifdef QT_BUILD_QMAKE -static const char qt_configure_ext_prefix_path_str [256 + 12] = "qt_epfxpath=$QT_EXT_PREFIX"; -static const char qt_configure_host_prefix_path_str [256 + 12] = "qt_hpfxpath=$QT_HOST_PREFIX"; -#endif - -static const short qt_configure_str_offsets[] = { - $QT_CONFIGURE_STR_OFFSETS_ALL -#ifdef QT_BUILD_QMAKE - $QT_CONFIGURE_STR_OFFSETS -#endif -}; -static const char qt_configure_strs[] = -$QT_CONFIGURE_STRS_ALL#ifdef QT_BUILD_QMAKE -$QT_CONFIGURE_STRS#endif -; - -#define QT_CONFIGURE_SETTINGS_PATH "$QT_REL_INSTALL_SETTINGS" - -#ifdef QT_BUILD_QMAKE -# define QT_CONFIGURE_SYSROOTIFY_PREFIX $QMAKE_SYSROOTIFY -#endif - -#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12 -#ifdef QT_BUILD_QMAKE -# define QT_CONFIGURE_EXT_PREFIX_PATH qt_configure_ext_prefix_path_str + 12 -# define QT_CONFIGURE_HOST_PREFIX_PATH qt_configure_host_prefix_path_str + 12 -#endif -EOF - -# avoid unecessary rebuilds by copying only if qconfig.cpp has changed -if cmp -s "$outpath/src/corelib/global/qconfig.cpp" "$outpath/src/corelib/global/qconfig.cpp.new"; then - rm -f "$outpath/src/corelib/global/qconfig.cpp.new" -else - [ -f "$outpath/src/corelib/global/qconfig.cpp" ] && chmod +w "$outpath/src/corelib/global/qconfig.cpp" - mv "$outpath/src/corelib/global/qconfig.cpp.new" "$outpath/src/corelib/global/qconfig.cpp" - chmod -w "$outpath/src/corelib/global/qconfig.cpp" -fi - - # ----------------------------------------------------------------------------- # build qmake # ----------------------------------------------------------------------------- @@ -1566,51 +878,16 @@ setBootstrapVariable() # create a qt.conf for the Qt build tree itself #------------------------------------------------------------------------------- -printInstallPaths() -{ - cat <<EOF -Documentation=$QT_REL_INSTALL_DOCS -Headers=$QT_REL_INSTALL_HEADERS -Libraries=$QT_REL_INSTALL_LIBS -LibraryExecutables=$QT_REL_INSTALL_LIBEXECS -Binaries=$QT_REL_INSTALL_BINS -Plugins=$QT_REL_INSTALL_PLUGINS -Imports=$QT_REL_INSTALL_IMPORTS -Qml2Imports=$QT_REL_INSTALL_QML -ArchData=$QT_REL_INSTALL_ARCHDATA -Data=$QT_REL_INSTALL_DATA -Translations=$QT_REL_INSTALL_TRANSLATIONS -Examples=$QT_REL_INSTALL_EXAMPLES -Tests=$QT_REL_INSTALL_TESTS -EOF -} - +# Note that this file is just sufficient to boot configure, by which it is +# replaced in-place with a version which is suitable for building all of Qt. QTCONFFILE="$outpath/bin/qt.conf" cat > "$QTCONFFILE" <<EOF [EffectivePaths] Prefix=.. -EOF -if [ -n "$CFG_HOST_QT_TOOLS_PATH" ]; then - cat >> "$QTCONFFILE" <<EOF -[DevicePaths] -Prefix=$QT_INSTALL_PREFIX -`printInstallPaths` [Paths] -Prefix=$QT_EXT_PREFIX -`printInstallPaths` -HostPrefix=$QT_HOST_PREFIX -HostBinaries=$QT_REL_HOST_BINS -HostLibraries=$QT_REL_HOST_LIBS -HostData=$QT_REL_HOST_DATA -TargetSpec=$XPLATFORM +TargetSpec=dummy HostSpec=$PLATFORM EOF - if [ -n "$CFG_SYSROOT" ]; then - cat >> "$QTCONFFILE" <<EOF -Sysroot=$CFG_SYSROOT -EOF - fi -fi if [ x"$relpath" != x"$outpath" ]; then cat >> "$QTCONFFILE" <<EOF [EffectiveSourcePaths] @@ -1622,28 +899,6 @@ fi CFG_QMAKE_PATH="$CFG_HOST_QT_TOOLS_PATH/qmake" #------------------------------------------------------------------------------- -# write out device config before we run the test. -#------------------------------------------------------------------------------- -DEVICE_VARS_OUTFILE="$outpath/mkspecs/qdevice.pri" -if cmp -s "$DEVICE_VARS_FILE" "$DEVICE_VARS_OUTFILE"; then - rm -f "$DEVICE_VARS_FILE" -else - mv -f $DEVICE_VARS_FILE "$DEVICE_VARS_OUTFILE" - DEVICE_VARS_FILE="$DEVICE_VARS_OUTFILE" -fi - -#------------------------------------------------------------------------------- -# write out host config. -#------------------------------------------------------------------------------- -HOST_VARS_OUTFILE="$outpath/mkspecs/qhost.pri" -if cmp -s "$HOST_VARS_FILE" "$HOST_VARS_OUTFILE"; then - rm -f "$HOST_VARS_FILE" -else - mv -f $HOST_VARS_FILE "$HOST_VARS_OUTFILE" - HOST_VARS_FILE="$HOST_VARS_OUTFILE" -fi - -#------------------------------------------------------------------------------- # run configure tests #------------------------------------------------------------------------------- @@ -1669,33 +924,6 @@ fi "$CFG_QMAKE_PATH" -qtconf "$QTCONFFILE" "$relpathMangled" -- "$@" || exit #------------------------------------------------------------------------------- -# finally save the executed command to another script -#------------------------------------------------------------------------------- -if [ $CFG_REDO = no ]; then - if [ "$COMMERCIAL_USER" = "ask" ]; then - if grep '^QT_EDITION = OpenSource$' "$outpath/mkspecs/qconfig.pri" >/dev/null 2>&1; then - OPT_CMDLINE="$OPT_CMDLINE --opensource" - else - OPT_CMDLINE="$OPT_CMDLINE --commercial" - fi - fi - if [ "$OPT_CONFIRM_LICENSE" = "no" ]; then - OPT_CMDLINE="$OPT_CMDLINE --confirm-license" - fi - - # skip first line, as it's always empty due to unconditional field separation - echo "$OPT_CMDLINE" | tail -n +2 > config.opt - - [ -f "config.status" ] && rm -f config.status - echo "#!/bin/sh" > config.status - echo "$relpathMangled/$relconf -redo \"\$@\"" >> config.status - chmod +x config.status -fi - -#------------------------------------------------------------------------------- # final notes for the user #------------------------------------------------------------------------------- @@ -1707,12 +935,7 @@ else echo fi -if [ -n "$PREFIX_COMPLAINTS" ]; then - echo - echo "$PREFIX_COMPLAINTS" - echo -fi - +QT_INSTALL_PREFIX=`sed -ne 's/^Prefix=//p' < "$outpath/qmake/builtin-qt.conf"` MAKE=`basename "$MAKE"` echo echo Qt is now configured for building. Just run \'$MAKE\'. diff --git a/configure.json b/configure.json index c13f44ed00..51eab72df2 100644 --- a/configure.json +++ b/configure.json @@ -1,5 +1,7 @@ { "files": { + "builtinQtConf": "qmake/builtin-qt.conf", + "qconfigSource": "src/corelib/global/qconfig.cpp", "publicHeader": "src/corelib/global/qconfig.h", "privateHeader": "src/corelib/global/qconfig_p.h", "publicPro": "mkspecs/qconfig.pri", @@ -43,7 +45,7 @@ "libexecdir": "string", "plugindir": "string", "qmldir": "string", - "settingsdir": "string", + "settingsdir": { "type": "string", "name": "sysconfdir" }, "sysconfdir": "string", "testsdir": "string", "translationdir": "string", @@ -65,7 +67,6 @@ "commercial": "void", "compile-examples": { "type": "boolean", "name": "compile_examples" }, "confirm-license": "void", - "continue": "void", "dbus": { "type": "optionalString", "values": [ "no", "yes", "linked", "runtime" ] }, "dbus-linked": { "type": "void", "name": "dbus", "value": "linked" }, "dbus-runtime": { "type": "void", "name": "dbus", "value": "runtime" }, @@ -73,7 +74,7 @@ "debug-and-release": { "type": "boolean", "name": "debug_and_release" }, "developer-build": "void", "device": "string", - "device-option": "string", + "device-option": "addString", "force-asserts": { "type": "boolean", "name": "force_asserts" }, "force-debug-info": { "type": "boolean", "name": "force_debug_info" }, "force-pkg-config": { "type": "void", "name": "pkg-config" }, @@ -83,7 +84,6 @@ "gnumake": { "type": "boolean", "name": "GNUmake" }, "gui": "boolean", "headersclean": "boolean", - "host-option": "string", "incredibuild-xge": { "type": "boolean", "name": "incredibuild_xge" }, "libudev": "boolean", "ltcg": "boolean", @@ -190,9 +190,9 @@ "testTypeDependencies": { "linkerSupportsFlag": [ "use_gold_linker" ], - "verifySpec": [ "shared", "use_gold_linker", "compiler-flags", "gcc-sysroot", "qmakeargs" ], + "verifySpec": [ "shared", "use_gold_linker", "compiler-flags", "gcc-sysroot", "qmakeargs", "commit" ], "compile": [ "verifyspec" ], - "detectPkgConfig": [ "cross_compile" ], + "detectPkgConfig": [ "cross_compile", "machineTuple" ], "library": [ "pkg-config" ], "getPkgConfigVariable": [ "pkg-config" ], "neon": [ "architecture" ] @@ -203,6 +203,10 @@ }, "tests": { + "machineTuple": { + "label": "machine tuple", + "type": "machineTuple" + }, "verifyspec": { "label": "valid makespec", "type": "verifySpec", @@ -419,6 +423,16 @@ }, "features": { + "prepare": { + "output": [ "prepareSpec", "prepareOptions", "preparePaths" ] + }, + "machineTuple": { + "condition": "!config.linux || config.android || tests.machineTuple", + "output": [ "machineTuple" ] + }, + "commit": { + "output": [ "commitOptions" ] + }, "android-style-assets": { "label": "Android Style Assets", "condition": "config.android", @@ -980,6 +994,15 @@ "earlyReport": [ { "type": "fatal", + "condition": "input.xplatform != '' && input.device != ''", + "message": "Cannot specify both -xplatform and -device." + }, + { + "condition": "!features.prepare", + "comment": "This is not an actual report - instead, it activates the early setup." + }, + { + "type": "fatal", "condition": "!call.licenseCheck", "message": "You are not licensed to use this software." }, diff --git a/configure.pri b/configure.pri index 526b09e965..0dfe6cc719 100644 --- a/configure.pri +++ b/configure.pri @@ -91,11 +91,14 @@ defineReplace(qtConfFunc_licenseCheck) { val = $$lower($$prompt("Which edition of Qt do you want to use? ", false)) equals(val, c) { commercial = yes + QMAKE_SAVED_ARGS += -commercial } else: equals(val, o) { commercial = no + QMAKE_SAVED_ARGS += -opensource } else { next() } + export(QMAKE_SAVED_ARGS) break() } } else { @@ -206,6 +209,8 @@ defineReplace(qtConfFunc_licenseCheck) { val = $$lower($$prompt("Do you accept the terms of $$affix license? ", false)) equals(val, y)|equals(val, yes) { logn() + QMAKE_SAVED_ARGS += -confirm-license + export(QMAKE_SAVED_ARGS) return(true) } else: equals(val, n)|equals(val, no) { return(false) @@ -228,6 +233,14 @@ defineReplace(qtConfFunc_licenseCheck) { # custom tests +# this is meant for linux device specs only +defineTest(qtConfTest_machineTuple) { + qtRunLoggedCommand("$$QMAKE_CXX -dumpmachine", $${1}.tuple)|return(false) + $${1}.cache += tuple + export($${1}.cache) + return(true) +} + defineTest(qtConfTest_architecture) { !qtConfTest_compile($${1}): \ error("Could not determine $$eval($${1}.label). See config.log for details.") @@ -323,11 +336,9 @@ defineTest(qtConfTest_detectPkgConfig) { } pkgConfigLibdir = $$sysroot/usr/lib/pkgconfig:$$sysroot/usr/share/pkgconfig - gcc { - qtRunLoggedCommand("$$QMAKE_CXX -dumpmachine", gccMachineDump): \ - !isEmpty(gccMachineDump): \ - pkgConfigLibdir = "$$pkgConfigLibdir:$$sysroot/usr/lib/$$gccMachineDump/pkgconfig" - } + machineTuple = $$eval($${currentConfig}.tests.machineTuple.tuple) + !isEmpty(machineTuple): \ + pkgConfigLibdir = "$$pkgConfigLibdir:$$sysroot/usr/lib/$$machineTuple/pkgconfig" qtConfAddNote("PKG_CONFIG_LIBDIR automatically set to $$pkgConfigLibdir") } @@ -432,6 +443,436 @@ defineTest(qtConfTest_checkCompiler) { # custom outputs +# this reloads the qmakespec as completely as reasonably possible. +defineTest(reloadSpec) { + bypassNesting() { + for (f, QMAKE_INTERNAL_INCLUDED_FILES) { + contains(f, .*/mkspecs/.*):\ + !contains(f, .*/(qt_build_config|qt_parts|qt_configure|configure_base)\\.prf): \ + discard_from($$f) + } + # nobody's going to try to re-load the features above, + # so don't bother with being selective. + QMAKE_INTERNAL_INCLUDED_FEATURES = + + _SAVED_CONFIG = $$CONFIG + load(spec_pre) + load(device_config) # avoid that the spec loads it later. + # discard possible settings from an earlier configure run. + discard_from($$[QT_HOST_DATA/get]/mkspecs/qdevice.pri) + # qdevice.pri gets written too late (and we can't write it early + # enough, as it's populated in stages, with later ones depending + # on earlier ones). so inject its variables manually. + for (l, $${currentConfig}.output.devicePro): \ + eval($$l) + include($$QMAKESPEC/qmake.conf) + load(spec_post) + load(default_pre) + CONFIG += $$_SAVED_CONFIG + + # ensure pristine environment for configuration. again. + discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri) + discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri) + } +} + +defineTest(qtConfOutput_prepareSpec) { + device = $$eval(config.input.device) + !isEmpty(device) { + devices = $$files($$[QT_HOST_DATA/src]/mkspecs/devices/*$$device*) + isEmpty(devices): \ + qtConfFatalError("No device matching '$$device'.") + !count(devices, 1) { + err = "Multiple matches for device '$$device'. Candidates are:" + for (d, devices): \ + err += " $$basename(d)" + qtConfFatalError($$err) + } + XSPEC = $$relative_path($$devices, $$[QT_HOST_DATA/src]/mkspecs) + } + xspec = $$eval(config.input.xplatform) + !isEmpty(xspec) { + !exists($$[QT_HOST_DATA/src]/mkspecs/$$xspec/qmake.conf): \ + qtConfFatalError("Invalid target platform '$$xspec'.") + XSPEC = $$xspec + } + isEmpty(XSPEC): \ + XSPEC = $$[QMAKE_SPEC] + export(XSPEC) + QMAKESPEC = $$[QT_HOST_DATA/src]/mkspecs/$$XSPEC + export(QMAKESPEC) + + # deviceOptions() below contains conditionals coming form the spec, + # so this cannot be delayed for a batch reload. + reloadSpec() +} + +defineTest(qtConfOutput_prepareOptions) { + $${currentConfig}.output.devicePro += \ + $$replace(config.input.device-option, "^([^=]+) *= *(.*)$", "\\1 = \\2") + darwin:!isEmpty(config.input.sdk) { + $${currentConfig}.output.devicePro += \ + "QMAKE_MAC_SDK = $$val_escape(config.input.sdk)" + } + android { + sdk_root = $$eval(config.input.android-sdk) + isEmpty(sdk_root): \ + sdk_root = $$getenv(ANDROID_SDK_ROOT) + isEmpty(sdk_root) { + for(ever) { + equals(QMAKE_HOST.os, Linux): \ + sdk_root = $$(HOME)/Android/Sdk + else: equals(QMAKE_HOST.os, Darwin): \ + sdk_root = $$(HOME)/Library/Android/sdk + else: \ + break() + !exists($$sdk_root): \ + sdk_root = + break() + } + } + isEmpty(sdk_root): \ + qtConfFatalError("Cannot find Android SDK." \ + "Please use -android-sdk option to specify one.") + + ndk_root = $$eval(config.input.android-ndk) + isEmpty(ndk_root): \ + ndk_root = $$getenv(ANDROID_NDK_ROOT) + isEmpty(ndk_root) { + for(ever) { + exists($$sdk_root/ndk-bundle) { + ndk_root = $$sdk_root/ndk-bundle + break() + } + equals(QMAKE_HOST.os, Linux): \ + ndk_root = $$(HOME)/Android/Sdk/ndk-bundle + else: equals(QMAKE_HOST.os, Darwin): \ + ndk_root = $$(HOME)/Library/Android/sdk/ndk-bundle + else: \ + break() + !exists($$ndk_root): \ + ndk_root = + break() + } + } + isEmpty(ndk_root): \ + qtConfFatalError("Cannot find Android NDK." \ + "Please use -android-ndk option to specify one.") + + ndk_tc_ver = $$eval(config.input.android-toolchain-version) + isEmpty(ndk_tc_ver): \ + ndk_tc_ver = 4.9 + !exists($$ndk_root/toolchains/arm-linux-androideabi-$$ndk_tc_ver/prebuilt/*): \ + qtConfFatalError("Cannot detect Android NDK toolchain." \ + "Please use -android-toolchain-version to specify it.") + + ndk_tc_pfx = $$ndk_root/toolchains/arm-linux-androideabi-$$ndk_tc_ver/prebuilt + ndk_host = $$eval(config.input.android-ndk-host) + isEmpty(ndk_host): \ + ndk_host = $$getenv(ANDROID_NDK_HOST) + isEmpty(ndk_host) { + equals(QMAKE_HOST.os, Linux) { + ndk_host_64 = linux-x86_64 + ndk_host_32 = linux-x86 + } else: equals(QMAKE_HOST.os, Darwin) { + ndk_host_64 = darwin-x86_64 + ndk_host_32 = darwin-x86 + } else: equals(QMAKE_HOST.os, Windows) { + ndk_host_64 = windows-x86_64 + ndk_host_32 = windows + } else { + qtConfFatalError("Host operating system not supported by Android.") + } + !exists($$ndk_tc_pfx/$$ndk_host_64/*): ndk_host_64 = + !exists($$ndk_tc_pfx/$$ndk_host_32/*): ndk_host_32 = + equals(QMAKE_HOST.arch, x86_64):!isEmpty(ndk_host_64) { + ndk_host = $$ndk_host_64 + } else: equals(QMAKE_HOST.arch, x86):!isEmpty(ndk_host_32) { + ndk_host = $$ndk_host_32 + } else { + !isEmpty(ndk_host_64): \ + ndk_host = $$ndk_host_64 + else: !isEmpty(ndk_host_32): \ + ndk_host = $$ndk_host_32 + else: \ + qtConfFatalError("Cannot detect the Android host." \ + "Please use -android-ndk-host option to specify one.") + qtConfAddNotice("Available Android host does not match host architecture.") + } + } else { + !exists($$ndk_tc_pfx/$$ndk_host/*): \ + qtConfFatalError("Specified Android NDK host is invalid.") + } + + target_arch = $$eval(config.input.android-arch) + isEmpty(target_arch): \ + target_arch = armeabi-v7a + + platform = $$eval(config.input.android-ndk-platform) + isEmpty(platform): \ + platform = android-16 ### the windows configure disagrees ... + + $${currentConfig}.output.devicePro += \ + "DEFAULT_ANDROID_SDK_ROOT = $$val_escape(sdk_root)" \ + "DEFAULT_ANDROID_NDK_ROOT = $$val_escape(ndk_root)" \ + "DEFAULT_ANDROID_PLATFORM = $$platform" \ + "DEFAULT_ANDROID_NDK_HOST = $$ndk_host" \ + "DEFAULT_ANDROID_TARGET_ARCH = $$target_arch" \ + "DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION = $$ndk_tc_ver" + } + + export($${currentConfig}.output.devicePro) + + # reload the spec to make the settings actually take effect. + !isEmpty($${currentConfig}.output.devicePro): \ + reloadSpec() +} + +defineTest(qtConfOutput_machineTuple) { + $${currentConfig}.output.devicePro += \ + "GCC_MACHINE_DUMP = $$eval($${currentConfig}.tests.machineTuple.tuple)" + export($${currentConfig}.output.devicePro) + + # for completeness, one could reload the spec here, + # but no downstream users actually need that. +} + +defineTest(qtConfOutput_commitOptions) { + # qdevice.pri needs to be written early, because the compile tests require it. + write_file($$QT_BUILD_TREE/mkspecs/qdevice.pri, $${currentConfig}.output.devicePro)|error() +} + +# type (empty or 'host'), option name, default value +defineTest(processQtPath) { + out_var = config.rel_input.$${2} + path = $$eval(config.input.$${2}) + isEmpty(path) { + $$out_var = $$3 + } else { + path = $$absolute_path($$path, $$OUT_PWD) + rel = $$relative_path($$path, $$eval(config.input.$${1}prefix)) + isEmpty(rel) { + $$out_var = . + } else: contains(rel, \.\..*) { + !equals(2, sysconfdir) { + PREFIX_COMPLAINTS += "-$$2 is not a subdirectory of -$${1}prefix." + export(PREFIX_COMPLAINTS) + !$$eval(have_$${1}prefix) { + PREFIX_REMINDER = true + export(PREFIX_REMINDER) + } + } + $$out_var = $$path + } else { + $$out_var = $$rel + } + } + export($$out_var) +} + +defineTest(addConfStr) { + QT_CONFIGURE_STR_OFFSETS += " $$QT_CONFIGURE_STR_OFF," + QT_CONFIGURE_STRS += " \"$$1\\0\"" + QT_CONFIGURE_STR_OFF = $$num_add($$QT_CONFIGURE_STR_OFF, $$str_size($$1), 1) + export(QT_CONFIGURE_STR_OFFSETS) + export(QT_CONFIGURE_STRS) + export(QT_CONFIGURE_STR_OFF) +} + +defineReplace(printInstallPath) { + val = $$eval(config.rel_input.$$2) + equals(val, $$3): return() + return("$$1=$$val") +} + +defineReplace(printInstallPaths) { + ret = \ + $$printInstallPath(Documentation, docdir, doc) \ + $$printInstallPath(Headers, headerdir, include) \ + $$printInstallPath(Libraries, libdir, lib) \ + $$printInstallPath(LibraryExecutables, libexecdir, $$DEFAULT_LIBEXEC) \ + $$printInstallPath(Binaries, bindir, bin) \ + $$printInstallPath(Plugins, plugindir, plugins) \ + $$printInstallPath(Imports, importdir, imports) \ + $$printInstallPath(Qml2Imports, qmldir, qml) \ + $$printInstallPath(ArchData, archdatadir, .) \ + $$printInstallPath(Data, datadir, .) \ + $$printInstallPath(Translations, translationdir, translations) \ + $$printInstallPath(Examples, examplesdir, examples) \ + $$printInstallPath(Tests, testsdir, tests) + return($$ret) +} + +defineReplace(printHostPaths) { + ret = \ + "HostPrefix=$$config.input.hostprefix" \ + $$printInstallPath(HostBinaries, hostbindir, bin) \ + $$printInstallPath(HostLibraries, hostlibdir, lib) \ + $$printInstallPath(HostData, hostdatadir, .) \ + "Sysroot=$$config.input.sysroot" \ + "TargetSpec=$$XSPEC" \ + "HostSpec=$$[QMAKE_SPEC]" + return($$ret) +} + +defineTest(qtConfOutput_preparePaths) { + isEmpty(config.input.prefix) { + $$qtConfEvaluate("features.developer-build"): \ + config.input.prefix = $$QT_BUILD_TREE # In Development, we use sandboxed builds by default + else: \ + config.input.prefix = /usr/local/Qt-$$[QT_VERSION] + have_prefix = false + } else { + config.input.prefix = $$absolute_path($$config.input.prefix, $$OUT_PWD) + have_prefix = true + } + + isEmpty(config.input.extprefix) { + config.input.extprefix = $$config.input.prefix + !isEmpty(config.input.sysroot): \ + qmake_sysrootify = true + else: \ + qmake_sysrootify = false + } else { + config.input.extprefix = $$absolute_path($$config.input.extprefix, $$OUT_PWD) + qmake_sysrootify = false + } + + isEmpty(config.input.hostprefix) { + $$qmake_sysrootify: \ + config.input.hostprefix = $$config.input.sysroot$$config.input.extprefix + else: \ + config.input.hostprefix = $$config.input.extprefix + have_hostprefix = false + } else { + isEqual(config.input.hostprefix, yes): \ + config.input.hostprefix = $$QT_BUILD_TREE + else: \ + config.input.hostprefix = $$absolute_path($$config.input.hostprefix, $$OUT_PWD) + have_hostprefix = true + } + + PREFIX_COMPLAINTS = + PREFIX_REMINDER = false + win32: \ + DEFAULT_LIBEXEC = bin + else: \ + DEFAULT_LIBEXEC = libexec + darwin: \ + DEFAULT_SYSCONFDIR = /Library/Preferences/Qt + else: \ + DEFAULT_SYSCONFDIR = etc/xdg + + processQtPath("", headerdir, include) + processQtPath("", libdir, lib) + processQtPath("", bindir, bin) + processQtPath("", datadir, .) + !equals(config.rel_input.datadir, .): \ + data_pfx = $$config.rel_input.datadir/ + processQtPath("", docdir, $${data_pfx}doc) + processQtPath("", translationdir, $${data_pfx}translations) + processQtPath("", examplesdir, $${data_pfx}examples) + processQtPath("", testsdir, tests) + processQtPath("", archdatadir, .) + !equals(config.rel_input.archdatadir, .): \ + archdata_pfx = $$config.rel_input.archdatadir/ + processQtPath("", libexecdir, $${archdata_pfx}$$DEFAULT_LIBEXEC) + processQtPath("", plugindir, $${archdata_pfx}plugins) + processQtPath("", importdir, $${archdata_pfx}imports) + processQtPath("", qmldir, $${archdata_pfx}qml) + processQtPath("", sysconfdir, $$DEFAULT_SYSCONFDIR) + $$have_hostprefix { + processQtPath(host, hostbindir, bin) + processQtPath(host, hostlibdir, lib) + processQtPath(host, hostdatadir, .) + } else { + processQtPath(host, hostbindir, $$config.rel_input.bindir) + processQtPath(host, hostlibdir, $$config.rel_input.libdir) + processQtPath(host, hostdatadir, $$config.rel_input.archdatadir) + } + + !isEmpty(PREFIX_COMPLAINTS) { + PREFIX_COMPLAINTS = "$$join(PREFIX_COMPLAINTS, "$$escape_expand(\\n)Note: ")" + $$PREFIX_REMINDER: \ + PREFIX_COMPLAINTS += "Maybe you forgot to specify -prefix/-hostprefix?" + qtConfAddNote($$PREFIX_COMPLAINTS) + } + + # populate qconfig.cpp (for qtcore) + + QT_CONFIGURE_STR_OFF = 0 + QT_CONFIGURE_STR_OFFSETS = + QT_CONFIGURE_STRS = + + addConfStr($$config.rel_input.docdir) + addConfStr($$config.rel_input.headerdir) + addConfStr($$config.rel_input.libdir) + addConfStr($$config.rel_input.libexecdir) + addConfStr($$config.rel_input.bindir) + addConfStr($$config.rel_input.plugindir) + addConfStr($$config.rel_input.importdir) + addConfStr($$config.rel_input.qmldir) + addConfStr($$config.rel_input.archdatadir) + addConfStr($$config.rel_input.datadir) + addConfStr($$config.rel_input.translationdir) + addConfStr($$config.rel_input.examplesdir) + addConfStr($$config.rel_input.testsdir) + + $${currentConfig}.output.qconfigSource = \ + "/* Installation date */" \ + "static const char qt_configure_installation [12+11] = \"qt_instdate=2012-12-20\";" \ + "" \ + "/* Installation Info */" \ + "static const char qt_configure_prefix_path_str [12+256] = \"qt_prfxpath=$$config.input.prefix\";" \ + "" \ + "static const short qt_configure_str_offsets[] = {" \ + $$QT_CONFIGURE_STR_OFFSETS \ + "};" \ + "static const char qt_configure_strs[] =" \ + $$QT_CONFIGURE_STRS \ + ";" \ + "" \ + "$${LITERAL_HASH}define QT_CONFIGURE_SETTINGS_PATH \"$$config.rel_input.sysconfdir\"" \ + "" \ + "$${LITERAL_HASH}define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12" + export($${currentConfig}.output.qconfigSource) + + # populate qmake/builtin-qt.conf + + $${currentConfig}.output.builtinQtConf = \ + " " \ + "===========================================================" \ + "==================== qt.conf beginning ====================" \ + "===========================================================" \ + "[Paths]" \ + "ExtPrefix=$$config.input.extprefix" \ + "Prefix=$$config.input.prefix" \ + $$printInstallPaths() \ + "Settings=$$config.rel_input.sysconfdir" \ + $$printHostPaths() + export($${currentConfig}.output.builtinQtConf) + + # create bin/qt.conf. this doesn't use the regular file output + # mechanism, as the file is relied upon by configure tests. + + cont = \ + "[EffectivePaths]" \ + "Prefix=.." \ + "[DevicePaths]" \ + "Prefix=$$config.input.prefix" \ + $$printInstallPaths() \ + "[Paths]" \ + "Prefix=$$config.input.extprefix" \ + $$printInstallPaths() \ + $$printHostPaths() + !equals(QT_SOURCE_TREE, $$QT_BUILD_TREE): \ + cont += \ + "[EffectiveSourcePaths]" \ + "Prefix=$$QT_SOURCE_TREE" + write_file($$QT_BUILD_TREE/bin/qt.conf, cont)|error() + reload_properties() +} + defineTest(qtConfOutput_shared) { !$${2}: return() @@ -643,6 +1084,15 @@ defineReplace(qtConfOutputPostProcess_publicPro) { return($$output) } +defineReplace(qtConfOutputPostProcess_privatePro) { + output = $$1 + + !isEmpty(config.input.external-hostbindir): \ + output += "HOST_QT_TOOLS = $$val_escape(config.input.external-hostbindir)" + + return($$output) +} + defineReplace(qtConfOutputPostProcess_publicHeader) { qt_version = $$[QT_VERSION] output = \ @@ -722,3 +1172,22 @@ discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri) QMAKE_POST_CONFIGURE += \ "include(\$\$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)" \ "include(\$\$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)" + +defineTest(createConfigStatus) { + $$QMAKE_REDO_CONFIG: return() + cfg = $$relative_path($$_PRO_FILE_PWD_/configure, $$OUT_PWD) + ext = + equals(QMAKE_HOST.os, Windows) { + ext = .bat + cont = \ + "$$system_quote($$system_path($$cfg)$$ext) -redo %*" + } else { + cont = \ + "$${LITERAL_HASH}!/bin/sh" \ + "exec $$system_quote($$cfg) -redo \"$@\"" + } + write_file($$OUT_PWD/config.status$$ext, cont, exe)|error() +} + +QMAKE_POST_CONFIGURE += \ + "createConfigStatus()" diff --git a/doc/global/externalsites/qtcreator.qdoc b/doc/global/externalsites/qtcreator.qdoc index f73b17c92f..0e66610d84 100644 --- a/doc/global/externalsites/qtcreator.qdoc +++ b/doc/global/externalsites/qtcreator.qdoc @@ -82,6 +82,34 @@ \title Qt Creator: Using Version Control Systems */ /*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-bazaar.html + \title Qt Creator: Using Bazaar +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-clearcase.html + \title Qt Creator: Using ClearCase +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-cvs.html + \title Qt Creator: Using CVS +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-git.html + \title Qt Creator: Using Git +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-mercurial.html + \title Qt Creator: Using Mercurial +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-perforce.html + \title Qt Creator: Using Perforce +*/ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-vcs-subversion.html + \title Qt Creator: Using Subversion +*/ +/*! \externalpage http://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html \title Qt Creator: Keyboard Shortcuts */ diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index 7ebe86a431..865a457581 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -33,7 +33,6 @@ manifestmeta.filters = highlighted android thumbnail ios manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \ "QtQuick/Qt Quick Demo - Photo Surface" \ "QtQuick/Qt Quick Demo - Tweet Search" \ - "QtQuick/Qt Quick Demo - Maroon*" \ "QtQuick/Qt Quick Demo - Calqlatr" \ "QtQuick/Qt Quick Demo - StocQt" \ "QtQuick/Qt Quick Demo - Clocks" \ @@ -45,14 +44,12 @@ manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \ "QtQuickDialogs/Qt Quick System Dialog Examples" \ "QtWinExtras/Quick Player" \ "QtMultimedia/QML Video Shader Effects Example" \ - "QtCanvas3D/Planets Example" \ "QtCanvas3D/Interactive Mobile Phone Example" \ "QtLocation/Map Viewer (QML)" manifestmeta.highlighted.attributes = isHighlighted:true -manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ - "QtQuick/Qt Quick Demo - Calqlatr" \ +manifestmeta.android.names = "QtQuick/Qt Quick Demo - Calqlatr" \ "QtWidgets/Application Chooser Example" \ "QtWidgets/Stickman Example" \ "QtWidgets/Move Blocks Example" \ diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf index fe8b7fb87e..28f3dade07 100644 --- a/doc/global/qt-cpp-defines.qdocconf +++ b/doc/global/qt-cpp-defines.qdocconf @@ -14,12 +14,14 @@ defines += Q_QDOC \ Q_NO_USING_KEYWORD \ __cplusplus \ Q_COMPILER_INITIALIZER_LISTS \ + Q_COMPILER_UNICODE_STRINGS \ Q_COMPILER_UNIFORM_INIT \ Q_COMPILER_RVALUE_REFS Cpp.ignoretokens += \ ENGINIOCLIENT_EXPORT \ PHONON_EXPORT \ + Q_ALWAYS_INLINE \ Q_AUTOTEST_EXPORT \ Q_BLUETOOTH_EXPORT \ Q_COMPAT_EXPORT \ @@ -121,6 +123,7 @@ Cpp.ignoretokens += \ QT_END_NAMESPACE \ QT_FASTCALL \ QT_MUTEX_LOCK_NOEXCEPT \ + QT_WARNING_DISABLE_DEPRECATED \ QT_WARNING_PUSH \ QT_WARNING_POP \ QT_WIDGET_PLUGIN_EXPORT \ @@ -148,8 +151,11 @@ Cpp.ignoredirectives += \ Q_DUMMY_COMPARISON_OPERATOR \ Q_ENUM \ Q_ENUMS \ + Q_ENUM_NS \ Q_FLAG \ Q_FLAGS \ + Q_FLAG_NS \ + QT_HAS_INCLUDE \ Q_INTERFACES \ Q_PRIVATE_PROPERTY \ QT_FORWARD_DECLARE_CLASS \ diff --git a/examples/widgets/painting/fontsampler/mainwindow.cpp b/examples/widgets/painting/fontsampler/mainwindow.cpp index 5aecea4968..192ffbd369 100644 --- a/examples/widgets/painting/fontsampler/mainwindow.cpp +++ b/examples/widgets/painting/fontsampler/mainwindow.cpp @@ -49,7 +49,9 @@ ****************************************************************************/ #include <QtWidgets> +#if defined(QT_PRINTSUPPORT_LIB) #include <QPrintPreviewDialog> +#endif #include "mainwindow.h" @@ -212,7 +214,7 @@ QMap<QString, StyleItems> MainWindow::currentPageMap() void MainWindow::on_printAction_triggered() { -#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) pageMap = currentPageMap(); if (pageMap.count() == 0) @@ -229,12 +231,12 @@ void MainWindow::on_printAction_triggered() printer.setFromTo(1, pageMap.keys().count()); printDocument(&printer); -#endif // QT_NO_PRINTER +#endif } void MainWindow::printDocument(QPrinter *printer) { -#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) printer->setFromTo(1, pageMap.count()); QProgressDialog progress(tr("Preparing font samples..."), tr("&Cancel"), @@ -263,12 +265,12 @@ void MainWindow::printDocument(QPrinter *printer) } painter.end(); -#endif // QT_NO_PRINTER +#endif } void MainWindow::on_printPreviewAction_triggered() { -#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) pageMap = currentPageMap(); if (pageMap.count() == 0) @@ -279,12 +281,12 @@ void MainWindow::on_printPreviewAction_triggered() connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(printDocument(QPrinter*))); preview.exec(); -#endif // QT_NO_PRINTER +#endif } void MainWindow::printPage(int index, QPainter *painter, QPrinter *printer) { -#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) +#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) QString family = pageMap.keys()[index]; StyleItems items = pageMap[family]; @@ -347,5 +349,5 @@ void MainWindow::printPage(int index, QPainter *painter, QPrinter *printer) } painter->restore(); -#endif // QT_NO_PRINTER +#endif } diff --git a/examples/widgets/painting/fontsampler/mainwindow.h b/examples/widgets/painting/fontsampler/mainwindow.h index 6d73e84ea3..8f59e1021b 100644 --- a/examples/widgets/painting/fontsampler/mainwindow.h +++ b/examples/widgets/painting/fontsampler/mainwindow.h @@ -55,6 +55,9 @@ #include <QPrinter> #include <QPrintDialog> +#if defined(QT_PRINTSUPPORT_LIB) +#include <QtPrintSupport/qtprintsupportglobal.h> +#endif QT_BEGIN_NAMESPACE class QPrinter; class QTextEdit; @@ -74,9 +77,9 @@ public: public slots: void on_clearAction_triggered(); void on_markAction_triggered(); + void on_unmarkAction_triggered(); void on_printAction_triggered(); void on_printPreviewAction_triggered(); - void on_unmarkAction_triggered(); void printDocument(QPrinter *printer); void printPage(int index, QPainter *painter, QPrinter *printer); void showFont(QTreeWidgetItem *item); diff --git a/mkspecs/common/android-base-head.conf b/mkspecs/common/android-base-head.conf index b75bcfaacb..ae4933c453 100644 --- a/mkspecs/common/android-base-head.conf +++ b/mkspecs/common/android-base-head.conf @@ -1,5 +1,8 @@ load(device_config) +# In early configure setup; nothing useful to be done here. +isEmpty(DEFAULT_ANDROID_NDK_ROOT): return() + NDK_ROOT = $$(ANDROID_NDK_ROOT) !exists($$NDK_ROOT) { NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf index 47eaa83e42..23bd6696de 100644 --- a/mkspecs/common/android-base-tail.conf +++ b/mkspecs/common/android-base-tail.conf @@ -1,3 +1,6 @@ +# In early configure setup; nothing useful to be done here. +isEmpty(DEFAULT_ANDROID_NDK_ROOT): return() + # -fstack-protector-strong offers good protection against stack smashing attacks. # It is (currently) enabled only on Android because we know for sure that Andoroid compilers supports it QMAKE_CFLAGS += -fstack-protector-strong -DANDROID diff --git a/mkspecs/devices/common/linux_device_post.conf b/mkspecs/devices/common/linux_device_post.conf index 88fa31d805..cf1608f32b 100644 --- a/mkspecs/devices/common/linux_device_post.conf +++ b/mkspecs/devices/common/linux_device_post.conf @@ -1,3 +1,7 @@ +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + contains(DISTRO_OPTS, deb-multi-arch) { QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib/$${GCC_MACHINE_DUMP} \ -Wl,-rpath-link,$$[QT_SYSROOT]/lib/$${GCC_MACHINE_DUMP} @@ -10,5 +14,3 @@ contains(DISTRO_OPTS, boot2qt) { QMAKE_CFLAGS += $$COMPILER_FLAGS QMAKE_CXXFLAGS += $$COMPILER_FLAGS QMAKE_LFLAGS += $$LINKER_FLAGS - -deviceSanityCheckCompiler() diff --git a/mkspecs/devices/linux-archos-gen8-g++/qmake.conf b/mkspecs/devices/linux-archos-gen8-g++/qmake.conf index 891559f3bf..66662f90ca 100644 --- a/mkspecs/devices/linux-archos-gen8-g++/qmake.conf +++ b/mkspecs/devices/linux-archos-gen8-g++/qmake.conf @@ -16,6 +16,10 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + QT_QPA_DEFAULT_PLATFORM = eglfs # modifications to g++.conf @@ -51,6 +55,4 @@ QMAKE_LIBS_EGL = -lEGL -lIMGegl -lsrv_um QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 $${QMAKE_LIBS_EGL} QMAKE_LIBS_OPENVG = -lOpenVG $${QMAKE_LIBS_EGL} -deviceSanityCheckCompiler() - load(qt_config) diff --git a/mkspecs/devices/linux-arm-amlogic-8726M-g++/qmake.conf b/mkspecs/devices/linux-arm-amlogic-8726M-g++/qmake.conf index da2e046d08..74eaf0dd09 100644 --- a/mkspecs/devices/linux-arm-amlogic-8726M-g++/qmake.conf +++ b/mkspecs/devices/linux-arm-amlogic-8726M-g++/qmake.conf @@ -12,6 +12,10 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_CXX = $${CROSS_COMPILE}g++ QMAKE_LINK = $${QMAKE_CXX} @@ -25,8 +29,6 @@ QMAKE_STRIP = $${CROSS_COMPILE}strip QMAKE_CFLAGS += -mfloat-abi=softfp -mfpu=neon -mcpu=cortex-a9 QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -deviceSanityCheckCompiler() - EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/qeglfshooks_8726m.cpp QT_QPA_DEFAULT_PLATFORM = eglfs diff --git a/mkspecs/devices/linux-arm-trident-pnx8473-g++/qmake.conf b/mkspecs/devices/linux-arm-trident-pnx8473-g++/qmake.conf index 3bbb7b6db9..b131f65a79 100644 --- a/mkspecs/devices/linux-arm-trident-pnx8473-g++/qmake.conf +++ b/mkspecs/devices/linux-arm-trident-pnx8473-g++/qmake.conf @@ -14,11 +14,17 @@ include(../../common/g++-unix.conf) load(device_config) -# Sanity checks -isEmpty(TRIDENT_SHINER_SDK_BUILDTREE): error("TRIDENT_SHINER_SDK_BUILDTREE needs to be set via -device-option TRIDENT_SHINER_SDK_BUILDTREE=<path>") -isEmpty(TRIDENT_SHINER_SDK_BUILDSPEC): error("TRIDENT_SHINER_SDK_BUILDSPEC needs to be set via -device-option TRIDENT_SHINER_SDK_BUILDSPEC=<build spec>") -isEmpty(TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2): error("TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2 needs to be set via -device-option TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2=<path>") -isEmpty(TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2): error("TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2 needs to be set via -device-option TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2=<path>") +defineTest(qtConfSanitizeMkspec) { + isEmpty(TRIDENT_SHINER_SDK_BUILDTREE): \ + error("TRIDENT_SHINER_SDK_BUILDTREE needs to be set via -device-option TRIDENT_SHINER_SDK_BUILDTREE=<path>") + isEmpty(TRIDENT_SHINER_SDK_BUILDSPEC): \ + error("TRIDENT_SHINER_SDK_BUILDSPEC needs to be set via -device-option TRIDENT_SHINER_SDK_BUILDSPEC=<build spec>") + isEmpty(TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2): \ + error("TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2 needs to be set via -device-option TRIDENT_SHINER_SDK_INCDIR_EGL_OPENGL_ES2=<path>") + isEmpty(TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2): \ + error("TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2 needs to be set via -device-option TRIDENT_SHINER_SDK_LIBDIR_EGL_OPENGL_ES2=<path>") + deviceSanityCheckCompiler() +} QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_CXX = $${CROSS_COMPILE}g++ @@ -35,8 +41,6 @@ QMAKE_CFLAGS += --sysroot=$${TRIDENT_SHINER_SDK_BUILDTREE}/open_source QMAKE_CXXFLAGS += --sysroot=$${TRIDENT_SHINER_SDK_BUILDTREE}/open_source_archive/linux/toolchains/gcc-4.5.2_uclibc/ QMAKE_LFLAGS += --sysroot=$${TRIDENT_SHINER_SDK_BUILDTREE}/open_source_archive/linux/toolchains/gcc-4.5.2_uclibc/ -deviceSanityCheckCompiler() - QMAKE_CFLAGS = -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard QMAKE_CXXFLAGS = $$QMAKE_CFLAGS diff --git a/mkspecs/devices/linux-mipsel-broadcom-97425-g++/qmake.conf b/mkspecs/devices/linux-mipsel-broadcom-97425-g++/qmake.conf index e196f279d7..9211551daf 100644 --- a/mkspecs/devices/linux-mipsel-broadcom-97425-g++/qmake.conf +++ b/mkspecs/devices/linux-mipsel-broadcom-97425-g++/qmake.conf @@ -12,6 +12,16 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + isEmpty(B_REFSW_DEBUG): \ + error("B_REFSW_DEBUG needs to be set via -device-option B_REFSW_DEBUG=(y|n)") + isEmpty(BRCM_ROCKFORD_PATH): \ + error("BRCM_ROCKFORD_PATH needs to be set via -device-option BRCM_ROCKFORD_PATH=<path>") + isEmpty(BRCM_APPLIBS_PATH): \ + error("BRCM_APPLIBS_PATH needs to be set via -device-option BRCM_APPLIBS_PATH=<path>") + deviceSanityCheckCompiler() +} + # Modify the defaults we loaded above CROSS_COMPILE = mipsel-linux- QMAKE_CC = $${CROSS_COMPILE}gcc @@ -31,12 +41,6 @@ QMAKE_STRIP = $${CROSS_COMPILE}strip BRCM_PLATFORM = 97425 -# Sanity checks -deviceSanityCheckCompiler() -isEmpty(B_REFSW_DEBUG):error("B_REFSW_DEBUG needs to be set via -device-option B_REFSW_DEBUG=(y|n).") -isEmpty(BRCM_ROCKFORD_PATH):error("BRCM_ROCKFORD_PATH needs to be set via -device-option BRCM_ROCKFORD_PATH=path.") -isEmpty(BRCM_APPLIBS_PATH):error("BRCM_APPLIBS_PATH needs to be set via -device-option BRCM_APPLIBS_PATH=path.") - # Figure the kind of directfb build used. BRCM_BUILD_TYPE = debug contains(B_REFSW_DEBUG, [Nn]) { diff --git a/mkspecs/devices/linux-sh4-stmicro-ST7108-g++/qmake.conf b/mkspecs/devices/linux-sh4-stmicro-ST7108-g++/qmake.conf index 18d07dad63..8dab1ea287 100644 --- a/mkspecs/devices/linux-sh4-stmicro-ST7108-g++/qmake.conf +++ b/mkspecs/devices/linux-sh4-stmicro-ST7108-g++/qmake.conf @@ -14,6 +14,10 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_CXX = $${CROSS_COMPILE}g++ QMAKE_LINK = $${QMAKE_CXX} @@ -24,8 +28,6 @@ QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_NM = $${CROSS_COMPILE}nm -P QMAKE_STRIP = $${CROSS_COMPILE}strip -deviceSanityCheckCompiler() - QMAKE_LIBS_EGL += -lMali QT_QPA_DEFAULT_PLATFORM = eglfs diff --git a/mkspecs/devices/linux-sh4-stmicro-ST7540-g++/qmake.conf b/mkspecs/devices/linux-sh4-stmicro-ST7540-g++/qmake.conf index 5672829da9..04b0a80d1f 100644 --- a/mkspecs/devices/linux-sh4-stmicro-ST7540-g++/qmake.conf +++ b/mkspecs/devices/linux-sh4-stmicro-ST7540-g++/qmake.conf @@ -14,6 +14,10 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_CXX = $${CROSS_COMPILE}g++ QMAKE_LINK = $${QMAKE_CXX} @@ -24,8 +28,6 @@ QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_NM = $${CROSS_COMPILE}nm -P QMAKE_STRIP = $${CROSS_COMPILE}strip -deviceSanityCheckCompiler() - QMAKE_INCDIR_EGL += $$[QT_SYSROOT]/root/modules/include/ QMAKE_LIBDIR_EGL += $$[QT_SYSROOT]/root/modules/ diff --git a/mkspecs/devices/linux-snowball-g++/qmake.conf b/mkspecs/devices/linux-snowball-g++/qmake.conf index 3520c7a922..9791119363 100644 --- a/mkspecs/devices/linux-snowball-g++/qmake.conf +++ b/mkspecs/devices/linux-snowball-g++/qmake.conf @@ -12,6 +12,10 @@ include(../../common/g++-unix.conf) load(device_config) +defineTest(qtConfSanitizeMkspec) { + deviceSanityCheckCompiler() +} + QMAKE_CC = $${CROSS_COMPILE}gcc QMAKE_CXX = $${CROSS_COMPILE}g++ QMAKE_LINK = $${QMAKE_CXX} @@ -26,6 +30,4 @@ QMAKE_STRIP = $${CROSS_COMPILE}strip QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/usr/lib/arm-linux-gnueabihf \ -Wl,-rpath-link,$$[QT_SYSROOT]/lib/arm-linux-gnueabihf -deviceSanityCheckCompiler() - load(qt_config) diff --git a/mkspecs/dummy/qmake.conf b/mkspecs/dummy/qmake.conf new file mode 100644 index 0000000000..7077fe6345 --- /dev/null +++ b/mkspecs/dummy/qmake.conf @@ -0,0 +1,8 @@ +# +# Minimal qmake configuration qt_configure.prf is run with. +# + +# Make spec_post.prf happy. +MAKEFILE_GENERATOR = DUMMY +QMAKE_PLATFORM = dummy_platform +QMAKE_COMPILER = dummy_compiler diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf index 4ca7c6ba07..934a18a924 100644 --- a/mkspecs/features/configure.prf +++ b/mkspecs/features/configure.prf @@ -4,6 +4,8 @@ cache() load(configure_base) +isEmpty(QMAKE_CONFIG_VERBOSE): QMAKE_CONFIG_VERBOSE = false + QMAKE_CONFIG_LOG = $$dirname(_QMAKE_CACHE_)/config.log recheck: write_file($$QMAKE_CONFIG_LOG, "") diff --git a/mkspecs/features/configure_base.prf b/mkspecs/features/configure_base.prf index dd1f4e5bfc..41f429e204 100644 --- a/mkspecs/features/configure_base.prf +++ b/mkspecs/features/configure_base.prf @@ -22,8 +22,6 @@ QMAKE_MAKE = $$(MAKE) # Make sure we don't inherit MAKEFLAGS - -i in particular is fatal. QMAKE_MAKE = "$${SETENV_PFX}MAKEFLAGS=$$SETENV_SFX $$QMAKE_MAKE" -isEmpty(QMAKE_CONFIG_VERBOSE): QMAKE_CONFIG_VERBOSE = false - defineTest(qtLog) { write_file($$QMAKE_CONFIG_LOG, 1, append) $$QMAKE_CONFIG_VERBOSE: for (l, 1): log("$$l$$escape_expand(\\n)") diff --git a/mkspecs/features/data/configure.json b/mkspecs/features/data/configure.json new file mode 100644 index 0000000000..8e5ff5f0a4 --- /dev/null +++ b/mkspecs/features/data/configure.json @@ -0,0 +1,25 @@ +{ + "files": { + }, + + "commandline": { + "options": { + "v": { "type": "enum", "name": "verbose", "values": { "yes": "true", "no": "false" } }, + "verbose": { "type": "enum", "values": { "yes": "true", "no": "false" } }, + + "continue": "void", + + "recheck": { "type": "void", "name": "cache_use", "value": "positive" }, + "recheck-all": { "type": "void", "name": "cache_use", "value": "none" }, + + "redo": { "type": "redo" } + } + + }, + + "features": { + "builtins": { + "output": [ "builtins" ] + } + } +} diff --git a/mkspecs/features/device_config.prf b/mkspecs/features/device_config.prf index 9281d3e407..c15559e174 100644 --- a/mkspecs/features/device_config.prf +++ b/mkspecs/features/device_config.prf @@ -1,45 +1,12 @@ # This file is loaded by some qmakespecs to get early configuration data. -host_build: \ - PRI_FILE_NAME = qhost.pri -else: \ - PRI_FILE_NAME = qdevice.pri -DEVICE_PRI = $$[QT_HOST_DATA/get]/mkspecs/$$PRI_FILE_NAME +# Some of these qmakespecs can be used also in host mode, but they are not +# supposed to be influenced by -device-option then. +host_build: return() + +DEVICE_PRI = $$[QT_HOST_DATA/get]/mkspecs/qdevice.pri exists($$DEVICE_PRI):include($$DEVICE_PRI) unset(DEVICE_PRI) # this variable can be persisted via qmake -set CROSS_COMPILE /foo -!host_build:isEmpty(CROSS_COMPILE): CROSS_COMPILE = $$[CROSS_COMPILE] - -# Provide a function to be used by mkspecs -defineTest(deviceSanityCheckCompiler) { - equals(QMAKE_HOST.os, Windows): \ - sfx = .exe - else: \ - sfx = - - # Build the compiler filename using the first value in QMAKE_CXX in order to - # support tools like ccache, which give QMAKE_CXX values of the form: - # ccache <path_to_compiler> - compiler = $$first(QMAKE_CXX)$$sfx - - # Check if the binary exists with an absolute path. Do this check - # before the CROSS_COMPILE empty check below to allow the mkspec - # to derive the compiler path from other device options. - exists($$compiler):return() - - # Check for possible reasons of failure - # check if CROSS_COMPILE device-option is set - isEmpty(CROSS_COMPILE):error("CROSS_COMPILE needs to be set via -device-option CROSS_COMPILE=<path>") - - # Check if QMAKE_CXX points to an executable. - ensurePathEnv() - for (dir, QMAKE_PATH_ENV) { - exists($$dir/$${compiler}): \ - return() - } - - # QMAKE_CXX does not point to a compiler. - error("Compiler $$QMAKE_CXX not found. Check the value of CROSS_COMPILE -device-option") -} - +isEmpty(CROSS_COMPILE): CROSS_COMPILE = $$[CROSS_COMPILE] diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index 333d06f63a..119dc53d20 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -28,12 +28,13 @@ win32:count(MOC_INCLUDEPATH, 40, >) { # UIKit builds are always multi-arch due to simulator_and_device (unless # -sdk is used) so this feature cannot possibly work. if(gcc|intel_icl|msvc):!rim_qcc:!uikit:if(!macos|count(QMAKE_APPLE_DEVICE_ARCHS, 1)) { + moc_predefs.name = "Generate moc_predefs.h" moc_predefs.CONFIG = no_link gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} - else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Za -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} else:msvc { moc_predefs.commands += $$QMAKE_CXX -Bx$$shell_quote($$shell_path($$QMAKE_QMAKE)) $$QMAKE_CXXFLAGS \ - -E ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT} + -E -Za ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT} } else: error("Oops, I messed up") moc_predefs.output = $$MOC_DIR/moc_predefs.h moc_predefs.input = MOC_PREDEF_FILE diff --git a/mkspecs/features/qlalr.prf b/mkspecs/features/qlalr.prf index 941bfe0d9f..54d8b583c6 100644 --- a/mkspecs/features/qlalr.prf +++ b/mkspecs/features/qlalr.prf @@ -25,7 +25,7 @@ for (s, QLALRSOURCES) { $${base}.variable_out = GENERATED_SOURCES $${base}.depends += $$QMAKE_QLALR_EXE $${base}.commands = $$QMAKE_QLALR $$QMAKE_QLALRFLAGS ${QMAKE_FILE_IN} - silent: $${base}.commands = @echo qlalr ${QMAKE_FILE_IN} && $${base}.commands + silent: $${base}.commands = @echo qlalr ${QMAKE_FILE_IN} && $$eval($${base}.commands) $${base}.name = QLALR ${QMAKE_FILE_IN} $${base}_h.input = $$invar diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 9b3deff331..a620e94e97 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -162,7 +162,8 @@ defineTest(qtConfCommandline_addString) { val = $${2} isEmpty(val): val = $$qtConfGetNextCommandlineArg() - contains(val, "^-.*|[A-Z_]+=.*")|isEmpty(val) { + # Note: Arguments which are variable assignments are legit here. + contains(val, "^-.*")|isEmpty(val) { qtConfAddError("No value supplied to command line option '$$opt'.") return() } @@ -177,6 +178,17 @@ defineTest(qtConfCommandline_addString) { export(config.input.$$opt) } +defineTest(qtConfCommandline_redo) { + !exists($$OUT_PWD/config.opt) { + qtConfAddError("No config.opt present - cannot redo configuration.") + return() + } + QMAKE_EXTRA_ARGS = $$cat($$OUT_PWD/config.opt, lines) $$QMAKE_EXTRA_ARGS + export(QMAKE_EXTRA_ARGS) + QMAKE_REDO_CONFIG = true + export(QMAKE_REDO_CONFIG) +} + defineTest(qtConfParseCommandLine) { customCalls = for (cc, allConfigs) { @@ -194,29 +206,6 @@ defineTest(qtConfParseCommandLine) { c = $$qtConfGetNextCommandlineArg() isEmpty(c): break() - # handle options to turn on verbose logging - contains(c, "^-v")|contains(c, "^--?verbose") { - QMAKE_CONFIG_VERBOSE = true - export(QMAKE_CONFIG_VERBOSE) - next() - } - contains(c, "^-no-v")|contains(c, "^--?no-verbose") { - QMAKE_CONFIG_VERBOSE = false - export(QMAKE_CONFIG_VERBOSE) - next() - } - - contains(c, "^--?recheck") { - QMAKE_CONFIG_CACHE_USE = positive - export(QMAKE_CONFIG_CACHE_USE) - next() - } - contains(c, "^--?recheck-all") { - QMAKE_CONFIG_CACHE_USE = none - export(QMAKE_CONFIG_CACHE_USE) - next() - } - didCustomCall = false for (customCall, customCalls) { $${customCall}($$c) { @@ -774,6 +763,7 @@ defineTest(qtConfTest_compile) { QMAKE_MAKE = "$$QMAKE_MAKE clean && $$QMAKE_MAKE" mkpath($$test_out_dir)|error() + write_file($$test_out_dir/.qmake.cache)|error() # add possible command line args qmake_args += $$qtConfPrepareArgs($$eval($${1}.args)) $$eval($${1}.literal_args) @@ -1622,6 +1612,19 @@ defineTest(qtConfOutput_privateFeature) { } } +# command line built-ins post-processing +defineTest(qtConfOutput_builtins) { + QMAKE_CONFIG_VERBOSE = $$eval(config.input.verbose) + isEmpty(QMAKE_CONFIG_VERBOSE): \ + QMAKE_CONFIG_VERBOSE = false + export(QMAKE_CONFIG_VERBOSE) + + QMAKE_CONFIG_CACHE_USE = $$eval(config.input.cache_use) + isEmpty(QMAKE_CONFIG_CACHE_USE): \ + QMAKE_CONFIG_CACHE_USE = all + export(QMAKE_CONFIG_CACHE_USE) +} + defineTest(qtConfProcessOneOutput) { feature = $${1} fpfx = $${currentConfig}.features.$${feature} @@ -1657,7 +1660,7 @@ defineTest(qtConfProcessOutput) { module = $$eval($${currentConfig}.module) # write it to the output files - isEmpty($${currentConfig}.files._KEYS_) { + !defined($${currentConfig}.files._KEYS_, var) { # set defaults that should work for most Qt modules isEmpty(module): \ error("Neither module nor files section specified in configuration file.") @@ -1677,7 +1680,7 @@ defineTest(qtConfProcessOutput) { $${currentConfig}.output.$$type += "$$k -= $$eval($${currentConfig}.output.$${type}.remove.$$k)" for (k, $${currentConfig}.output.$${type}.append._KEYS_): \ $${currentConfig}.output.$$type += "$$k += $$eval($${currentConfig}.output.$${type}.append.$$k)" - } else { + } else: contains(type, ".*Header") { for (define, $${currentConfig}.output.$${type}._KEYS_) { value = $$eval($${currentConfig}.output.$${type}.$${define}) $${currentConfig}.output.$$type += "$${LITERAL_HASH}define $$define $$value" @@ -1730,6 +1733,8 @@ isEmpty(configsToProcess): \ load(configure_base) QMAKE_POST_CONFIGURE = +config.builtins.dir = $$PWD/data +configsToProcess = builtins $$configsToProcess allConfigs = for(ever) { isEmpty(configsToProcess): \ @@ -1763,14 +1768,22 @@ for(ever) { for (currentConfig, allConfigs): \ qtConfSetupLibraries() +QMAKE_SAVED_ARGS = $$QMAKE_EXTRA_ARGS +QMAKE_REDO_CONFIG = false +qtConfParseCommandLine() + +for (currentConfig, allConfigs) { + qtConfSetModuleName() + qtConfSetupModuleOutputs() + # do early checks, mainly to validate the command line + qtConfProcessEarlyChecks() +} +qtConfCheckErrors() + !isEmpty(_QMAKE_SUPER_CACHE_): \ QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_SUPER_CACHE_)/config.cache else: \ QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_CACHE_)/config.cache -QMAKE_CONFIG_CACHE_USE = all - -qtConfParseCommandLine() - !equals(QMAKE_CONFIG_CACHE_USE, none) { include($$QMAKE_CONFIG_CACHE, , true) # this crudely determines when to discard the cache. this also catches the case @@ -1789,14 +1802,6 @@ QMAKE_CONFIG_LOG = $$OUT_PWD/config.log !equals(QMAKE_CONFIG_CACHE_USE, all): \ write_file($$QMAKE_CONFIG_LOG, "") -for (currentConfig, allConfigs) { - qtConfSetModuleName() - qtConfSetupModuleOutputs() - # do early checks, mainly to validate the command line - qtConfProcessEarlyChecks() -} -qtConfCheckErrors() - CONFIG += qt_conf_tests_allowed logn() logn("Running configuration tests...") @@ -1842,13 +1847,17 @@ for (currentConfig, allConfigs) { !isEmpty(QT_CONFIGURE_SKIPPED_MODULES): \ qtConfAddNote("The following modules are not being compiled in this configuration:" $$QT_CONFIGURE_SKIPPED_MODULES) +logn("Done running configuration tests.") +logn() + +!$$QMAKE_REDO_CONFIG { + write_file($$OUT_PWD/config.opt, QMAKE_SAVED_ARGS)|error() +} + # these come from the pri files loaded above. for (p, QMAKE_POST_CONFIGURE): \ eval($$p) -logn("Done running configuration tests.") -logn() - logn("Configure summary:") logn() qtConfPrintReport() diff --git a/mkspecs/features/qt_tool.prf b/mkspecs/features/qt_tool.prf index 4b73b4b8f7..a8d589f0fa 100644 --- a/mkspecs/features/qt_tool.prf +++ b/mkspecs/features/qt_tool.prf @@ -27,7 +27,7 @@ DEFINES *= QT_USE_QSTRINGBUILDER vars = binary depends - isEmpty(HOST_QT_TOOLS) { + !host_build|isEmpty(HOST_QT_TOOLS) { load(resolve_target) !host_build|!force_bootstrap: MODULE_DEPENDS = $$replace(QT, -private$, _private) diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index 3f266dd2a4..0ef0fa8fc7 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -1,4 +1,7 @@ +# In early configure setup; nothing useful to be done here. +isEmpty(QMAKE_CXX): return() + defineReplace(qtMakeExpand) { out = "$$1" for(ever) { diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index 495fd15e80..2c66e80db4 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -14,7 +14,7 @@ QMAKE_YACCFLAGS = -d QMAKE_CFLAGS = QMAKE_CFLAGS_APP = -fPIC QMAKE_CFLAGS_DEPS = -M -QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261 +QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261,3373 QMAKE_CFLAGS_WARN_OFF = -w QMAKE_CFLAGS_RELEASE = -O2 -falign-functions=16 -ansi-alias -fstrict-aliasing QMAKE_CFLAGS_DEBUG = -O0 -g diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index 990f3b39ee..0d349b2329 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -14,7 +14,7 @@ QMAKE_COMPILER = gcc clang intel_icc # icc pretends to be gcc and cla QMAKE_CC = icc QMAKE_CFLAGS = QMAKE_CFLAGS_DEPS = -M -QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280 +QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280,3373 QMAKE_CFLAGS_WARN_OFF = -w QMAKE_CFLAGS_RELEASE = QMAKE_CFLAGS_DEBUG = -g diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index e19570bf16..7cf94c3e40 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -17,7 +17,7 @@ QMAKE_LEX = flex QMAKE_LEXFLAGS = QMAKE_YACC = bison -y QMAKE_YACCFLAGS = -d -QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809 +QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809,3373 QMAKE_CFLAGS_WARN_ON = -W3 /Qwd673 QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673 QMAKE_CFLAGS_RELEASE = -O2 -MD diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 33ec2508e2..de41e14e75 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -66,7 +66,6 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/io/qdir.cpp $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \ $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \ - $(SOURCE_PATH)/src/corelib/global/qconfig.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \ @@ -225,7 +224,7 @@ qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp -qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(BUILD_PATH)/src/corelib/global/qconfig.cpp +qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index db8572839e..6c1644004e 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -156,8 +156,6 @@ $(OBJS): $(PCH_OBJECT) $(QTOBJS): $(PCH_OBJECT) -qlibraryinfo.obj: $(BUILD_PATH)\src\corelib\global\qconfig.cpp - qmake_pch.obj: $(CXX) $(CXXFLAGS_BARE) -c -Yc -Fpqmake_pch.pch -TP $(QMKSRC)\qmake_pch.h diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index e3d76cd76e..8d5a9a7d0f 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -308,13 +308,13 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t) { t << "first: all\n"; t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) - << ' ' << depVar("ALL_DEPS"); + << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n"; + t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS"); if (project->first("TEMPLATE") == "aux") { t << "\n\n"; return; } - t << " $(DESTDIR_TARGET)\n\n"; - t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS"); + if(!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" <<var("QMAKE_PRE_LINK"); if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") { diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 3a4f6242b2..da10b1984f 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -517,13 +517,12 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) t << "first: all\n"; t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) - << ' ' << depVar("ALL_DEPS"); + << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n"; + t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS"); if (templateName == "aux") { t << "\n\n"; return; } - t << " $(DESTDIR_TARGET)\n\n"; - t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS"); if(!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" <<var("QMAKE_PRE_LINK"); diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 1fb83d719e..f4e2ef33ac 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2293,10 +2293,14 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) QString inFile = info.file; // is the extracompiler rule on a file with a built in compiler? - const QStringList &objectMappedFile = Project->extraCompilerOutputs[inFile]; + const QString objectMappedFile = Project->extraCompilerOutputs.value(inFile); bool hasBuiltIn = false; if (!objectMappedFile.isEmpty()) { - hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile.at(0)); + hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile); + + // Remove the fake file suffix we've added initially to generate correct command lines. + inFile.chop(Project->customBuildToolFilterFileSuffix.length()); + // qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' '))); } @@ -2338,7 +2342,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) // compiler, too bad.. if (hasBuiltIn) { out = inFile; - inFile = objectMappedFile.at(0); + inFile = objectMappedFile; } // Dependency for the output diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index a5ee42a449..6a8d8b7e0f 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -111,7 +111,8 @@ const char _slnExtSections[] = "\n\tGlobalSection(ExtensibilityGlobals) = pos VcprojGenerator::VcprojGenerator() : Win32MakefileGenerator(), is64Bit(false), - projectWriter(0) + projectWriter(0), + customBuildToolFilterFileSuffix(QStringLiteral(".cbt")) { } @@ -800,10 +801,14 @@ void VcprojGenerator::init() if (!hasBuiltinCompiler(file)) { extraCompilerSources[file] += quc.toQString(); } else { + // Use a fake file name foo.moc.cbt for the project view. + // This prevents VS from complaining about a circular + // dependency from foo.moc -> foo.moc. QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables( compiler_out, file, QString(), NoShell), false); + out += customBuildToolFilterFileSuffix; extraCompilerSources[out] += quc.toQString(); - extraCompilerOutputs[out] = QStringList(file); // Can only have one + extraCompilerOutputs[out] = file; } } } diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index 9ccd8c2552..e3e67d64b9 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -63,7 +63,8 @@ public: static bool hasBuiltinCompiler(const QString &file); QHash<QString, QStringList> extraCompilerSources; - QHash<QString, QStringList> extraCompilerOutputs; + QHash<QString, QString> extraCompilerOutputs; + const QString customBuildToolFilterFileSuffix; bool usePCH; VCProjectWriter *projectWriter; diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 48df4ff916..3c029c8004 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -165,6 +165,9 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) void Win32MakefileGenerator::processVars() { + if (project->first("TEMPLATE").endsWith("aux")) + return; + project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); if (project->isEmpty("QMAKE_PROJECT_NAME")) project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET"); diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h index 05d9e8da28..c81e205699 100644 --- a/qmake/library/proitems.h +++ b/qmake/library/proitems.h @@ -329,6 +329,9 @@ enum ProToken { // - function name: hash (2), length (1), chars (length) // - body length (2) // - body + TokTerminator (body length) + TokBypassNesting, // escape from function local variable scopes: + // - block length (2) + // - block + TokTerminator (block length) TokMask = 0xff, TokQuoted = 0x100, // The expression is quoted => join expanded stringlist TokNewStr = 0x200 // Next stringlist element diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 02c910fe46..b30373b596 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -101,7 +101,7 @@ enum TestFunc { T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE, T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF, - T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE + T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE, T_RELOAD_PROPERTIES }; void QMakeEvaluator::initFunctionStatics() @@ -200,6 +200,7 @@ void QMakeEvaluator::initFunctionStatics() { "write_file", T_WRITE_FILE }, { "touch", T_TOUCH }, { "cache", T_CACHE }, + { "reload_properties", T_RELOAD_PROPERTIES }, }; statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0]))); for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i) @@ -560,11 +561,9 @@ void QMakeEvaluator::populateDeps( } } -ProStringList QMakeEvaluator::evaluateBuiltinExpand( - int func_t, const ProKey &func, const ProStringList &args) +QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( + int func_t, const ProKey &func, const ProStringList &args, ProStringList &ret) { - ProStringList ret; - traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args)); switch (func_t) { @@ -1110,6 +1109,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (qfile.open(stdin, QIODevice::ReadOnly)) { QTextStream t(&qfile); const QString &line = t.readLine(); + if (t.atEnd()) { + fputs("\n", stderr); + evalError(fL1S("Unexpected EOF.")); + return ReturnError; + } ret = split_value_list(QStringRef(&line)); } } @@ -1279,7 +1283,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( break; } - return ret; + return ReturnTrue; } QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( @@ -2012,6 +2016,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr); } + case T_RELOAD_PROPERTIES: +#ifdef QT_BUILD_QMAKE + m_option->reloadProperties(); +#endif + return ReturnTrue; default: evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); return ReturnFalse; diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index fd24cf209d..767528eb57 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -594,6 +594,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock( tokPtr += blockLen; okey = true, or_op = false; // force next evaluation break; + case TokBypassNesting: + blockLen = getBlockLen(tokPtr); + if ((m_cumulative || okey != or_op) && blockLen) { + ProValueMapStack savedValuemapStack = m_valuemapStack; + m_valuemapStack.clear(); + m_valuemapStack.append(savedValuemapStack.takeFirst()); + traceMsg("visiting nesting-bypassing block"); + ret = visitProBlock(tokPtr); + traceMsg("visited nesting-bypassing block"); + savedValuemapStack.prepend(m_valuemapStack.first()); + m_valuemapStack = savedValuemapStack; + } else { + traceMsg("skipped nesting-bypassing block"); + ret = ReturnTrue; + } + tokPtr += blockLen; + okey = true, or_op = false; // force next evaluation + break; case TokTestDef: case TokReplaceDef: if (m_cumulative || okey != or_op) { @@ -1761,8 +1779,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( ProStringList args; if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError) return ReturnError; - *ret = evaluateBuiltinExpand(func_t, func, args); - return ReturnTrue; + return evaluateBuiltinExpand(func_t, func, args, *ret); } QHash<ProKey, ProFunctionDef>::ConstIterator it = diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index 3f2a22c567..544c257f07 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -212,7 +212,7 @@ public: VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret); VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr); - ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args); + VisitReturn evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args, ProStringList &ret); VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args); VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1); diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h index 96c39fa168..1bb8632883 100644 --- a/qmake/library/qmakeglobals.h +++ b/qmake/library/qmakeglobals.h @@ -125,6 +125,7 @@ public: void setDirectories(const QString &input_dir, const QString &output_dir); #ifdef QT_BUILD_QMAKE void setQMakeProperty(QMakeProperty *prop) { property = prop; } + void reloadProperties() { property->reload(); } ProString propertyValue(const ProKey &name) const { return property->value(name); } #else # ifdef PROEVALUATOR_INIT_PROPS diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index 56b217dfbb..78350c76c4 100644 --- a/qmake/library/qmakeparser.cpp +++ b/qmake/library/qmakeparser.cpp @@ -118,6 +118,7 @@ static struct { QString strfor; QString strdefineTest; QString strdefineReplace; + QString strbypassNesting; QString stroption; QString strreturn; QString strnext; @@ -141,6 +142,7 @@ void QMakeParser::initialize() statics.strfor = QLatin1String("for"); statics.strdefineTest = QLatin1String("defineTest"); statics.strdefineReplace = QLatin1String("defineReplace"); + statics.strbypassNesting = QLatin1String("bypassNesting"); statics.stroption = QLatin1String("option"); statics.strreturn = QLatin1String("return"); statics.strnext = QLatin1String("next"); @@ -1157,6 +1159,25 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg } parseError(fL1S("%1(function) requires one literal argument.").arg(*defName)); return; + } else if (m_tmp == statics.strbypassNesting) { + if (*uce != TokFuncTerminator) { + bogusTest(tokPtr, fL1S("%1() requires zero arguments.").arg(m_tmp)); + return; + } + if (!(m_blockstack.top().nest & NestFunction)) { + bogusTest(tokPtr, fL1S("Unexpected %1().").arg(m_tmp)); + return; + } + if (m_invert) { + bogusTest(tokPtr, fL1S("Unexpected NOT operator in front of %1().").arg(m_tmp)); + return; + } + flushScopes(tokPtr); + putLineMarker(tokPtr); + putOperator(tokPtr); + putTok(tokPtr, TokBypassNesting); + enterScope(tokPtr, true, StCtrl); + return; } else if (m_tmp == statics.strreturn) { if (m_blockstack.top().nest & NestFunction) { if (argc > 1) { @@ -1425,7 +1446,7 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS "TokReturn", "TokBreak", "TokNext", "TokNot", "TokAnd", "TokOr", "TokBranch", "TokForLoop", - "TokTestDef", "TokReplaceDef" + "TokTestDef", "TokReplaceDef", "TokBypassNesting" }; while (offset != limit) { @@ -1509,6 +1530,9 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS if (ok) ok = getSubBlock(tokens, limit, offset, outStr, indent, "body"); break; + case TokBypassNesting: + ok = getSubBlock(tokens, limit, offset, outStr, indent, "block"); + break; default: Q_ASSERT(!"unhandled token"); } diff --git a/qmake/option.cpp b/qmake/option.cpp index fb49f5a100..b8102ecf06 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -638,6 +638,11 @@ qmakeAddCacheClear(qmakeCacheClearFunc func, void **data) cache_items.append(new QMakeCacheClearItem(func, data)); } +QString qmake_absoluteLocation() +{ + return Option::globals->qmake_abslocation; +} + QString qmake_libraryInfoFile() { if (!Option::globals->qtconf.isEmpty()) diff --git a/qmake/project.cpp b/qmake/project.cpp index 2f8411d52f..3a073b0954 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -99,8 +99,12 @@ QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> { m_current.clear(); - if (int func_t = statics.expands.value(func)) - return evaluateBuiltinExpand(func_t, func, prepareBuiltinArgs(args)).toQStringList(); + if (int func_t = statics.expands.value(func)) { + ProStringList ret; + if (evaluateBuiltinExpand(func_t, func, prepareBuiltinArgs(args), ret) == ReturnError) + exit(3); + return ret.toQStringList(); + } QHash<ProKey, ProFunctionDef>::ConstIterator it = m_functionDefs.replaceFunctions.constFind(func); diff --git a/qmake/property.cpp b/qmake/property.cpp index d17d62481a..9a8db8904d 100644 --- a/qmake/property.cpp +++ b/qmake/property.cpp @@ -70,6 +70,12 @@ static const struct { QMakeProperty::QMakeProperty() : settings(0) { + reload(); +} + +void QMakeProperty::reload() +{ + QLibraryInfo::reload(); for (unsigned i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) { QString name = QString::fromLatin1(propList[i].name); if (!propList[i].singular) { diff --git a/qmake/property.h b/qmake/property.h index cd04e4bc03..b0129196eb 100644 --- a/qmake/property.h +++ b/qmake/property.h @@ -50,6 +50,8 @@ public: QMakeProperty(); ~QMakeProperty(); + void reload(); + bool hasValue(const ProKey &); ProString value(const ProKey &); diff --git a/qmake/qmake-aux.pro b/qmake/qmake-aux.pro index 33a7fbfd2d..357ebc7367 100644 --- a/qmake/qmake-aux.pro +++ b/qmake/qmake-aux.pro @@ -6,6 +6,24 @@ QMAKE_DOCS = $$PWD/doc/qmake.qdocconf # qmake binary win32: EXTENSION = .exe + +!build_pass { + qmake_exe.target = $$OUT_PWD/qmake$$EXTENSION + qmake_exe.depends = ../bin/qmake$$EXTENSION builtin-qt.conf + equals(QMAKE_DIR_SEP, /): \ + qmake_exe.commands = cat ../bin/qmake$$EXTENSION builtin-qt.conf > qmake$$EXTENSION && chmod +x qmake$$EXTENSION + else: \ + qmake_exe.commands = copy /B ..\bin\qmake$$EXTENSION + builtin-qt.conf qmake$$EXTENSION + QMAKE_EXTRA_TARGETS += qmake_exe + + QMAKE_CLEAN += builtin-qt.conf + QMAKE_DISTCLEAN += qmake$$EXTENSION + + first.depends += qmake_exe + QMAKE_EXTRA_TARGETS += first +} + qmake.path = $$[QT_HOST_BINS] -qmake.files = $$OUT_PWD/../bin/qmake$$EXTENSION +qmake.files = $$OUT_PWD/qmake$$EXTENSION +qmake.CONFIG = no_check_exist executable INSTALLS += qmake diff --git a/qtbase.pro b/qtbase.pro index 4aa4d6f600..c0ce0972ef 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -28,7 +28,6 @@ QMAKE_DISTCLEAN += \ config.tests/.qmake.cache \ mkspecs/qconfig.pri \ mkspecs/qdevice.pri \ - mkspecs/qhost.pri \ mkspecs/qmodule.pri \ src/corelib/global/qconfig.h \ src/corelib/global/qconfig_p.h \ @@ -79,7 +78,7 @@ prefix_build|!equals(PWD, $$OUT_PWD) { mkspecs.path = $$[QT_HOST_DATA]/mkspecs mkspecs.files = \ $$OUT_PWD/mkspecs/qconfig.pri $$OUT_PWD/mkspecs/qmodule.pri \ - $$OUT_PWD/mkspecs/qdevice.pri $$OUT_PWD/mkspecs/qhost.pri \ + $$OUT_PWD/mkspecs/qdevice.pri \ $$files($$PWD/mkspecs/*) mkspecs.files -= $$PWD/mkspecs/modules $$PWD/mkspecs/modules-inst INSTALLS += mkspecs diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri index 58caacb837..4535880536 100644 --- a/src/android/jar/jar.pri +++ b/src/android/jar/jar.pri @@ -17,7 +17,9 @@ JAVASOURCES += \ $$PATHPREFIX/QtNativeLibrariesDir.java \ $$PATHPREFIX/QtSurface.java \ $$PATHPREFIX/ExtractStyle.java \ - $$PATHPREFIX/QtServiceDelegate.java + $$PATHPREFIX/EditMenu.java \ + $$PATHPREFIX/EditPopupMenu.java \ + $$PATHPREFIX/CursorHandle.java # install target.path = $$[QT_INSTALL_PREFIX]/jar diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml index 43296f2e7a..77f422cfb2 100644 --- a/src/android/templates/res/values/libs.xml +++ b/src/android/templates/res/values/libs.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> <resources> <array name="qt_sources"> - <item>https://download.qt.io/ministro/android/qt5/qt-5.7</item> + <item>https://download.qt.io/ministro/android/qt5/qt-5.8</item> </array> <!-- The following is handled automatically by the deployment tool. It should diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp index d222ca32a7..b84cf0ae2d 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.cpp @@ -52,7 +52,7 @@ class MyXcbEventFilter : public QAbstractNativeEventFilter { public: - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE + bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override { if (eventType == "xcb_generic_event_t") { xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message); diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h index 6666bc56c5..9734f99d50 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h @@ -44,6 +44,6 @@ class MyCocoaEventFilter : public QAbstractNativeEventFilter { public: - bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; + bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override; }; //! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp index a621109c0d..7c687a0430 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp @@ -55,7 +55,7 @@ class MyObject; class WorkerThread : public QThread { Q_OBJECT - void run() Q_DECL_OVERRIDE { + void run() override { QString result; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index d978c141a4..4142c17b42 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1273,7 +1273,7 @@ # define QT_WARNING_DISABLE_INTEL(number) __pragma(warning(disable: number)) # define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_GCC(text) -# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1786) +# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786) #elif defined(Q_CC_INTEL) /* icc: Intel compiler on Linux or OS X */ # define QT_WARNING_PUSH QT_DO_PRAGMA(warning(push)) @@ -1282,7 +1282,7 @@ # define QT_WARNING_DISABLE_MSVC(number) # define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_GCC(text) -# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1786) +# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786) #elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG) # undef QT_DO_PRAGMA /* not needed */ # define QT_WARNING_PUSH __pragma(warning(push)) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 4354c85bfe..7a0804d436 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -925,8 +925,8 @@ template <typename T> class QForeachContainer { QForeachContainer &operator=(const QForeachContainer &) Q_DECL_EQ_DELETE; public: - QForeachContainer(const T &t) : c(t) {} - QForeachContainer(T &&t) : c(std::move(t)) {} + QForeachContainer(const T &t) : c(t), i(c.begin()), e(c.end()) {} + QForeachContainer(T &&t) : c(std::move(t)), i(c.begin()), e(c.end()) {} QForeachContainer(const QForeachContainer &other) : c(other.c), i(c.begin()), @@ -936,7 +936,7 @@ public: } const T c; - typename T::const_iterator i = c.begin(), e = c.end(); + typename T::const_iterator i, e; int control = 1; }; diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 27fe10a79e..87ee75fa45 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -41,15 +41,18 @@ #include "qdir.h" #include "qstringlist.h" #include "qfile.h" +#include "qtemporaryfile.h" #include "qsettings.h" #include "qlibraryinfo.h" #include "qscopedpointer.h" #ifdef QT_BUILD_QMAKE QT_BEGIN_NAMESPACE +extern QString qmake_absoluteLocation(); extern QString qmake_libraryInfoFile(); QT_END_NAMESPACE #else +# include "qconfig.cpp" # include "qcoreapplication.h" #endif @@ -57,7 +60,6 @@ QT_END_NAMESPACE # include "private/qcore_mac_p.h" #endif -#include "qconfig.cpp" #include "archdetect.cpp" QT_BEGIN_NAMESPACE @@ -70,9 +72,16 @@ struct QLibrarySettings { QLibrarySettings(); void load(); +#ifdef QT_BUILD_QMAKE + void loadBuiltinValues(QSettings *config); +#endif QScopedPointer<QSettings> settings; #ifdef QT_BUILD_QMAKE + QString builtinValues[QLibraryInfo::LastHostPath + 1]; +# ifndef Q_OS_WIN + QString builtinSettingsPath; +# endif bool haveDevicePaths; bool haveEffectiveSourcePaths; bool haveEffectivePaths; @@ -88,6 +97,11 @@ class QLibraryInfoPrivate public: static QSettings *findConfiguration(); #ifdef QT_BUILD_QMAKE + static void reload() + { + if (qt_library_settings.exists()) + qt_library_settings->load(); + } static bool haveGroup(QLibraryInfo::PathGroup group) { QLibrarySettings *ls = qt_library_settings(); @@ -99,6 +113,25 @@ public: ? ls->haveDevicePaths : ls->havePaths) : false; } + static bool sysrootify() + { + // This is actually bogus, as it does not consider post-configure settings. + QLibrarySettings *ls = qt_library_settings(); + return ls ? (!ls->builtinValues[QLibraryInfo::SysrootPath].isEmpty() + && ls->builtinValues[QLibraryInfo::ExtPrefixPath].isEmpty()) : false; + } + static QString builtinValue(int loc) + { + QLibrarySettings *ls = qt_library_settings(); + return ls ? ls->builtinValues[loc] : QString(); + } +# ifndef Q_OS_WIN + static QString builtinSettingsPath() + { + QLibrarySettings *ls = qt_library_settings(); + return ls ? ls->builtinSettingsPath : QString(); + } +# endif #endif static QSettings *configuration() { @@ -122,6 +155,20 @@ QLibrarySettings::QLibrarySettings() load(); } +#ifdef QT_BUILD_QMAKE +static QByteArray qtconfSeparator() +{ +# ifdef Q_OS_WIN + QByteArray header = QByteArrayLiteral("\r\n===========================================================\r\n"); +# else + QByteArray header = QByteArrayLiteral("\n===========================================================\n"); +# endif + QByteArray content = QByteArrayLiteral("==================== qt.conf beginning ===================="); + // Assemble from pieces to avoid that the string appears in a raw executable + return header + content + header; +} +#endif + void QLibrarySettings::load() { // If we get any settings here, those won't change when the application shows up. @@ -159,6 +206,27 @@ void QLibrarySettings::load() havePaths = false; #endif } + +#ifdef QT_BUILD_QMAKE + // Try to use an embedded qt.conf appended to the QMake executable. + QFile qmakeFile(qmake_absoluteLocation()); + if (!qmakeFile.open(QIODevice::ReadOnly)) + return; + qmakeFile.seek(qmakeFile.size() - 10000); + QByteArray tail = qmakeFile.read(10000); + QByteArray separator = qtconfSeparator(); + int qtconfOffset = tail.lastIndexOf(separator); + if (qtconfOffset < 0) + return; + tail.remove(0, qtconfOffset + separator.size()); + // If QSettings had a c'tor taking a QIODevice, we'd pass a QBuffer ... + QTemporaryFile tmpFile; + tmpFile.open(); + tmpFile.write(tail); + tmpFile.close(); + QSettings builtinSettings(tmpFile.fileName(), QSettings::IniFormat); + loadBuiltinValues(&builtinSettings); +#endif } QSettings *QLibraryInfoPrivate::findConfiguration() @@ -420,10 +488,30 @@ static const struct { { "HostData", "." }, { "TargetSpec", "" }, { "HostSpec", "" }, + { "ExtPrefix", "" }, { "HostPrefix", "" }, #endif }; +#ifdef QT_BUILD_QMAKE +void QLibrarySettings::loadBuiltinValues(QSettings *config) +{ + config->beginGroup(QLatin1String("Paths")); + for (int i = 0; i <= QLibraryInfo::LastHostPath; i++) + builtinValues[i] = config->value(QLatin1String(qtConfEntries[i].key), + QLatin1String(qtConfEntries[i].value)).toString(); +# ifndef Q_OS_WIN + builtinSettingsPath = config->value(QLatin1String("Settings")).toString(); +# endif + config->endGroup(); +} + +void QLibraryInfo::reload() +{ + QLibraryInfoPrivate::reload(); +} +#endif + /*! Returns the location specified by \a loc. */ @@ -434,7 +522,7 @@ QLibraryInfo::location(LibraryLocation loc) QString ret = rawLocation(loc, FinalPaths); // Automatically prepend the sysroot to target paths - if ((loc < SysrootPath || loc > LastHostPath) && QT_CONFIGURE_SYSROOTIFY_PREFIX) { + if ((loc < SysrootPath || loc > LastHostPath) && QLibraryInfoPrivate::sysrootify()) { QString sysroot = rawLocation(SysrootPath, FinalPaths); if (!sysroot.isEmpty() && ret.length() > 2 && ret.at(1) == QLatin1Char(':') && (ret.at(2) == QLatin1Char('/') || ret.at(2) == QLatin1Char('\\'))) @@ -528,28 +616,32 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) #endif // QT_NO_SETTINGS if (!fromConf) { +#ifdef QT_BUILD_QMAKE + if ((unsigned)loc <= (unsigned)LastHostPath) { + if (loc == PrefixPath && group != DevicePaths) + ret = QLibraryInfoPrivate::builtinValue(ExtPrefixPath); + else + ret = QLibraryInfoPrivate::builtinValue(loc); +# ifndef Q_OS_WIN // On Windows we use the registry + } else if (loc == SettingsPath) { + ret = QLibraryInfoPrivate::builtinSettingsPath(); +# endif + } +#else // QT_BUILD_QMAKE const char * volatile path = 0; if (loc == PrefixPath) { - path = -#ifdef QT_BUILD_QMAKE - (group != DevicePaths) ? - QT_CONFIGURE_EXT_PREFIX_PATH : -#endif - QT_CONFIGURE_PREFIX_PATH; + path = QT_CONFIGURE_PREFIX_PATH; } else if (unsigned(loc) <= sizeof(qt_configure_str_offsets)/sizeof(qt_configure_str_offsets[0])) { path = qt_configure_strs + qt_configure_str_offsets[loc - 1]; #ifndef Q_OS_WIN // On Windows we use the registry } else if (loc == SettingsPath) { path = QT_CONFIGURE_SETTINGS_PATH; #endif -#ifdef QT_BUILD_QMAKE - } else if (loc == HostPrefixPath) { - path = QT_CONFIGURE_HOST_PREFIX_PATH; -#endif } if (path) ret = QString::fromLocal8Bit(path); +#endif } #ifdef QT_BUILD_QMAKE diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 55be706382..9d794ce1da 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -96,6 +96,7 @@ public: HostDataPath, TargetSpecPath, HostSpecPath, + ExtPrefixPath, HostPrefixPath, LastHostPath = HostPrefixPath, #endif @@ -105,6 +106,7 @@ public: #ifdef QT_BUILD_QMAKE enum PathGroup { FinalPaths, EffectivePaths, EffectiveSourcePaths, DevicePaths }; static QString rawLocation(LibraryLocation, PathGroup); + static void reload(); #endif static QStringList platformPluginArguments(const QString &platformName); diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 0506d372b6..6b90a47388 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1042,6 +1042,10 @@ void QMessagePattern::setPattern(const QString &pattern) delete [] literals; } delete [] tokens; + timeArgs.clear(); +#ifdef QLOGGING_HAVE_BACKTRACE + backtraceArgs.clear(); +#endif // scanner QList<QString> lexemes; diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 23fcf340f1..01b8772ee1 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -68,7 +68,8 @@ #if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL) || !defined(__cplusplus)) # include <math.h> -# define QT_MATH_H_DEFINES_MACROS +# ifdef isnan +# define QT_MATH_H_DEFINES_MACROS QT_BEGIN_NAMESPACE namespace qnumeric_std_wrapper { // the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros. @@ -81,10 +82,11 @@ static inline bool math_h_isfinite(float f) { using namespace std; return isfini } QT_END_NAMESPACE // These macros from math.h conflict with the real functions in the std namespace. -#undef signbit -#undef isnan -#undef isinf -#undef isfinite +# undef signbit +# undef isnan +# undef isinf +# undef isfinite +# endif // defined(isnan) #endif QT_BEGIN_NAMESPACE diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index fa919e9f10..be33ec2d23 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -579,6 +579,22 @@ QDebug &QDebug::resetFormat() */ /*! + \fn QDebug &QDebug::operator<<(char16_t t) + \since 5.5 + + Writes the UTF-16 character, \a t, to the stream and returns a reference + to the stream. +*/ + +/*! + \fn QDebug &QDebug::operator<<(char32_t t) + \since 5.5 + + Writes the UTF-32 character, \a t, to the stream and returns a reference + to the stream. +*/ + +/*! \fn QDebug &QDebug::operator<<(const QString &s) Writes the string, \a s, to the stream and returns a reference to the diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index 99d223ca88..ad549dcd7b 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -122,6 +122,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64 \code using namespace std::chrono; + using namespace std::chrono_literals; QDeadlineTimer deadline(30s); device->waitForReadyRead(deadline); @@ -141,6 +142,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64 \code using namespace std::chrono; + using namespace std::chrono_literals; auto now = steady_clock::now(); QDeadlineTimer deadline(now + 1s); Q_ASSERT(deadline == now + 1s); @@ -240,7 +242,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW This constructor can be used with C++14's user-defined literals for time, such as in: \code - using namespace std::chrono; + using namespace std::chrono_literals; QDeadlineTimer deadline(250ms); \endcode @@ -333,7 +335,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time This function can be used with C++14's user-defined literals for time, such as in: \code - using namespace std::chrono; + using namespace std::chrono_literals; deadline.setRemainingTime(250ms); \endcode diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e64812b3ae..7b0a9f986b 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1389,10 +1389,6 @@ namespace QtPrivate }; -QT_WARNING_PUSH -// In C++03 mode, clang consider local or unnamed type and throw a warning instead of ignoring them -QT_WARNING_DISABLE_CLANG("-Wunnamed-type-template-args") -QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args") template<typename T> char qt_getEnumMetaObject(const T&); template<typename T> @@ -1405,7 +1401,6 @@ QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args") enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) }; }; template<> struct IsQEnumHelper<void> { enum { Value = false }; }; -QT_WARNING_POP template<typename T, typename Enable = void> struct MetaObjectForType diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 0aee4aeda4..653c3efe1c 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -279,7 +279,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT for the mutex to become available. Note: Passing a negative duration as the \a duration is equivalent to - calling try_lock(). This behavior is different from tryLock. + calling try_lock(). This behavior differs from tryLock(). If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. @@ -303,7 +303,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT for the mutex to become available. Note: Passing a \a timePoint which has already passed is equivalent - to calling try_lock. This behavior is different from tryLock. + to calling try_lock(). This behavior differs from tryLock(). If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index 7e846956f5..fb7031ce71 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -535,7 +535,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera # define QT_HAS_BUILTIN_CTZS Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW { -# if QT_HAS_BUILTIN(__builtin_ctzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_ctzs) return __builtin_ctzs(v); # else return __builtin_ctz(v); @@ -544,7 +544,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW #define QT_HAS_BUILTIN_CLZS Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW { -# if QT_HAS_BUILTIN(__builtin_clzs) || defined(__BMI__) +# if QT_HAS_BUILTIN(__builtin_clzs) return __builtin_clzs(v); # else return __builtin_clz(v) - 16U; diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h index 258ce0fce6..7d3cbab322 100644 --- a/src/gui/image/qbmphandler_p.h +++ b/src/gui/image/qbmphandler_p.h @@ -94,17 +94,17 @@ public: }; explicit QBmpHandler(InternalFormat fmt = BmpFormat); - bool canRead() const; - bool read(QImage *image); - bool write(const QImage &image); + bool canRead() const override; + bool read(QImage *image) override; + bool write(const QImage &image) override; - QByteArray name() const; + QByteArray name() const override; static bool canRead(QIODevice *device); - QVariant option(ImageOption option) const; - void setOption(ImageOption option, const QVariant &value); - bool supportsOption(ImageOption option) const; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; + bool supportsOption(ImageOption option) const override; private: bool readHeader(); diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index 16cd4aa954..0ba9844f7a 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -92,6 +92,14 @@ QIconEngine::QIconEngine() } /*! + \since 5.8 + \internal + */ +QIconEngine::QIconEngine(const QIconEngine &) +{ +} + +/*! Destroys the icon engine. */ QIconEngine::~QIconEngine() diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index b0c92ced73..783770cd30 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -51,6 +51,7 @@ class Q_GUI_EXPORT QIconEngine { public: QIconEngine(); + QIconEngine(const QIconEngine &other); // ### Qt6: make protected virtual ~QIconEngine(); virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0; virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); @@ -80,6 +81,9 @@ public: bool isNull() const; // ### Qt6 make virtual virtual void virtual_hook(int id, void *data); + +private: + QIconEngine &operator=(const QIconEngine &other) Q_DECL_EQ_DELETE; }; #if QT_DEPRECATED_SINCE(5, 0) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 7e0922a90a..b1dcf6a9f8 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -596,37 +596,6 @@ bool QImageData::checkForAlphaPixels() const \endtable - \target qimage-legalese - \section1 Legal Information - - For smooth scaling, the transformed() functions use code based on - smooth scaling algorithm by Daniel M. Duley. - - \badcode - Copyright (C) 2004, 2005 Daniel M. Duley - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - \endcode - \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer, {Image Composition Example}, {Image Viewer Example}, {Scribble Example}, {Pixelator Example} */ diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h index 269df25794..4ca716e7c2 100644 --- a/src/gui/image/qpnghandler_p.h +++ b/src/gui/image/qpnghandler_p.h @@ -65,15 +65,15 @@ public: QPngHandler(); ~QPngHandler(); - bool canRead() const; - bool read(QImage *image); - bool write(const QImage &image); + bool canRead() const override; + bool read(QImage *image) override; + bool write(const QImage &image) override; - QByteArray name() const; + QByteArray name() const override; - QVariant option(ImageOption option) const; - void setOption(ImageOption option, const QVariant &value); - bool supportsOption(ImageOption option) const; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; + bool supportsOption(ImageOption option) const override; static bool canRead(QIODevice *device); diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h index 8889d9e663..1c6fbd6869 100644 --- a/src/gui/image/qppmhandler_p.h +++ b/src/gui/image/qppmhandler_p.h @@ -63,17 +63,17 @@ class QPpmHandler : public QImageIOHandler { public: QPpmHandler(); - bool canRead() const; - bool read(QImage *image); - bool write(const QImage &image); + bool canRead() const override; + bool read(QImage *image) override; + bool write(const QImage &image) override; - QByteArray name() const; + QByteArray name() const override; static bool canRead(QIODevice *device, QByteArray *subType = 0); - QVariant option(ImageOption option) const; - void setOption(ImageOption option, const QVariant &value); - bool supportsOption(ImageOption option) const; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; + bool supportsOption(ImageOption option) const override; private: bool readHeader(); diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h index 561153376d..26439af527 100644 --- a/src/gui/image/qxbmhandler_p.h +++ b/src/gui/image/qxbmhandler_p.h @@ -62,17 +62,17 @@ class QXbmHandler : public QImageIOHandler { public: QXbmHandler(); - bool canRead() const; - bool read(QImage *image); - bool write(const QImage &image); + bool canRead() const override; + bool read(QImage *image) override; + bool write(const QImage &image) override; - QByteArray name() const; + QByteArray name() const override; static bool canRead(QIODevice *device); - QVariant option(ImageOption option) const; - void setOption(ImageOption option, const QVariant &value); - bool supportsOption(ImageOption option) const; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; + bool supportsOption(ImageOption option) const override; private: bool readHeader(); diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h index af3e98d3ff..f118bf2309 100644 --- a/src/gui/image/qxpmhandler_p.h +++ b/src/gui/image/qxpmhandler_p.h @@ -62,17 +62,17 @@ class QXpmHandler : public QImageIOHandler { public: QXpmHandler(); - bool canRead() const; - bool read(QImage *image); - bool write(const QImage &image); + bool canRead() const override; + bool read(QImage *image) override; + bool write(const QImage &image) override; static bool canRead(QIODevice *device); - QByteArray name() const; + QByteArray name() const override; - QVariant option(ImageOption option) const; - void setOption(ImageOption option, const QVariant &value); - bool supportsOption(ImageOption option) const; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; + bool supportsOption(ImageOption option) const override; private: bool readHeader(); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 468523ab9c..44ec9c95da 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -44,6 +44,7 @@ #include "qpa/qplatformdrag.h" #include "private/qevent_p.h" #include "qfile.h" +#include "qhashfunctions.h" #include "qmetaobject.h" #include "qmimedata.h" #include "private/qdnd_p.h" @@ -4476,14 +4477,14 @@ int QTouchEvent::TouchPoint::id() const \since 5.8 Returns the unique ID of this touch point or token, if any. - It is normally invalid (with a \l {QPointerUniqueId::numeric()} {numeric()} value of -1), + It is normally invalid (see \l {QPointingDeviceUniqueId::isValid()} {isValid()}), because touchscreens cannot uniquely identify fingers. But when the \l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely identify a specific token (fiducial object). \sa flags */ -QPointerUniqueId QTouchEvent::TouchPoint::uniqueId() const +QPointingDeviceUniqueId QTouchEvent::TouchPoint::uniqueId() const { return d->uniqueId; } @@ -4795,7 +4796,7 @@ void QTouchEvent::TouchPoint::setUniqueId(qint64 uid) { if (d->ref.load() != 1) d = d->detach(); - d->uniqueId = QPointerUniqueId(uid); + d->uniqueId = QPointingDeviceUniqueId::fromNumericId(uid); } /*! \internal */ @@ -5226,36 +5227,99 @@ Qt::ApplicationState QApplicationStateChangeEvent::applicationState() const } /*! - \class QPointerUniqueId + \class QPointingDeviceUniqueId \since 5.8 \ingroup events \inmodule QtGui - \brief QPointerUniqueId identifies a unique object, such as a tagged token + \brief QPointingDeviceUniqueId identifies a unique object, such as a tagged token or stylus, which is used with a pointing device. + QPointingDeviceUniqueIds can be compared for equality, and can be used as keys in a QHash. + You get access to the numerical ID via numericId(), if the device supports such IDs. + For future extensions, though, you should not use that function, but compare objects + of this type using the equality operator. + + This class is a thin wrapper around an integer ID. You pass it into and out of + functions by value. + + This type actively prevents you from holding it in a QList, because doing so would + be very inefficient. Use a QVector instead, which has the same API as QList, but more + efficient storage. + \sa QTouchEvent::TouchPoint */ /*! - Constructs a unique pointer ID with a numeric \a id provided by the hardware. - The default is -1, which means an invalid pointer ID. + \fn QPointingDeviceUniqueId::QPointingDeviceUniqueId() + Constructs an invalid unique pointer ID. +*/ + +/*! + Constructs a unique pointer ID from numeric ID \a id. */ -QPointerUniqueId::QPointerUniqueId(qint64 id) - : m_numericId(id) +QPointingDeviceUniqueId QPointingDeviceUniqueId::fromNumericId(qint64 id) { + QPointingDeviceUniqueId result; + result.m_numericId = id; + return result; } /*! - \property QPointerUniqueId::numeric + \fn bool QPointingDeviceUniqueId::isValid() const + + Returns whether this unique pointer ID is valid, that is, it represents an actual + pointer. +*/ + +/*! + \property QPointingDeviceUniqueId::numericId \brief the numeric unique ID of the token represented by a touchpoint - This is the numeric unique ID if the device provides that type of ID; + If the device provides a numeric ID, isValid() returns true, and this + property provides the numeric ID; otherwise it is -1. + + You should not use the value of this property in portable code, but + instead rely on equality to identify pointers. + + \sa isValid() */ -qint64 QPointerUniqueId::numeric() const +qint64 QPointingDeviceUniqueId::numericId() const Q_DECL_NOTHROW { return m_numericId; } +/*! + \relates QPointingDeviceUniqueId + \since 5.8 + + Returns whether the two unique pointer IDs \a lhs and \a rhs identify the same pointer + (\c true) or not (\c false). +*/ +bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW +{ + return lhs.numericId() == rhs.numericId(); +} + +/*! + \fn bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) + \relates QPointingDeviceUniqueId + \since 5.8 + + Returns whether the two unique pointer IDs \a lhs and \a rhs identify different pointers + (\c true) or not (\c false). +*/ + +/*! + \relates QPointingDeviceUniqueId + \since 5.8 + + Returns the hash value for \a key, using \a seed to seed the calculation. +*/ +uint qHash(QPointingDeviceUniqueId key, uint seed) Q_DECL_NOTHROW +{ + return qHash(key.numericId(), seed); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index d7b7b636b2..cfc3b842d7 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -793,21 +793,36 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} #endif // QT_NO_SHORTCUT -class QPointerUniqueIdPrivate; -class Q_GUI_EXPORT QPointerUniqueId +class Q_GUI_EXPORT QPointingDeviceUniqueId { Q_GADGET - Q_PROPERTY(qint64 numeric READ numeric CONSTANT) + Q_PROPERTY(qint64 numericId READ numericId CONSTANT) public: - explicit QPointerUniqueId(qint64 id = -1); + Q_ALWAYS_INLINE + Q_DECL_CONSTEXPR QPointingDeviceUniqueId() Q_DECL_NOTHROW : m_numericId(-1) {} + // compiler-generated copy/move ctor/assignment operators are ok! + // compiler-generated dtor is ok! - qint64 numeric() const; + static QPointingDeviceUniqueId fromNumericId(qint64 id); + + Q_ALWAYS_INLINE Q_DECL_CONSTEXPR bool isValid() const Q_DECL_NOTHROW { return m_numericId != -1; } + qint64 numericId() const Q_DECL_NOTHROW; private: - // TODO for TUIO 2, or any other type of complex token ID, a d-pointer can replace - // m_numericId without changing the size of this class. + // TODO: for TUIO 2, or any other type of complex token ID, an internal + // array (or hash) can be added to hold additional properties. + // In this case, m_numericId will then turn into an index into that array (or hash). qint64 m_numericId; }; +Q_DECLARE_TYPEINFO(QPointingDeviceUniqueId, Q_MOVABLE_TYPE); +template <> class QList<QPointingDeviceUniqueId> {}; // to prevent instantiation: use QVector instead + +Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW; +inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW +{ return !operator==(lhs, rhs); } +Q_GUI_EXPORT uint qHash(QPointingDeviceUniqueId key, uint seed = 0) Q_DECL_NOTHROW; + + class QTouchEventTouchPointPrivate; class Q_GUI_EXPORT QTouchEvent : public QInputEvent @@ -844,7 +859,7 @@ public: { qSwap(d, other.d); } int id() const; - QPointerUniqueId uniqueId() const; + QPointingDeviceUniqueId uniqueId() const; Qt::TouchPointState state() const; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index f67284eebb..1eccfaea78 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -81,7 +81,7 @@ public: QAtomicInt ref; int id; - QPointerUniqueId uniqueId; + QPointingDeviceUniqueId uniqueId; Qt::TouchPointStates state; QPointF pos, scenePos, screenPos, normalizedPos, startPos, startScenePos, startScreenPos, startNormalizedPos, diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index d3f3827d6e..568b010792 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2603,7 +2603,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To break; } - if (w->d_func()->blockedByModalWindow) { + if (w->d_func()->blockedByModalWindow && !qApp->d_func()->popupActive()) { // a modal window is blocking this window, don't allow touch events through // QTBUG-37371 temporary fix; TODO: revisit in 5.4 when we have a forwarding solution diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index b6b57e01f5..11864e7adc 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -129,7 +129,7 @@ public: TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { } int id; // for application use qint64 uniqueId; // for TUIO: object/token ID; otherwise empty - // TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId) + // TODO for TUIO 2.0: add registerPointerUniqueID(QPointingDeviceUniqueId) QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) QRectF area; // dimensions of the elliptical contact patch, unrotated, and centered at position in screen coordinates // width is the horizontal diameter, height is the vertical diameter diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h index 27b7fba84f..300002a9c1 100644 --- a/src/gui/opengl/qopenglpaintdevice.h +++ b/src/gui/opengl/qopenglpaintdevice.h @@ -61,8 +61,8 @@ public: QOpenGLPaintDevice(int width, int height); virtual ~QOpenGLPaintDevice(); - int devType() const { return QInternal::OpenGL; } - QPaintEngine *paintEngine() const; + int devType() const override { return QInternal::OpenGL; } + QPaintEngine *paintEngine() const override; QOpenGLContext *context() const; QSize size() const; @@ -82,7 +82,7 @@ public: protected: QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd); - int metric(QPaintDevice::PaintDeviceMetric metric) const; + int metric(QPaintDevice::PaintDeviceMetric metric) const override; Q_DISABLE_COPY(QOpenGLPaintDevice) QScopedPointer<QOpenGLPaintDevicePrivate> d_ptr; diff --git a/src/gui/painting/QIMAGETRANSFORM_LICENSE.txt b/src/gui/painting/QIMAGETRANSFORM_LICENSE.txt new file mode 100644 index 0000000000..67c910826a --- /dev/null +++ b/src/gui/painting/QIMAGETRANSFORM_LICENSE.txt @@ -0,0 +1,60 @@ +qimagetransform.cpp was contributed by Daniel M. Duley based on code from Imlib2. + +Copyright (C) 2004, 2005 Daniel M. Duley + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +Imlib2 License + +Copyright (C) 2000 Carsten Haitzler and various contributors (see +AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies of the Software and its Copyright notices. In addition +publicly documented acknowledgment must be given that this software has +been used if no source code of this software is made available publicly. +This includes acknowledgments in either Copyright notices, Manuals, +Publicity and Marketing documents or any documentation provided with any +product containing this software. This License does not apply to any +software that links to the libraries provided by this software +(statically or dynamically), but only to the software provided. + +Please see the COPYING.PLAIN for a plain-english explanation of this +notice and it's intent. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h index 77b5be0c4c..7cac2ac358 100644 --- a/src/gui/painting/qdatabuffer_p.h +++ b/src/gui/painting/qdatabuffer_p.h @@ -65,10 +65,12 @@ public: QDataBuffer(int res) { capacity = res; - if (res) + if (res) { buffer = (Type*) malloc(capacity * sizeof(Type)); - else + Q_CHECK_PTR(buffer); + } else { buffer = 0; + } siz = 0; } @@ -115,14 +117,16 @@ public: while (capacity < size) capacity *= 2; buffer = (Type*) realloc(buffer, capacity * sizeof(Type)); + Q_CHECK_PTR(buffer); } } inline void shrink(int size) { capacity = size; - if (size) + if (size) { buffer = (Type*) realloc(buffer, capacity * sizeof(Type)); - else { + Q_CHECK_PTR(buffer); + } else { free(buffer); buffer = 0; } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 08f96bd654..772291b22b 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -844,6 +844,7 @@ template <QPixelLayout::BPP bpp> static uint QT_FASTCALL fetchPixel(const uchar *, int) { Q_UNREACHABLE(); + return 0; } template <> @@ -1581,7 +1582,7 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 Q_ASSERT(layout->bpp == bpp); // When templated 'fetch' should be inlined at compile time: - const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; + const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>); uint *const end = buffer + length; uint *b = buffer; @@ -2532,8 +2533,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 Q_ASSERT(layout->bpp == bpp); // When templated 'fetch' should be inlined at compile time: - const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : fetchPixels<bpp>; - const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; + const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : FetchPixelsFunc(fetchPixels<bpp>); + const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>); int image_width = data->texture.width; int image_height = data->texture.height; diff --git a/src/gui/painting/qemulationpaintengine_p.h b/src/gui/painting/qemulationpaintengine_p.h index 457cc06d63..a2eb9b008c 100644 --- a/src/gui/painting/qemulationpaintengine_p.h +++ b/src/gui/painting/qemulationpaintengine_p.h @@ -62,37 +62,37 @@ class QEmulationPaintEngine : public QPaintEngineEx public: QEmulationPaintEngine(QPaintEngineEx *engine); - virtual bool begin(QPaintDevice *pdev); - virtual bool end(); + bool begin(QPaintDevice *pdev) override; + bool end() override; - virtual Type type() const; - virtual QPainterState *createState(QPainterState *orig) const; + Type type() const override; + QPainterState *createState(QPainterState *orig) const override; - virtual void fill(const QVectorPath &path, const QBrush &brush); - virtual void stroke(const QVectorPath &path, const QPen &pen); - virtual void clip(const QVectorPath &path, Qt::ClipOperation op); + void fill(const QVectorPath &path, const QBrush &brush) override; + void stroke(const QVectorPath &path, const QPen &pen) override; + void clip(const QVectorPath &path, Qt::ClipOperation op) override; - virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); - virtual void drawStaticTextItem(QStaticTextItem *item); - virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override; + void drawTextItem(const QPointF &p, const QTextItem &textItem) override; + void drawStaticTextItem(QStaticTextItem *item) override; + void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override; + void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) override; - virtual void clipEnabledChanged(); - virtual void penChanged(); - virtual void brushChanged(); - virtual void brushOriginChanged(); - virtual void opacityChanged(); - virtual void compositionModeChanged(); - virtual void renderHintsChanged(); - virtual void transformChanged(); + void clipEnabledChanged() override; + void penChanged() override; + void brushChanged() override; + void brushOriginChanged() override; + void opacityChanged() override; + void compositionModeChanged() override; + void renderHintsChanged() override; + void transformChanged() override; - virtual void setState(QPainterState *s); + void setState(QPainterState *s) override; - virtual void beginNativePainting(); - virtual void endNativePainting(); + void beginNativePainting() override; + void endNativePainting() override; - virtual uint flags() const {return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate;} + uint flags() const override { return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate; } inline QPainterState *state() { return (QPainterState *)QPaintEngine::state; } inline const QPainterState *state() const { return (const QPainterState *)QPaintEngine::state; } diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 8cde88fa82..59213220a6 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -287,7 +287,7 @@ public: void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer); void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix); - void systemStateChanged(); + void systemStateChanged() override; void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func, const QRect &clip, int alpha, const QRect &sr = QRect()); diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h index baad274818..17c73dd480 100644 --- a/src/gui/painting/qpdfwriter.h +++ b/src/gui/painting/qpdfwriter.h @@ -67,7 +67,7 @@ public: QString creator() const; void setCreator(const QString &creator); - bool newPage(); + bool newPage() override; void setResolution(int resolution); int resolution() const; @@ -83,14 +83,14 @@ public: using QPagedPaintDevice::setPageSize; #endif - void setPageSize(PageSize size); - void setPageSizeMM(const QSizeF &size); + void setPageSize(PageSize size) override; + void setPageSizeMM(const QSizeF &size) override; - void setMargins(const Margins &m); + void setMargins(const Margins &m) override; protected: - QPaintEngine *paintEngine() const; - int metric(PaintDeviceMetric id) const; + QPaintEngine *paintEngine() const override; + int metric(PaintDeviceMetric id) const override; private: Q_DISABLE_COPY(QPdfWriter) diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h index ededb5d80b..1a7c184e1a 100644 --- a/src/gui/painting/qstroker_p.h +++ b/src/gui/painting/qstroker_p.h @@ -234,7 +234,7 @@ protected: static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode); static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle); - virtual void processCurrentSubpath(); + void processCurrentSubpath() override; qfixed m_strokeWidth; qfixed m_miterLimit; @@ -265,14 +265,14 @@ public: void setDashOffset(qreal offset) { m_dashOffset = offset; } qreal dashOffset() const { return m_dashOffset; } - virtual void begin(void *data); - virtual void end(); + void begin(void *data) override; + void end() override; inline void setStrokeWidth(qreal width) { m_stroke_width = width; } inline void setMiterLimit(qreal limit) { m_miter_limit = limit; } protected: - virtual void processCurrentSubpath(); + void processCurrentSubpath() override; QStroker *m_stroker; QVector<qfixed> m_dashPattern; diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json index f635cf98ac..06a62d9d66 100644 --- a/src/gui/painting/qt_attribution.json +++ b/src/gui/painting/qt_attribution.json @@ -1,14 +1,31 @@ -{ - "Id": "grayraster", - "Name": "Anti-aliasing rasterizer from FreeType 2", - "QDocModule": "qtgui", - "QtUsage": "Used in Qt GUI.", - "Path": "qgrayraster.c", +[ + { + "Id": "grayraster", + "Name": "Anti-aliasing rasterizer from FreeType 2", + "QDocModule": "qtgui", + "QtUsage": "Used in Qt GUI.", + "Path": "qgrayraster.c", - "Description": "FreeType is a freely available software library to render fonts.", - "Homepage": "http://www.freetype.org", - "License": "Freetype Project License or GNU General Public License v2.0 only", - "LicenseId": "FTL or GPL-2.0", - "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT", - "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." -} + "Description": "FreeType is a freely available software library to render fonts.", + "Homepage": "http://www.freetype.org", + "License": "Freetype Project License or GNU General Public License v2.0 only", + "LicenseId": "FTL or GPL-2.0", + "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT", + "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." + }, + { + "Id": "smooth-scaling-algorithm", + "Name": "Smooth Scaling Algorithm", + "QDocModule": "qtgui", + "QtUsage": "Used in Qt Gui (QImage::transformed() functions).", + "Files": "qimagescale.cpp", + + "Description": "Normal smoothscale method, based on Imlib2's smoothscale.", + "LicenseId": "BSD-2-Clause AND Imlib2", + "License": "BSD 2-clause \"Simplified\" License and Imlib2 License", + "LicenseFile": "QIMAGETRANSFORM_LICENSE.txt", + "Copyright": "Copyright (C) 2004, 2005 Daniel M. Duley. + (C) Carsten Haitzler and various contributors. + (C) Willem Monsuwe <willem@stack.nl>" + } +] diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 5e9fac5f86..6074917087 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1163,9 +1163,12 @@ QString QTextDocument::toRawText() const formatting information use a QTextCursor instead. This function returns the same as toRawText(), but will replace - some unicode characters, such as line separators and non-breaking - spaces, with ASCII alternatives. If you need the precise contents - of the document, use toRawText() instead. + some unicode characters with ASCII alternatives. + In particular, no-break space (U+00A0) is replaced by a regular + space (U+0020), and both paragraph (U+2029) and line (U+2028) + separators are replaced by line feed (U+000A). + If you need the precise contents of the document, use toRawText() + instead. \note Embedded objects, such as images, are represented by a Unicode value U+FFFC (OBJECT REPLACEMENT CHARACTER). diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 6f837de27f..128f75f93b 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -118,6 +118,7 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate() { for (int i = 0; i < channelCount; ++i) { if (channels[i].socket) { + QObject::disconnect(channels[i].socket, Q_NULLPTR, &channels[i], Q_NULLPTR); channels[i].socket->close(); delete channels[i].socket; } diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 2a905101a4..2b5fde2a76 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -517,6 +517,19 @@ QHostAddress::QHostAddress(const QHostAddress &address) QHostAddress::QHostAddress(SpecialAddress address) : d(new QHostAddressPrivate) { + setAddress(address); +} + +/*! + \overload + \since 5.8 + + Sets the special address specified by \a address. +*/ +void QHostAddress::setAddress(SpecialAddress address) +{ + d->clear(); + Q_IPV6ADDR ip6; memset(&ip6, 0, sizeof ip6); quint32 ip4 = INADDR_ANY; @@ -567,6 +580,7 @@ QHostAddress &QHostAddress::operator=(const QHostAddress &address) return *this; } +#if QT_DEPRECATED_SINCE(5, 8) /*! Assigns the host address \a address to this object, and returns a reference to this object. @@ -578,6 +592,20 @@ QHostAddress &QHostAddress::operator=(const QString &address) setAddress(address); return *this; } +#endif + +/*! + \since 5.8 + Assigns the special address \a address to this object, and returns a + reference to this object. + + \sa setAddress() +*/ +QHostAddress &QHostAddress::operator=(SpecialAddress address) +{ + setAddress(address); + return *this; +} /*! \fn bool QHostAddress::operator!=(const QHostAddress &other) const diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 58af14ee33..10fe33f6fa 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -108,7 +108,11 @@ public: #endif QHostAddress &operator=(const QHostAddress &other); +#if QT_DEPRECATED_SINCE(5, 8) + QT_DEPRECATED_X("use = QHostAddress(string) instead") QHostAddress &operator=(const QString &address); +#endif + QHostAddress &operator=(SpecialAddress address); void swap(QHostAddress &other) Q_DECL_NOTHROW { d.swap(other.d); } @@ -118,6 +122,7 @@ public: void setAddress(const Q_IPV6ADDR &ip6Addr); void setAddress(const sockaddr *address); bool setAddress(const QString &address); + void setAddress(SpecialAddress address); QAbstractSocket::NetworkLayerProtocol protocol() const; quint32 toIPv4Address() const; // ### Qt6: merge with next overload diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 8257eec9ea..8b36406c67 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -126,6 +126,33 @@ static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr<I } #endif // _MSC_VER >= 1900 +typedef QHash<qintptr, IStreamSocket *> TcpSocketHash; + +struct SocketHandler +{ + SocketHandler() : socketCount(0) {} + qintptr socketCount; + TcpSocketHash pendingTcpSockets; +}; + +Q_GLOBAL_STATIC(SocketHandler, gSocketHandler) + +struct SocketGlobal +{ + SocketGlobal() + { + HRESULT hr; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + &bufferFactory); + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr<IBufferFactory> bufferFactory; +}; +Q_GLOBAL_STATIC(SocketGlobal, g) + +#define READ_BUFFER_SIZE 65536 + static inline QString qt_QStringFromHString(const HString &string) { UINT32 length; @@ -136,8 +163,43 @@ static inline QString qt_QStringFromHString(const HString &string) class SocketEngineWorker : public QObject { Q_OBJECT +public: + SocketEngineWorker(QNativeSocketEnginePrivate *engine) + : enginePrivate(engine) + { + } + + ~SocketEngineWorker() + { + if (Q_UNLIKELY(initialReadOp)) { + ComPtr<IAsyncInfo> info; + HRESULT hr = initialReadOp.As(&info); + Q_ASSERT_SUCCEEDED(hr); + if (info) { + hr = info->Cancel(); + Q_ASSERT_SUCCEEDED(hr); + hr = info->Close(); + Q_ASSERT_SUCCEEDED(hr); + } + } + + if (readOp) { + ComPtr<IAsyncInfo> info; + HRESULT hr = readOp.As(&info); + Q_ASSERT_SUCCEEDED(hr); + if (info) { + hr = info->Cancel(); + Q_ASSERT_SUCCEEDED(hr); + hr = info->Close(); + Q_ASSERT_SUCCEEDED(hr); + } + } + } + signals: void newDatagramsReceived(const QList<WinRtDatagram> &datagram); + void newDataReceived(const QVector<QByteArray> &data); + void socketErrorOccured(QAbstractSocket::SocketError error); public slots: Q_INVOKABLE void notifyAboutNewDatagrams() @@ -148,7 +210,30 @@ public slots: emit newDatagramsReceived(datagrams); } + Q_INVOKABLE void notifyAboutNewData() + { + QMutexLocker locker(&mutex); + const QVector<QByteArray> newData = std::move(pendingData); + pendingData.clear(); + emit newDataReceived(newData); + } + public: + void startReading() + { + ComPtr<IBuffer> buffer; + HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IInputStream> stream; + hr = tcpSocket->get_InputStream(&stream); + Q_ASSERT_SUCCEEDED(hr); + hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, initialReadOp.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + enginePrivate->socketState = QAbstractSocket::ConnectedState; + hr = initialReadOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &SocketEngineWorker::onReadyRead).Get()); + Q_ASSERT_SUCCEEDED(hr); + } + HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args) { WinRtDatagram datagram; @@ -184,9 +269,127 @@ public: return S_OK; } + HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) + { + if (asyncInfo == initialReadOp.Get()) { + initialReadOp.Reset(); + } else if (asyncInfo == readOp.Get()) { + readOp.Reset(); + } else { + Q_ASSERT(false); + } + + // A read in UnconnectedState will close the socket and return -1 and thus tell the caller, + // that the connection was closed. The socket cannot be closed here, as the subsequent read + // might fail then. + if (status == Error || status == Canceled) { + emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); + return S_OK; + } + + ComPtr<IBuffer> buffer; + HRESULT hr = asyncInfo->GetResults(&buffer); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get read results buffer"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + + UINT32 bufferLength; + hr = buffer->get_Length(&bufferLength); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get buffer length"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + // A zero sized buffer length signals, that the remote host closed the connection. The socket + // cannot be closed though, as the following read might have socket descriptor -1 and thus and + // the closing of the socket won't be communicated to the caller. So only the error is set. The + // actual socket close happens inside of read. + if (!bufferLength) { + emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); + return S_OK; + } + + ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess; + hr = buffer.As(&byteArrayAccess); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get cast buffer"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + byte *data; + hr = byteArrayAccess->Buffer(&data); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to access buffer data"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + + QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength)); + QMutexLocker readLocker(&mutex); + if (pendingData.isEmpty()) + QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection); + pendingData << newData; + readLocker.unlock(); + + hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() { + UINT32 readBufferLength; + ComPtr<IInputStream> stream; + HRESULT hr = tcpSocket->get_InputStream(&stream); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to obtain input stream"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + + // Reuse the stream buffer + hr = buffer->get_Capacity(&readBufferLength); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get buffer capacity"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + hr = buffer->put_Length(0); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set buffer length"); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + + hr = stream->ReadAsync(buffer.Get(), readBufferLength, InputStreamOptions_Partial, &readOp); + if (FAILED(hr)) { + qErrnoWarning(hr, "onReadyRead(): Could not read into socket stream buffer."); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &SocketEngineWorker::onReadyRead).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "onReadyRead(): Failed to set socket read callback."); + emit socketErrorOccured(QAbstractSocket::UnknownSocketError); + return S_OK; + } + return S_OK; + }); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + } + + void setTcpSocket(ComPtr<IStreamSocket> socket) { tcpSocket = socket; } + private: + ComPtr<IStreamSocket> tcpSocket; + QList<WinRtDatagram> pendingDatagrams; + QVector<QByteArray> pendingData; + + // Protects pendingData/pendingDatagrams which are accessed from native callbacks QMutex mutex; + + ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> initialReadOp; + ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> readOp; + + QNativeSocketEnginePrivate *enginePrivate; }; static QByteArray socketDescription(const QAbstractSocketEngine *s) @@ -239,33 +442,6 @@ static QByteArray socketDescription(const QAbstractSocketEngine *s) } } while (0) #define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a) -typedef QHash<qintptr, IStreamSocket *> TcpSocketHash; - -struct SocketHandler -{ - SocketHandler() : socketCount(0) {} - qintptr socketCount; - TcpSocketHash pendingTcpSockets; -}; - -Q_GLOBAL_STATIC(SocketHandler, gSocketHandler) - -struct SocketGlobal -{ - SocketGlobal() - { - HRESULT hr; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - &bufferFactory); - Q_ASSERT_SUCCEEDED(hr); - } - - ComPtr<IBufferFactory> bufferFactory; -}; -Q_GLOBAL_STATIC(SocketGlobal, g) - -#define READ_BUFFER_SIZE 65536 - template <typename T> static AsyncStatus opStatus(const ComPtr<T> &op) { @@ -315,6 +491,10 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent) connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection); connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection); connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection); + connect(d->worker, &SocketEngineWorker::newDataReceived, + this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection); + connect(d->worker, &SocketEngineWorker::socketErrorOccured, + this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection); } QNativeSocketEngine::~QNativeSocketEngine() @@ -358,23 +538,9 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket:: // Start processing incoming data if (d->socketType == QAbstractSocket::TcpSocket) { - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, socketState, this]() { - ComPtr<IBuffer> buffer; - HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - RETURN_HR_IF_FAILED("initialize(): Could not create buffer"); - ComPtr<IInputStream> stream; - hr = socket->get_InputStream(&stream); - RETURN_HR_IF_FAILED("initialize(): Could not obtain input stream"); - ComPtr<IAsyncBufferOperation> readOp; - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, readOp.GetAddressOf()); - RETURN_HR_IF_FAILED_WITH_ARGS("initialize(): Failed to read from the socket buffer (%s).", - socketDescription(this).constData()); - QMutexLocker locker(&d->readOperationsMutex); - d->pendingReadOps.append(readOp); - d->socketState = socketState; - hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); - RETURN_HR_IF_FAILED_WITH_ARGS("initialize(): Failed to set socket read callback (%s).", - socketDescription(this).constData()); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, this]() { + d->worker->setTcpSocket(socket); + d->worker->startReading(); return S_OK; }); if (FAILED(hr)) @@ -639,20 +805,6 @@ void QNativeSocketEngine::close() } #endif // _MSC_VER >= 1900 - QMutexLocker locker(&d->readOperationsMutex); - for (ComPtr<IAsyncBufferOperation> readOp : d->pendingReadOps) { - ComPtr<IAsyncInfo> info; - hr = readOp.As(&info); - Q_ASSERT_SUCCEEDED(hr); - if (info) { - hr = info->Cancel(); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - } - locker.unlock(); - if (d->socketDescriptor != -1) { ComPtr<IClosable> socket; if (d->socketType == QAbstractSocket::TcpSocket) { @@ -730,14 +882,32 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) // happens and there isn't anything left in the buffer, we have to return -1 in order to signal // the closing of the socket. QMutexLocker mutexLocker(&d->readMutex); - if (d->readBytes.pos() == d->readBytes.size() && d->socketState != QAbstractSocket::ConnectedState) { + if (d->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) { close(); return -1; } - qint64 b = d->readBytes.read(data, maxlen); - d->bytesAvailable = d->readBytes.size() - d->readBytes.pos(); - return b; + QByteArray readData; + qint64 leftToMaxLen = maxlen; + while (leftToMaxLen > 0 && !d->pendingData.isEmpty()) { + QByteArray pendingData = d->pendingData.takeFirst(); + // Do not read the whole data. Put the rest of it back into the "queue" + if (leftToMaxLen < pendingData.length()) { + readData += pendingData.left(leftToMaxLen); + pendingData = pendingData.remove(0, maxlen); + d->pendingData.prepend(pendingData); + break; + } else { + readData += pendingData; + leftToMaxLen -= pendingData.length(); + } + } + const int copyLength = qMin(maxlen, qint64(readData.length())); + d->bytesAvailable -= copyLength; + mutexLocker.unlock(); + + memcpy(data, readData, copyLength); + return copyLength; } qint64 QNativeSocketEngine::write(const char *data, qint64 len) @@ -913,7 +1083,7 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) // If we are a client, we are ready to read if our buffer has data QMutexLocker locker(&d->readMutex); - if (!d->readBytes.atEnd()) + if (!d->pendingData.isEmpty()) return true; // Nothing to do, wait for more events @@ -1001,21 +1171,8 @@ void QNativeSocketEngine::establishRead() HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - ComPtr<IInputStream> stream; - HRESULT hr = d->tcpSocket()->get_InputStream(&stream); - RETURN_HR_IF_FAILED("establishRead(): Failed to get socket input stream"); - - ComPtr<IBuffer> buffer; - hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - RETURN_HR_IF_FAILED("establishRead(): Failed to create buffer"); - - ComPtr<IAsyncBufferOperation> readOp; - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, readOp.GetAddressOf()); - RETURN_HR_IF_FAILED("establishRead(): Failed to initiate socket read"); - QMutexLocker locker(&d->readOperationsMutex); - d->pendingReadOps.append(readOp); - hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); - RETURN_HR_IF_FAILED("establishRead(): Failed to register read callback"); + d->worker->setTcpSocket(d->tcpSocket()); + d->worker->startReading(); return S_OK; }); Q_ASSERT_SUCCEEDED(hr); @@ -1032,6 +1189,32 @@ void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagra emit readReady(); } +void QNativeSocketEngine::handleNewData(const QVector<QByteArray> &data) +{ + // Defer putting the data into the list until the next event loop iteration + // (where the readyRead signal is emitted as well) + QMetaObject::invokeMethod(this, "putIntoPendingData", Qt::QueuedConnection, + Q_ARG(QVector<QByteArray>, data)); +} + +void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error) +{ + Q_D(QNativeSocketEngine); + QNativeSocketEnginePrivate::ErrorString errorString; + switch (error) { + case QAbstractSocket::RemoteHostClosedError: + errorString = QNativeSocketEnginePrivate::RemoteHostClosedErrorString; + break; + default: + errorString = QNativeSocketEnginePrivate::UnknownSocketErrorString; + } + + d->setError(error, errorString); + d->socketState = QAbstractSocket::UnconnectedState; + if (d->notifyOnRead) + emit readReady(); +} + void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams) { Q_D(QNativeSocketEngine); @@ -1039,6 +1222,18 @@ void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram> d->pendingDatagrams.append(datagrams); } +void QNativeSocketEngine::putIntoPendingData(const QVector<QByteArray> &data) +{ + Q_D(QNativeSocketEngine); + QMutexLocker locker(&d->readMutex); + d->pendingData.append(data); + for (const QByteArray &newData : data) + d->bytesAvailable += newData.length(); + locker.unlock(); + if (d->notifyOnRead) + readNotification(); +} + bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) { Q_UNUSED(socketProtocol); @@ -1093,7 +1288,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , notifyOnException(false) , closingDown(false) , socketDescriptor(-1) - , worker(new SocketEngineWorker) + , worker(new SocketEngineWorker(this)) , sslSocket(Q_NULLPTR) , connectionToken( { -1 } ) { @@ -1481,109 +1676,6 @@ HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action return S_OK; } -HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) -{ - if (closingDown || wasDeleted || isDeletingChildren - || socketState == QAbstractSocket::UnconnectedState) { - return S_OK; - } - - Q_Q(QNativeSocketEngine); - QMutexLocker locker(&readOperationsMutex); - for (int i = 0; i < pendingReadOps.count(); ++i) { - if (pendingReadOps.at(i).Get() == asyncInfo) { - pendingReadOps.takeAt(i); - break; - } - } - locker.unlock(); - - // A read in UnconnectedState will close the socket and return -1 and thus tell the caller, - // that the connection was closed. The socket cannot be closed here, as the subsequent read - // might fail then. - if (status == Error || status == Canceled) { - setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); - socketState = QAbstractSocket::UnconnectedState; - if (notifyOnRead) - emit q->readReady(); - return S_OK; - } - - ComPtr<IBuffer> buffer; - HRESULT hr = asyncInfo->GetResults(&buffer); - RETURN_OK_IF_FAILED("Failed to get read results buffer"); - - UINT32 bufferLength; - hr = buffer->get_Length(&bufferLength); - Q_ASSERT_SUCCEEDED(hr); - // A zero sized buffer length signals, that the remote host closed the connection. The socket - // cannot be closed though, as the following read might have socket descriptor -1 and thus and - // the closing of the socket won't be communicated to the caller. So only the error is set. The - // actual socket close happens inside of read. - if (!bufferLength) { - setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); - socketState = QAbstractSocket::UnconnectedState; - if (notifyOnRead) - emit q->readReady(); - return S_OK; - } - - ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess; - hr = buffer.As(&byteArrayAccess); - Q_ASSERT_SUCCEEDED(hr); - byte *data; - hr = byteArrayAccess->Buffer(&data); - Q_ASSERT_SUCCEEDED(hr); - - QMutexLocker readLocker(&readMutex); - if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset - readBytes.close(); - if (!readBytes.isOpen()) - readBytes.open(QBuffer::ReadWrite|QBuffer::Truncate); - qint64 readPos = readBytes.pos(); - readBytes.seek(readBytes.size()); - Q_ASSERT(readBytes.atEnd()); - readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength)); - readBytes.seek(readPos); - bytesAvailable = readBytes.size() - readBytes.pos(); - readLocker.unlock(); - - if (notifyOnRead) - emit q->readReady(); - - hr = QEventDispatcherWinRT::runOnXamlThread([buffer, q, this]() { - UINT32 readBufferLength; - ComPtr<IInputStream> stream; - HRESULT hr = tcpSocket()->get_InputStream(&stream); - RETURN_HR_IF_FAILED("handleReadyRead(): Could not obtain input stream"); - - // Reuse the stream buffer - hr = buffer->get_Capacity(&readBufferLength); - RETURN_HR_IF_FAILED("handleReadyRead(): Could not obtain buffer capacity"); - hr = buffer->put_Length(0); - RETURN_HR_IF_FAILED("handleReadyRead(): Could not set buffer length"); - - ComPtr<IAsyncBufferOperation> readOp; - hr = stream->ReadAsync(buffer.Get(), readBufferLength, InputStreamOptions_Partial, &readOp); - if (FAILED(hr)) { - qErrnoWarning(hr, "handleReadyRead(): Could not read into socket stream buffer (%s).", - socketDescription(q).constData()); - return S_OK; - } - QMutexLocker locker(&readOperationsMutex); - pendingReadOps.append(readOp); - hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); - if (FAILED(hr)) { - qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).", - socketDescription(q).constData()); - return S_OK; - } - return S_OK; - }); - Q_ASSERT_SUCCEEDED(hr); - return S_OK; -} - HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args) { Q_Q(QNativeSocketEngine); diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 085704275c..9758310902 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -144,9 +144,12 @@ signals: private slots: void establishRead(); void handleNewDatagrams(const QList<WinRtDatagram> &datagram); + void handleNewData(const QVector<QByteArray> &data); + void handleTcpError(QAbstractSocket::SocketError error); private: Q_INVOKABLE void putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams); + Q_INVOKABLE void putIntoPendingData(const QVector<QByteArray> &data); Q_DECLARE_PRIVATE(QNativeSocketEngine) Q_DISABLE_COPY(QNativeSocketEngine) @@ -215,23 +218,17 @@ private: Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp; - // Protected by readOperationsMutex. Written in handleReadyRead (native callback) - QVector<Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32>>> pendingReadOps; - - // Protected by readMutex. Written in handleReadyRead (native callback) - QBuffer readBytes; - // In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is // pendingDatagrams. They are written inside native callbacks (handleReadyRead and // handleNewDatagrams/putIntoPendingDatagramsList) mutable QMutex readMutex; - // As pendingReadOps is changed inside handleReadyRead(native callback) it has to be protected - QMutex readOperationsMutex; - // Protected by readMutex. Written in handleReadyRead (native callback) QAtomicInteger<int> bytesAvailable; + // Protected by readMutex. Written in handleNewData/putIntoPendingData (native callback) + QVector<QByteArray> pendingData; + // Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList QList<WinRtDatagram> pendingDatagrams; @@ -246,7 +243,6 @@ private: HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); - HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus); }; QT_END_NAMESPACE diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.h b/src/platformheaders/nativecontexts/qeglnativecontext.h index 697b3ef3fd..eae74126fd 100644 --- a/src/platformheaders/nativecontexts/qeglnativecontext.h +++ b/src/platformheaders/nativecontexts/qeglnativecontext.h @@ -41,7 +41,8 @@ #define QEGLNATIVECONTEXT_H #include <QtCore/QMetaType> -#include <QtEglSupport/private/qt_egl_p.h> + +// Leave including egl.h with the appropriate defines to the client. QT_BEGIN_NAMESPACE diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc index e6a4048376..22e763ec24 100644 --- a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc +++ b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc @@ -36,6 +36,12 @@ that an application using it is only guaranteed to work with the Qt version it was developed against. + \note Due to being public while relying on otherwise hidden EGL types, this header + itself does not include \c{EGL/egl.h}. It is the application's responsibility to + include egl.h with any appropriate defines (for example, \c{MESA_EGL_NO_X11_HEADERS} + or other vendor-specific defines controlling the typedefs for EGL's native resources) + before this header. + \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle() */ diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index 6130107cc8..683b7f65ad 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -663,7 +663,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.glyphOffsets = &glyphOffset; QTransform xform = originalTransform; - if (fontDef.stretch != 100) + if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch) xform.scale(fontDef.stretch / 100.0, 1.0); DWRITE_MATRIX transform; @@ -933,7 +933,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph Q_UNUSED(format); QTransform matrix = originalTransform; - if (fontDef.stretch != 100) + if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch) matrix.scale(fontDef.stretch / 100.0, 1.0); glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance diff --git a/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java b/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java index 8170188ecb..805c90548b 100644 --- a/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java +++ b/src/plugins/bearer/android/jar/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java @@ -44,7 +44,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; -import android.app.Activity; import android.net.ConnectivityManager; public class QtNetworkReceiver @@ -65,29 +64,29 @@ public class QtNetworkReceiver private QtNetworkReceiver() {} - public static void registerReceiver(final Activity activity) + public static void registerReceiver(final Context context) { synchronized (m_lock) { if (m_broadcastReceiver == null) { m_broadcastReceiver = new BroadcastReceiverPrivate(); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - activity.registerReceiver(m_broadcastReceiver, intentFilter); + context.registerReceiver(m_broadcastReceiver, intentFilter); } } } - public static void unregisterReceiver(final Activity activity) + public static void unregisterReceiver(final Context context) { synchronized (m_lock) { if (m_broadcastReceiver == null) return; - activity.unregisterReceiver(m_broadcastReceiver); + context.unregisterReceiver(m_broadcastReceiver); } } - public static ConnectivityManager getConnectivityManager(final Activity activity) + public static ConnectivityManager getConnectivityManager(final Context context) { - return (ConnectivityManager)activity.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); + return (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); } } diff --git a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp index 3a5030d1f3..6787690246 100644 --- a/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp +++ b/src/plugins/bearer/android/src/wrappers/androidconnectivitymanager.cpp @@ -250,15 +250,15 @@ AndroidConnectivityManager::AndroidConnectivityManager() m_connectivityManager = QJNIObjectPrivate::callStaticObjectMethod(networkReceiverClass, "getConnectivityManager", - "(Landroid/app/Activity;)Landroid/net/ConnectivityManager;", - QtAndroidPrivate::activity()); + "(Landroid/content/Context;)Landroid/net/ConnectivityManager;", + QtAndroidPrivate::context()); if (!m_connectivityManager.isValid()) return; QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass, "registerReceiver", - "(Landroid/app/Activity;)V", - QtAndroidPrivate::activity()); + "(Landroid/content/Context;)V", + QtAndroidPrivate::context()); } AndroidConnectivityManager *AndroidConnectivityManager::getInstance() @@ -272,8 +272,8 @@ AndroidConnectivityManager::~AndroidConnectivityManager() { QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass, "unregisterReceiver", - "(Landroid/app/Activity;)V", - QtAndroidPrivate::activity()); + "(Landroid/content/Context;)V", + QtAndroidPrivate::context()); } AndroidNetworkInfo AndroidConnectivityManager::getActiveNetworkInfo() const diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index d89b8d398b..68619928d3 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -767,6 +767,10 @@ static bool readExifHeader(QDataStream &stream) */ static int getExifOrientation(QByteArray &exifData) { + // Current EXIF version (2.3) says there can be at most 5 IFDs, + // byte we allow for 10 so we're able to deal with future extensions. + const int maxIfdCount = 10; + QDataStream stream(&exifData, QIODevice::ReadOnly); if (!readExifHeader(stream)) @@ -774,7 +778,8 @@ static int getExifOrientation(QByteArray &exifData) quint16 val; quint32 offset; - const qint64 headerStart = stream.device()->pos(); + const qint64 headerStart = 6; // the EXIF header has a constant size + Q_ASSERT(headerStart == stream.device()->pos()); // read byte order marker stream >> val; @@ -785,7 +790,7 @@ static int getExifOrientation(QByteArray &exifData) else return -1; // unknown byte order - // read size + // confirm byte order stream >> val; if (val != 0x2a) return -1; @@ -793,18 +798,22 @@ static int getExifOrientation(QByteArray &exifData) stream >> offset; // read IFD - while (!stream.atEnd()) { + for (int n = 0; n < maxIfdCount; ++n) { quint16 numEntries; - // skip offset bytes to get the next IFD const qint64 bytesToSkip = offset - (stream.device()->pos() - headerStart); - - if (stream.skipRawData(bytesToSkip) != bytesToSkip) + if (bytesToSkip < 0 || (offset + headerStart >= exifData.size())) { + // disallow going backwards, though it's permitted in the spec return -1; + } else if (bytesToSkip != 0) { + // seek to the IFD + if (!stream.device()->seek(offset + headerStart)) + return -1; + } stream >> numEntries; - for (; numEntries > 0; --numEntries) { + for (; numEntries > 0 && stream.status() == QDataStream::Ok; --numEntries) { quint16 tag; quint16 type; quint32 components; @@ -828,12 +837,14 @@ static int getExifOrientation(QByteArray &exifData) // read offset to next IFD stream >> offset; + if (stream.status() != QDataStream::Ok) + return -1; if (offset == 0) // this is the last IFD - break; + return 0; // No Exif orientation was found } - // No Exif orientation was found - return 0; + // too many IFDs + return -1; } static QImageIOHandler::Transformations exif2Qt(int exifOrientation) diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index a987092862..3b1ce6d21d 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -54,7 +54,6 @@ static const char m_qtTag[] = "Qt A11Y"; static const char m_classErrorMsg[] = "Can't find class \"%s\""; -static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 5f05ab395e..d3bb089aa4 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -810,7 +810,7 @@ namespace QtAndroidInput #endif QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext(); if (inputContext && qGuiApp) - QMetaObject::invokeMethod(inputContext, "handleLocationChanged", + QMetaObject::invokeMethod(inputContext, "handleLocationChanged", Qt::BlockingQueuedConnection, Q_ARG(int, id), Q_ARG(int, x), Q_ARG(int, y)); } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index df8883ab34..1f681cc1a3 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -122,8 +122,6 @@ static int m_desktopHeightPixels = 0; static double m_scaledDensity = 0; static double m_density = 1.0; -static volatile bool m_pauseApplication; - static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr; diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 2656d45d5f..12e85046f8 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -578,6 +578,11 @@ void QAndroidInputContext::updateSelectionHandles() */ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) { + if (m_batchEditNestingLevel.load() || m_blockUpdateSelection) + return; + + finishComposingText(); + auto im = qGuiApp->inputMethod(); auto leftRect = im->cursorRectangle(); // The handle is down of the cursor, but we want the position in the middle. diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index ce0ec8724c..e7692bf720 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -152,7 +152,7 @@ private: CursorHandleShowPopup = 3 }; CursorHandleShowMode m_cursorHandleShown; - int m_batchEditNestingLevel; + QAtomicInt m_batchEditNestingLevel; QObject *m_focusObject; }; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 88ffd48538..e177a24e73 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -331,11 +331,12 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) { - item->nsItem().target = m_nativeMenu.delegate; - item->nsItem().action = @selector(itemFired:); + NSMenuItem *nativeItem = item->nsItem(); + nativeItem.target = m_nativeMenu.delegate; + nativeItem.action = @selector(itemFired:); // Someone's adding new items after aboutToShow() was emitted - if (isOpen() && item->menu() && item->nsItem()) - item->menu()->setAttachedItem(item->nsItem()); + if (isOpen() && nativeItem && item->menu()) + item->menu()->setAttachedItem(nativeItem); item->setParentEnabled(isEnabled()); @@ -348,15 +349,20 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) beforeItem = itemOrNull(m_menuItems.indexOf(beforeItem) + 1); } + if (nativeItem.menu) { + qWarning() << "Menu item" << item->text() << "already in menu" << QString::fromNSString(nativeItem.menu.title); + return; + } + if (beforeItem) { if (beforeItem->isMerged()) { qWarning("No non-merged before menu item found"); return; } - NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; - [m_nativeMenu insertItem: item->nsItem() atIndex: nativeIndex]; + const NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; + [m_nativeMenu insertItem:nativeItem atIndex:nativeIndex]; } else { - [m_nativeMenu addItem: item->nsItem()]; + [m_nativeMenu addItem:nativeItem]; } item->setMenuParent(this); } @@ -413,9 +419,8 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) return; } - bool wasMerged = cocoaItem->isMerged(); - NSMenu *oldMenu = wasMerged ? [[QCocoaMenuLoader sharedMenuLoader] applicationMenu] : m_nativeMenu; - NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem]; + const bool wasMerged = cocoaItem->isMerged(); + NSMenuItem *oldItem = cocoaItem->nsItem(); if (cocoaItem->sync() != oldItem) { // native item was changed for some reason diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index e32ff26ff5..21f2b4de85 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -288,7 +288,7 @@ NSMenuItem *QCocoaMenuItem::sync() } default: - qWarning() << "menu item" << m_text << "has unsupported role" << (int)m_role; + qWarning() << "Menu item" << m_text << "has unsupported role" << m_role; } if (mergeItem) { diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index 4e95aebe35..e500d8c419 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -3,7 +3,7 @@ TARGET = qdirectfb QT += \ core-private gui-private \ eventdispatcher_support-private service_support-private \ - fontdatabase_support-private egl_support-private + fontdatabase_support-private QMAKE_USE += directfb @@ -28,6 +28,7 @@ HEADERS = qdirectfbintegration.h \ # ### port the GL context contains(QT_CONFIG, directfb_egl) { + QT += egl_support-private HEADERS += qdirectfb_egl.h SOURCES += qdirectfb_egl.cpp DEFINES += DIRECTFB_GL_EGL diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index 52cc5739aa..aca0078bfb 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -2,8 +2,8 @@ TEMPLATE = subdirs QT_FOR_CONFIG += gui-private qtConfig(egl_x11): SUBDIRS += eglfs_x11 -qtConfig(eglfs_gbm): SUBDIRS += eglfs_kms_support eglfs_kms -qtConfig(eglfs_egldevice): SUBDIRS += eglfs_kms_support eglfs_kms_egldevice +qtConfig(eglfs_gbm): SUBDIRS *= eglfs_kms_support eglfs_kms +qtConfig(eglfs_egldevice): SUBDIRS *= eglfs_kms_support eglfs_kms_egldevice qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm qtConfig(eglfs_mali): SUBDIRS += eglfs_mali qtConfig(eglfs_viv): SUBDIRS += eglfs_viv diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp index 3ded96b9d6..977bbfd11b 100644 --- a/src/plugins/platforms/windows/qwin10helpers.cpp +++ b/src/plugins/platforms/windows/qwin10helpers.cpp @@ -44,7 +44,8 @@ #if defined(Q_CC_MINGW) # define HAS_UI_VIEW_SETTINGS_INTEROP -#elif !defined(Q_CC_MSVC) || _MSC_VER >= 1900 // MSVC2013 is lacking both +// Present from MSVC2015 + SDK 10 onwards +#elif (!defined(Q_CC_MSVC) || _MSC_VER >= 1900) && NTDDI_VERSION >= 0xa000000 # define HAS_UI_VIEW_SETTINGS_INTEROP # define HAS_UI_VIEW_SETTINGS #endif diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 6d4edcc8dc..f87ae9fd24 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -486,6 +486,9 @@ public: QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens; ComPtr<IApplicationView2> view2; #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + QAtomicPointer<QWinRTWindow> mouseGrabWindow; + QAtomicPointer<QWinRTWindow> keyboardGrabWindow; + QWindow *currentPressWindow = 0; }; // To be called from the XAML thread @@ -877,6 +880,44 @@ void QWinRTScreen::lower(QWindow *window) handleExpose(); } +bool QWinRTScreen::setMouseGrabWindow(QWinRTWindow *window, bool grab) +{ + Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window + << "(" << window->window()->objectName() << "):" << grab; + + if (!grab || window == nullptr) + d->mouseGrabWindow = nullptr; + else if (d->mouseGrabWindow != window) + d->mouseGrabWindow = window; + return grab; +} + +QWinRTWindow *QWinRTScreen::mouseGrabWindow() const +{ + Q_D(const QWinRTScreen); + return d->mouseGrabWindow; +} + +bool QWinRTScreen::setKeyboardGrabWindow(QWinRTWindow *window, bool grab) +{ + Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window + << "(" << window->window()->objectName() << "):" << grab; + + if (!grab || window == nullptr) + d->keyboardGrabWindow = nullptr; + else if (d->keyboardGrabWindow != window) + d->keyboardGrabWindow = window; + return grab; +} + +QWinRTWindow *QWinRTScreen::keyboardGrabWindow() const +{ + Q_D(const QWinRTScreen); + return d->keyboardGrabWindow; +} + void QWinRTScreen::updateWindowTitle(const QString &title) { Q_D(QWinRTScreen); @@ -1022,7 +1063,11 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args) pointerPoint->get_Position(&point); QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); - QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); + QWindow *targetWindow = topWindow(); + if (d->mouseGrabWindow) + targetWindow = d->mouseGrabWindow.load()->window(); + + QWindowSystemInterface::handleEnterEvent(targetWindow, pos, pos); } return S_OK; } @@ -1041,7 +1086,11 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args) d->touchPoints.remove(id); - QWindowSystemInterface::handleLeaveEvent(0); + QWindow *targetWindow = nullptr; + if (d->mouseGrabWindow) + targetWindow = d->mouseGrabWindow.load()->window(); + + QWindowSystemInterface::handleLeaveEvent(targetWindow); return S_OK; } @@ -1063,7 +1112,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) QPointF localPos = pos; const QPoint posPoint = pos.toPoint(); - QWindow *targetWindow = windowAt(posPoint); + QWindow *windowUnderPointer = windowAt(posPoint); + QWindow *targetWindow = windowUnderPointer; + + if (d->mouseGrabWindow) + targetWindow = d->mouseGrabWindow.load()->window(); + if (targetWindow) { const QPointF globalPosDelta = pos - posPoint; localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta; @@ -1127,6 +1181,22 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) if (isPressed) buttons |= Qt::XButton2; + // In case of a mouse grab we have to store the target of a press event + // to be able to send one additional release event to this target when the mouse + // button is released. This is a similar approach to AutoMouseCapture in the + // windows qpa backend. Otherwise the release might not be propagated and the original + // press event receiver considers a button to still be pressed, as in Qt Quick Controls 1 + // menus. + if (buttons != Qt::NoButton && d->currentPressWindow == nullptr && !d->mouseGrabWindow) + d->currentPressWindow = windowUnderPointer; + if (!isPressed && d->currentPressWindow && d->mouseGrabWindow) { + const QPointF globalPosDelta = pos - posPoint; + const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta; + + QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, buttons, mods); + d->currentPressWindow = nullptr; + } + QWindowSystemInterface::handleMouseEvent(targetWindow, localPos, pos, buttons, mods); break; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 2f1112472c..7dcdb98ead 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -83,6 +83,7 @@ class QTouchDevice; class QWinRTCursor; class QWinRTInputContext; class QWinRTScreenPrivate; +class QWinRTWindow; class QWinRTScreen : public QPlatformScreen { public: @@ -110,6 +111,12 @@ public: void raise(QWindow *window); void lower(QWindow *window); + bool setMouseGrabWindow(QWinRTWindow *window, bool grab); + QWinRTWindow* mouseGrabWindow() const; + + bool setKeyboardGrabWindow(QWinRTWindow *window, bool grab); + QWinRTWindow* keyboardGrabWindow() const; + void updateWindowTitle(const QString &title); ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 297e6618d1..8f3b86ff3b 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -191,6 +191,11 @@ QWinRTWindow::~QWinRTWindow() }); RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down"); + if (d->screen->mouseGrabWindow() == this) + d->screen->setMouseGrabWindow(this, false); + if (d->screen->keyboardGrabWindow() == this) + d->screen->setKeyboardGrabWindow(this, false); + d->screen->removeWindow(window()); if (!d->surface) @@ -384,6 +389,24 @@ void QWinRTWindow::setWindowState(Qt::WindowState state) d->state = state; } +bool QWinRTWindow::setMouseGrabEnabled(bool grab) +{ + Q_D(QWinRTWindow); + if (!isActive() && grab) { + qWarning("%s: Not setting mouse grab for invisible window %s/'%s'", + __FUNCTION__, window()->metaObject()->className(), + qPrintable(window()->objectName())); + return false; + } + return d->screen->setMouseGrabWindow(this, grab); +} + +bool QWinRTWindow::setKeyboardGrabEnabled(bool grab) +{ + Q_D(QWinRTWindow); + return d->screen->setKeyboardGrabWindow(this, grab); +} + EGLSurface QWinRTWindow::eglSurface() const { Q_D(const QWinRTWindow); diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 968edcfa85..26c2fa800d 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -70,6 +70,9 @@ public: qreal devicePixelRatio() const override; void setWindowState(Qt::WindowState state) override; + bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; + bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE; + EGLSurface eglSurface() const; void createEglSurface(EGLDisplay display, EGLConfig config); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 494cecb3d1..58fb1f3918 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1121,6 +1121,9 @@ void QXcbDrag::cancel() QBasicDrag::cancel(); if (current_target) send_leave(); + + // remove canceled object + currentDrag()->deleteLater(); } // find an ancestor with XdndAware on it diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5fa8541f26..ff01fa019e 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2738,7 +2738,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); if (!connection()->wmSupport()->isSupportedByWM(moveResize)) return false; - const QPoint globalPos = window()->mapToGlobal(pos); + const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen()); #ifdef XCB_USE_XINPUT22 if (connection()->startSystemResizeForTouchBegin(m_window, globalPos, corner)) return true; diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp index ba5089a8bc..699b058932 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp @@ -135,10 +135,12 @@ bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget); if (parent) { - GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow); - XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay), - gdk_x11_window_get_xid(gdkWindow), - parent->winId()); + if (GDK_IS_X11_WINDOW(gdkWindow)) { + GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow); + XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay), + gdk_x11_window_get_xid(gdkWindow), + parent->winId()); + } } if (modality != Qt::NonModal) { diff --git a/src/sql/configure.json b/src/sql/configure.json index 96c82e84f9..72671b6df9 100644 --- a/src/sql/configure.json +++ b/src/sql/configure.json @@ -58,8 +58,10 @@ "label": "MySQL", "test": "unix/mysql", "sources": [ - { "type": "mysqlConfig", "query": "--libs_r" }, - { "type": "mysqlConfig", "query": "--libs" }, + { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": true }, + { "type": "mysqlConfig", "query": "--libs", "cleanlibs": true }, + { "type": "mysqlConfig", "query": "--libs_r", "cleanlibs": false }, + { "type": "mysqlConfig", "query": "--libs", "cleanlibs": false }, { "libs": "-lmysqlclient_r", "condition": "!config.win32" }, { "libs": "-llibmysql", "condition": "config.win32" }, { "libs": "-lmysqlclient", "condition": "!config.win32" } diff --git a/src/sql/configure.pri b/src/sql/configure.pri index 1d8847b4bc..62d56e2186 100644 --- a/src/sql/configure.pri +++ b/src/sql/configure.pri @@ -57,6 +57,14 @@ defineTest(qtConfLibrary_mysqlConfig) { libs = $$filterLibraryPath($$libs) # -rdynamic should not be returned by mysql_config, but is on RHEL 6.6 libs -= -rdynamic + equals($${1}.cleanlibs, true) { + for(l, libs) { + # Drop all options besides the -L one and the -lmysqlclient one + # so we don't unnecessarily link to libs like OpenSSL + contains(l, "^(-L|-lmysqlclient).*"): cleanlibs += $$l + } + libs = $$cleanlibs + } $${1}.libs = "$$val_escape(libs)" eval(includedir = $$includedir) includedir ~= s/^-I//g diff --git a/src/src.pro b/src/src.pro index 13aa08c12a..9f3dbfa712 100644 --- a/src/src.pro +++ b/src/src.pro @@ -164,7 +164,7 @@ qtConfig(gui) { SUBDIRS += src_angle src_gui.depends += src_angle } - qtConfig(png) { + qtConfig(png):!qtConfig(system-png) { SUBDIRS += src_3rdparty_libpng src_3rdparty_freetype.depends += src_3rdparty_libpng src_gui.depends += src_3rdparty_libpng diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 55cf7ed872..6128d5490b 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -477,9 +477,6 @@ int runMoc(int argc, char **argv) } moc.symbols += pp.preprocessed(moc.filename, &in); - // We obviously do not support MS extensions - pp.macros.remove("_MSC_EXTENSIONS"); - if (!pp.preprocessOnly) { // 2. parse moc.parse(); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index c9cb826213..53cb21186f 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -219,8 +219,10 @@ QDockWidgetLayout::~QDockWidgetLayout() bool QDockWidgetLayout::nativeWindowDeco() const { bool floating = parentWidget()->isWindow(); - if (!floating && qobject_cast<QDockWidgetGroupWindow*>(parentWidget()->parentWidget())) - return wmSupportsNativeWindowDeco(); + if (!floating) { + if (auto groupWindow = qobject_cast<const QDockWidgetGroupWindow*>(parentWidget()->parentWidget())) + return groupWindow->hasNativeDecos(); + } return nativeWindowDeco(floating); } diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 8df197e05c..aef8b9cbd5 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -183,7 +183,7 @@ class QDockWidgetGroupLayout : public QLayout { QDockAreaLayoutInfo info; QWidgetResizeHandler *resizer; public: - QDockWidgetGroupLayout(QWidget* parent) : QLayout(parent) { + QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) { setSizeConstraint(QLayout::SetMinAndMaxSize); resizer = new QWidgetResizeHandler(parent); resizer->setMovingEnabled(false); @@ -221,7 +221,7 @@ public: } void setGeometry(const QRect&r) Q_DECL_OVERRIDE { - static_cast<QDockWidgetGroupWindow *>(parent())->destroyOrHideIfEmpty(); + groupWindow()->destroyOrHideIfEmpty(); QDockAreaLayoutInfo *li = layoutInfo(); if (li->isEmpty()) return; @@ -239,7 +239,7 @@ public: bool nativeWindowDeco() const { - return QDockWidgetLayout::wmSupportsNativeWindowDeco(); + return groupWindow()->hasNativeDecos(); } int frameWidth() const @@ -247,6 +247,11 @@ public: return nativeWindowDeco() ? 0 : parentWidget()->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, parentWidget()); } + + QDockWidgetGroupWindow *groupWindow() const + { + return static_cast<QDockWidgetGroupWindow *>(parent()); + } }; bool QDockWidgetGroupWindow::event(QEvent *e) @@ -390,16 +395,49 @@ void QDockWidgetGroupWindow::adjustFlags() flags.setFlag(Qt::WindowCloseButtonHint, top->features() & QDockWidget::DockWidgetClosable); flags &= ~Qt::FramelessWindowHint; } else { + flags &= ~(Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint | Qt::WindowTitleHint); flags |= Qt::FramelessWindowHint; } + if (oldFlags != flags) { setWindowFlags(flags); + const bool gainedNativeDecos = (oldFlags & Qt::FramelessWindowHint) && !(flags & Qt::FramelessWindowHint); + const bool lostNativeDecos = !(oldFlags & Qt::FramelessWindowHint) && (flags & Qt::FramelessWindowHint); + + // Adjust the geometry after gaining/losing decos, so that the client area appears always + // at the same place when tabbing + if (lostNativeDecos) { + QRect newGeometry = geometry(); + newGeometry.setTop(frameGeometry().top()); + const int bottomFrame = geometry().top() - frameGeometry().top(); + m_removedFrameSize = QSize((frameSize() - size()).width(), bottomFrame); + setGeometry(newGeometry); + } else if (gainedNativeDecos && m_removedFrameSize.isValid()) { + QRect r = geometry(); + r.adjust(-m_removedFrameSize.width() / 2, 0, + -m_removedFrameSize.width() / 2, -m_removedFrameSize.height()); + setGeometry(r); + m_removedFrameSize = QSize(); + } + show(); // setWindowFlags hides the window } setWindowTitle(top->windowTitle()); setWindowIcon(top->windowIcon()); } + +bool QDockWidgetGroupWindow::hasNativeDecos() const +{ + if (!QDockWidgetLayout::wmSupportsNativeWindowDeco()) + return false; + + if (QDockWidget *dw = topDockWidget()) + return dw->titleBarWidget() == nullptr; + + return true; +} + #endif /****************************************************************************** @@ -1704,6 +1742,9 @@ void QMainWindowLayout::tabChanged() if (activated) emit static_cast<QMainWindow *>(parentWidget())->tabifiedDockWidgetActivated(activated); + if (auto dwgw = qobject_cast<QDockWidgetGroupWindow*>(tb->parentWidget())) + dwgw->adjustFlags(); + if (QWidget *w = centralWidget()) w->raise(); } diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index 6e8b965431..40336caeba 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -83,9 +83,14 @@ public: QDockWidget *topDockWidget() const; void destroyOrHideIfEmpty(); void adjustFlags(); + bool hasNativeDecos() const; + protected: bool event(QEvent *) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE; + +private: + QSize m_removedFrameSize; }; // This item will be used in the layout for the gap item. We cannot use QWidgetItem directly diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_back_pointers.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_back_pointers.jpg Binary files differnew file mode 100644 index 0000000000..164d3080a3 --- /dev/null +++ b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_back_pointers.jpg diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_past_end.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_past_end.jpg Binary files differnew file mode 100644 index 0000000000..7e2451e6f9 --- /dev/null +++ b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_past_end.jpg diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_ifds.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_ifds.jpg Binary files differnew file mode 100644 index 0000000000..52c6a93f08 --- /dev/null +++ b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_ifds.jpg diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_tags.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_tags.jpg Binary files differnew file mode 100644 index 0000000000..6a080aada7 --- /dev/null +++ b/tests/auto/gui/image/qimage/images/jpeg_exif_invalid_data_too_many_tags.jpg diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 9b5477a06a..65ee4a2188 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -188,7 +188,8 @@ private slots: void exifOrientation(); void exif_QTBUG45865(); - void exif_invalid_data_QTBUG46870(); + void exifInvalidData_data(); + void exifInvalidData(); void cleanupFunctions(); @@ -3025,10 +3026,20 @@ void tst_QImage::exif_QTBUG45865() QCOMPARE(image.size(), QSize(5, 8)); } -void tst_QImage::exif_invalid_data_QTBUG46870() +void tst_QImage::exifInvalidData_data() +{ + QTest::addColumn<bool>("$never used"); + QTest::newRow("QTBUG-46870"); + QTest::newRow("back_pointers"); + QTest::newRow("past_end"); + QTest::newRow("too_many_ifds"); + QTest::newRow("too_many_tags"); +} + +void tst_QImage::exifInvalidData() { QImage image; - QVERIFY(image.load(m_prefix + "jpeg_exif_invalid_data_QTBUG-46870.jpg")); + QVERIFY(image.load(m_prefix + "jpeg_exif_invalid_data_" + QTest::currentDataTag() + ".jpg")); QVERIFY(!image.isNull()); } diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index a3de9ee5b5..ec143896ab 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -195,6 +195,7 @@ public: private slots: void cleanup(); + void qPointerUniqueId(); void touchDisabledByDefault(); void touchEventAcceptedByDefault(); void touchBeginPropagatesWhenIgnored(); @@ -226,6 +227,44 @@ void tst_QTouchEvent::cleanup() QVERIFY(QGuiApplication::topLevelWindows().isEmpty()); } +void tst_QTouchEvent::qPointerUniqueId() +{ + QPointingDeviceUniqueId id1, id2; + + QCOMPARE(id1.numericId(), Q_INT64_C(-1)); + QVERIFY(!id1.isValid()); + + QVERIFY( id1 == id2); + QVERIFY(!(id1 != id2)); + + QSet<QPointingDeviceUniqueId> set; // compile test + set.insert(id1); + set.insert(id2); + QCOMPARE(set.size(), 1); + + + const auto id3 = QPointingDeviceUniqueId::fromNumericId(-1); + QCOMPARE(id3.numericId(), Q_INT64_C(-1)); + QVERIFY(!id3.isValid()); + + QVERIFY( id1 == id3); + QVERIFY(!(id1 != id3)); + + set.insert(id3); + QCOMPARE(set.size(), 1); + + + const auto id4 = QPointingDeviceUniqueId::fromNumericId(4); + QCOMPARE(id4.numericId(), Q_INT64_C(4)); + QVERIFY(id4.isValid()); + + QVERIFY( id1 != id4); + QVERIFY(!(id1 == id4)); + + set.insert(id4); + QCOMPARE(set.size(), 2); +} + void tst_QTouchEvent::touchDisabledByDefault() { // QWidget diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 419c781aab..364e435d3d 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -46,6 +46,8 @@ # include <netinet/in.h> #endif +Q_DECLARE_METATYPE(QHostAddress::SpecialAddress) + class tst_QHostAddress : public QObject { Q_OBJECT @@ -232,51 +234,55 @@ void tst_QHostAddress::setAddress_QString() void tst_QHostAddress::specialAddresses_data() { QTest::addColumn<QString>("text"); - QTest::addColumn<int>("address"); + QTest::addColumn<QHostAddress::SpecialAddress>("address"); QTest::addColumn<bool>("result"); - QTest::newRow("localhost_1") << QString("127.0.0.1") << (int)QHostAddress::LocalHost << true; - QTest::newRow("localhost_2") << QString("127.0.0.2") << (int)QHostAddress::LocalHost << false; - QTest::newRow("localhost_3") << QString("127.0.0.2") << (int)QHostAddress::LocalHostIPv6 << false; + QTest::newRow("localhost_1") << QString("127.0.0.1") << QHostAddress::LocalHost << true; + QTest::newRow("localhost_2") << QString("127.0.0.2") << QHostAddress::LocalHost << false; + QTest::newRow("localhost_3") << QString("127.0.0.2") << QHostAddress::LocalHostIPv6 << false; - QTest::newRow("localhost_ipv6_4") << QString("::1") << (int)QHostAddress::LocalHostIPv6 << true; - QTest::newRow("localhost_ipv6_5") << QString("::2") << (int)QHostAddress::LocalHostIPv6 << false; - QTest::newRow("localhost_ipv6_6") << QString("::1") << (int)QHostAddress::LocalHost << false; + QTest::newRow("localhost_ipv6_4") << QString("::1") << QHostAddress::LocalHostIPv6 << true; + QTest::newRow("localhost_ipv6_5") << QString("::2") << QHostAddress::LocalHostIPv6 << false; + QTest::newRow("localhost_ipv6_6") << QString("::1") << QHostAddress::LocalHost << false; - QTest::newRow("null_1") << QString("") << (int)QHostAddress::Null << true; - QTest::newRow("null_2") << QString("bjarne") << (int)QHostAddress::Null << true; + QTest::newRow("null_1") << QString("") << QHostAddress::Null << true; + QTest::newRow("null_2") << QString("bjarne") << QHostAddress::Null << true; - QTest::newRow("compare_from_null") << QString("") << (int)QHostAddress::Broadcast << false; + QTest::newRow("compare_from_null") << QString("") << QHostAddress::Broadcast << false; - QTest::newRow("broadcast_1") << QString("255.255.255.255") << (int)QHostAddress::Any << false; - QTest::newRow("broadcast_2") << QString("255.255.255.255") << (int)QHostAddress::Broadcast << true; + QTest::newRow("broadcast_1") << QString("255.255.255.255") << QHostAddress::Any << false; + QTest::newRow("broadcast_2") << QString("255.255.255.255") << QHostAddress::Broadcast << true; - QTest::newRow("any_ipv6") << QString("::") << (int)QHostAddress::AnyIPv6 << true; - QTest::newRow("any_ipv4") << QString("0.0.0.0") << (int)QHostAddress::AnyIPv4 << true; + QTest::newRow("any_ipv6") << QString("::") << QHostAddress::AnyIPv6 << true; + QTest::newRow("any_ipv4") << QString("0.0.0.0") << QHostAddress::AnyIPv4 << true; - QTest::newRow("dual_not_ipv6") << QString("::") << (int)QHostAddress::Any << false; - QTest::newRow("dual_not_ipv4") << QString("0.0.0.0") << (int)QHostAddress::Any << false; + QTest::newRow("dual_not_ipv6") << QString("::") << QHostAddress::Any << false; + QTest::newRow("dual_not_ipv4") << QString("0.0.0.0") << QHostAddress::Any << false; } void tst_QHostAddress::specialAddresses() { QFETCH(QString, text); - QFETCH(int, address); + QFETCH(QHostAddress::SpecialAddress, address); QFETCH(bool, result); - QVERIFY((QHostAddress(text) == (QHostAddress::SpecialAddress)address) == result); + QCOMPARE(QHostAddress(text) == address, result); //check special address equal to itself (QTBUG-22898), note two overloads of operator== - QVERIFY(QHostAddress((QHostAddress::SpecialAddress)address) == QHostAddress((QHostAddress::SpecialAddress)address)); - QVERIFY(QHostAddress((QHostAddress::SpecialAddress)address) == (QHostAddress::SpecialAddress)address); + QVERIFY(QHostAddress(address) == QHostAddress(address)); + QVERIFY(QHostAddress(address) == address); + QVERIFY(!(QHostAddress(address) != QHostAddress(address))); + QVERIFY(!(QHostAddress(address) != address)); + + { + QHostAddress ha; + ha.setAddress(address); + QVERIFY(ha == address); + } QHostAddress setter; setter.setAddress(text); - if (result) { - QVERIFY(setter == (QHostAddress::SpecialAddress) address); - } else { - QVERIFY(!((QHostAddress::SpecialAddress) address == setter)); - } + QCOMPARE(setter == address, result); } @@ -359,6 +365,11 @@ void tst_QHostAddress::isEqual() QCOMPARE(second.isEqual(first, QHostAddress::ConversionModeFlag(flags)), result); } +QT_WARNING_PUSH +#ifdef QT_WARNING_DISABLE_DEPRECATED +QT_WARNING_DISABLE_DEPRECATED +#endif + void tst_QHostAddress::assignment() { QHostAddress address; @@ -379,6 +390,8 @@ void tst_QHostAddress::assignment() #endif // !Q_OS_WINRT } +QT_WARNING_POP + void tst_QHostAddress::scopeId() { QHostAddress address("fe80::2e0:4cff:fefb:662a%eth0"); diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index e3be294e5f..4e215b8570 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -633,6 +633,31 @@ void tst_qmakelib::addControlStructs() << "" << true; + QTest::newRow("bypassNesting()") + << "defineTest(func) {\n" + "LOCAL = 1\n" + "bypassNesting() {\n" + "OUT = 1\n" + "!isEmpty(GLOBAL): OUT1 = 1\n" + "!isEmpty(LOCAL): OUT2 = 1\n" + "}\n" + "}\n" + "GLOBAL = 1\n" + "func()" + << "GLOBAL = 1\nLOCAL = UNDEF\nOUT = 1\nOUT1 = 1\nOUT2 = UNDEF" + << "" + << true; + + QTest::newRow("error() from bypassNesting()") + << "defineTest(func) {\n" + "bypassNesting() { error(error) }\n" + "}\n" + "func()\n" + "OKE = 1" + << "OKE = UNDEF" + << "Project ERROR: error" + << false; + QTest::newRow("top-level return()") << "VAR = good\nreturn()\nVAR = bad" << "VAR = good" diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp index dc92f98f45..70f1be5fc3 100644 --- a/tests/auto/tools/qmakelib/parsertest.cpp +++ b/tests/auto/tools/qmakelib/parsertest.cpp @@ -1684,6 +1684,57 @@ void tst_qmakelib::addParseCustomFunctions() /* 22 */ << H(TokTerminator)) << "" << true; + + QTest::newRow("bypassNesting()-{return}") + << "defineTest(test) { bypassNesting() { return(true) } }" + << TS( + /* 0 */ << H(TokLine) << H(1) + /* 2 */ << H(TokTestDef) << HS(L"test") + /* 10 */ /* body */ << I(16) + /* 12 */ << H(TokLine) << H(1) + /* 14 */ << H(TokBypassNesting) + /* 15 */ /* block */ << I(10) + /* 17 */ << H(TokLine) << H(1) + /* 19 */ << H(TokLiteral | TokNewStr) << S(L"true") + /* 25 */ << H(TokReturn) + /* 26 */ << H(TokTerminator) + /* 27 */ << H(TokTerminator)) + << "" + << true; + + QTest::newRow("test-AND-bypassNesting()-{}") + << "defineTest(test) { test: bypassNesting() {} }" + << TS( + /* 0 */ << H(TokLine) << H(1) + /* 2 */ << H(TokTestDef) << HS(L"test") + /* 10 */ /* body */ << I(17) + /* 12 */ << H(TokLine) << H(1) + /* 14 */ << H(TokHashLiteral) << HS(L"test") + /* 22 */ << H(TokCondition) + /* 23 */ << H(TokAnd) + /* 24 */ << H(TokBypassNesting) + /* 25 */ /* block */ << I(1) + /* 27 */ << H(TokTerminator) + /* 28 */ << H(TokTerminator)) + << "" + << true; + + QTest::newRow("test-OR-bypassNesting()-{}") + << "defineTest(test) { test| bypassNesting() {} }" + << TS( + /* 0 */ << H(TokLine) << H(1) + /* 2 */ << H(TokTestDef) << HS(L"test") + /* 10 */ /* body */ << I(17) + /* 12 */ << H(TokLine) << H(1) + /* 14 */ << H(TokHashLiteral) << HS(L"test") + /* 22 */ << H(TokCondition) + /* 23 */ << H(TokOr) + /* 24 */ << H(TokBypassNesting) + /* 25 */ /* block */ << I(1) + /* 27 */ << H(TokTerminator) + /* 28 */ << H(TokTerminator)) + << "" + << true; } void tst_qmakelib::addParseAbuse() @@ -1736,6 +1787,24 @@ void tst_qmakelib::addParseAbuse() << "in:1: Unexpected NOT operator in front of function definition." << false; + QTest::newRow("outer-bypassNesting()-{}") + << "bypassNesting() {}" + << TS() + << "in:1: Unexpected bypassNesting()." + << false; + + QTest::newRow("bypassNesting(arg)-{}") + << "defineTest(test) { bypassNesting(arg) {} }" + << TS() + << "in:1: bypassNesting() requires zero arguments." + << false; + + QTest::newRow("NOT-bypassNesting()-{}") + << "defineTest(test) { !bypassNesting() {} }" + << TS() + << "in:1: Unexpected NOT operator in front of bypassNesting()." + << false; + QTest::newRow("AND-test") << ":test" << TS( diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index 2d335c532a..434876eb3c 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -133,6 +133,7 @@ private slots: void taskQTBUG53205_crashReparentNested(); #ifdef Q_OS_MACOS void taskQTBUG56275_reinsertMenuInParentlessQMenuBar(); + void QTBUG_57404_existingMenuItemException(); #endif void taskQTBUG55966_subMenuRemoved(); @@ -1581,6 +1582,31 @@ void tst_QMenuBar::taskQTBUG56275_reinsertMenuInParentlessQMenuBar() QVERIFY(tst_qmenubar_taskQTBUG56275(&menubar)); } + +void tst_QMenuBar::QTBUG_57404_existingMenuItemException() +{ + QMainWindow mw1; + QMainWindow mw2; + mw1.show(); + mw2.show(); + + QMenuBar *mb = new QMenuBar(&mw1); + mw1.setMenuBar(mb); + mb->show(); + QMenu *editMenu = new QMenu(QLatin1String("Edit"), &mw1); + mb->addMenu(editMenu); + QAction *copyAction = editMenu->addAction("&Copy"); + copyAction->setShortcut(QKeySequence("Ctrl+C")); + QTest::ignoreMessage(QtWarningMsg, "Menu item \"&Copy\" has unsupported role QPlatformMenuItem::MenuRole(NoRole)"); + copyAction->setMenuRole(QAction::NoRole); + + QVERIFY(QTest::qWaitForWindowExposed(&mw2)); + QTest::qWait(100); + mw2.close(); + mw1.activateWindow(); + QTest::qWait(100); + // No crash, all fine. Ideally, there should be only one warning. +} #endif // Q_OS_MACOS void tst_QMenuBar::taskQTBUG55966_subMenuRemoved() diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 2fe96c2f93..8367994509 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -1,4 +1,5 @@ TEMPLATE=subdirs +QT_FOR_CONFIG += network-private gui-private SUBDIRS = bearerex \ filetest \ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index fc66220335..2ffec0707f 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -48,14 +48,6 @@ QT_BEGIN_NAMESPACE -enum Platforms { - WINDOWS, - WINDOWS_RT, - QNX, - ANDROID, - OTHER -}; - std::ostream &operator<<(std::ostream &s, const QString &val) { s << val.toLocal8Bit().data(); return s; @@ -84,20 +76,12 @@ Configure::Configure(int& argc, char** argv) sourceDir = sourcePathInfo.dir(); } buildPath = QDir::currentPath(); -#if 0 - const QString installPath = QString("C:\\Qt\\%1").arg(QT_VERSION_STR); -#else - const QString installPath = buildPath; -#endif if (sourceDir != buildDir) { //shadow builds! QDir(buildPath).mkpath("bin"); buildDir.mkpath("mkspecs"); - buildDir.mkpath("config.tests"); } - dictionary[ "QT_INSTALL_PREFIX" ] = installPath; - if (dictionary[ "QMAKESPEC" ].size() == 0) { dictionary[ "QMAKESPEC" ] = Environment::detectQMakeSpec(); dictionary[ "QMAKESPEC_FROM" ] = "detected"; @@ -105,13 +89,6 @@ Configure::Configure(int& argc, char** argv) dictionary[ "SYNCQT" ] = "auto"; - //Only used when cross compiling. - dictionary[ "QT_INSTALL_SETTINGS" ] = "/etc/xdg"; - - dictionary[ "REDO" ] = "no"; - - dictionary[ "BUILDTYPE" ] = "none"; - QString tmp = dictionary[ "QMAKESPEC" ]; if (tmp.contains("\\")) { tmp = tmp.mid(tmp.lastIndexOf("\\") + 1); @@ -125,17 +102,6 @@ Configure::~Configure() { } -QString Configure::formatPath(const QString &path) -{ - QString ret = QDir::cleanPath(path); - // This amount of quoting is deemed sufficient. - if (ret.contains(QLatin1Char(' '))) { - ret.prepend(QLatin1Char('"')); - ret.append(QLatin1Char('"')); - } - return ret; -} - void Configure::parseCmdLine() { sourcePathMangled = sourcePath; @@ -146,6 +112,7 @@ void Configure::parseCmdLine() sourcePathMangled = QFileInfo(sourcePath).path(); buildPathMangled = QFileInfo(buildPath).path(); } + qmakeCmdLine = configCmdLine; int argCount = configCmdLine.size(); int i = 0; @@ -153,7 +120,6 @@ void Configure::parseCmdLine() // Look first for -redo for (int k = 0 ; k < argCount; ++k) { if (configCmdLine.at(k) == "-redo") { - dictionary["REDO"] = "yes"; configCmdLine.removeAt(k); if (!reloadCmdLine(k)) { dictionary["DONE"] = "error"; @@ -164,196 +130,18 @@ void Configure::parseCmdLine() } } - // Then look for XQMAKESPEC - bool isDeviceMkspec = false; - for (int j = 0 ; j < argCount; ++j) - { - if ((configCmdLine.at(j) == "-xplatform") || (configCmdLine.at(j) == "-device")) { - isDeviceMkspec = (configCmdLine.at(j) == "-device"); - ++j; - if (j == argCount) - break; - dictionary["XQMAKESPEC"] = configCmdLine.at(j); - break; - } - } - for (; i<configCmdLine.size(); ++i) { - if (configCmdLine.at(i) == "-opensource") { - dictionary[ "BUILDTYPE" ] = "opensource"; - } - else if (configCmdLine.at(i) == "-commercial") { - dictionary[ "BUILDTYPE" ] = "commercial"; - } - else if (configCmdLine.at(i) == "-platform") { + if (configCmdLine.at(i) == "-platform") { ++i; if (i == argCount) break; dictionary[ "QMAKESPEC" ] = configCmdLine.at(i); dictionary[ "QMAKESPEC_FROM" ] = "commandline"; - } else if (configCmdLine.at(i) == "-xplatform" - || configCmdLine.at(i) == "-device") { - ++i; - // do nothing - } else if (configCmdLine.at(i) == "-device-option") { - ++i; - const QString option = configCmdLine.at(i); - QString &devOpt = dictionary["DEVICE_OPTION"]; - if (!devOpt.isEmpty()) - devOpt.append("\n").append(option); - else - devOpt = option; } else if (configCmdLine.at(i) == "-no-syncqt") dictionary[ "SYNCQT" ] = "no"; - else if (configCmdLine.at(i) == "-confirm-license") { - dictionary["LICENSE_CONFIRMED"] = "yes"; - } - - // Directories ---------------------------------------------- - else if (configCmdLine.at(i) == "-prefix") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_PREFIX" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-bindir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_BINS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-libexecdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_LIBEXECS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-libdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_LIBS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-docdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_DOCS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-headerdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_HEADERS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-plugindir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_PLUGINS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-importdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_IMPORTS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-qmldir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_QML" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-archdatadir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_ARCHDATA" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-datadir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_DATA" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-translationdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_TRANSLATIONS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-examplesdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_EXAMPLES" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-testsdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_INSTALL_TESTS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-sysroot") { - ++i; - if (i == argCount) - break; - dictionary[ "CFG_SYSROOT" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-hostprefix") { - ++i; - if (i == argCount || configCmdLine.at(i).startsWith('-')) - dictionary[ "QT_HOST_PREFIX" ] = buildPath; - else - dictionary[ "QT_HOST_PREFIX" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-hostbindir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_HOST_BINS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-hostlibdir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_HOST_LIBS" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-hostdatadir") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_HOST_DATA" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-extprefix") { - ++i; - if (i == argCount) - break; - dictionary[ "QT_EXT_PREFIX" ] = configCmdLine.at(i); - } - else if (configCmdLine.at(i) == "-make-tool") { ++i; if (i == argCount) @@ -361,54 +149,6 @@ void Configure::parseCmdLine() dictionary[ "MAKE" ] = configCmdLine.at(i); } - else if (configCmdLine.at(i) == "-sysconfdir") { - ++i; - if (i == argCount) - break; - dictionary["QT_INSTALL_SETTINGS"] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-ndk") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_NDK_ROOT" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-sdk") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_SDK_ROOT" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-ndk-platform") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_PLATFORM" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-ndk-host") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_HOST" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-arch") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_TARGET_ARCH" ] = configCmdLine.at(i); - } - - else if (configCmdLine.at(i) == "-android-toolchain-version") { - ++i; - if (i == argCount) - break; - dictionary[ "ANDROID_NDK_TOOLCHAIN_VERSION" ] = configCmdLine.at(i); - } } // Ensure that QMAKESPEC exists in the mkspecs folder @@ -449,95 +189,6 @@ void Configure::parseCmdLine() dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32"; } } - - if (isDeviceMkspec) { - const QStringList devices = mkspecs.filter("devices/", Qt::CaseInsensitive); - const QStringList family = devices.filter(dictionary["XQMAKESPEC"], Qt::CaseInsensitive); - - if (family.isEmpty()) { - dictionary[ "DONE" ] = "error"; - cout << "Error: No device matching '" << dictionary["XQMAKESPEC"] << "'." << endl; - } else if (family.size() > 1) { - dictionary[ "DONE" ] = "error"; - - cout << "Error: Multiple matches for device '" << dictionary["XQMAKESPEC"] << "'. Candidates are:" << endl; - - foreach (const QString &device, family) - cout << "\t* " << device << endl; - } else { - Q_ASSERT(family.size() == 1); - dictionary["XQMAKESPEC"] = family.at(0); - } - - } else { - // Ensure that -spec (XQMAKESPEC) exists in the mkspecs folder as well - if (dictionary.contains("XQMAKESPEC") && - !mkspecs.contains(dictionary["XQMAKESPEC"], Qt::CaseInsensitive)) { - dictionary[ "DONE" ] = "error"; - cout << "Invalid option \"" << dictionary["XQMAKESPEC"] << "\" for -xplatform." << endl; - } - } -} - -void Configure::prepareConfigTests() -{ - // Generate an empty .qmake.cache file for config.tests - QDir buildDir(buildPath); - bool success = true; - if (!buildDir.exists("config.tests")) - success = buildDir.mkdir("config.tests"); - - QString fileName(buildPath + "/config.tests/.qmake.cache"); - QFile cacheFile(fileName); - success &= cacheFile.open(QIODevice::WriteOnly); - cacheFile.close(); - - if (!success) { - cout << "Failed to create file " << qPrintable(QDir::toNativeSeparators(fileName)) << endl; - dictionary[ "DONE" ] = "error"; - } -} - -void Configure::generateQDevicePri() -{ - FileWriter deviceStream(buildPath + "/mkspecs/qdevice.pri"); - if (dictionary.contains("DEVICE_OPTION")) { - const QString devoptionlist = dictionary["DEVICE_OPTION"]; - const QStringList optionlist = devoptionlist.split(QStringLiteral("\n")); - foreach (const QString &entry, optionlist) - deviceStream << entry << "\n"; - } - if (dictionary.contains("ANDROID_SDK_ROOT") && dictionary.contains("ANDROID_NDK_ROOT")) { - deviceStream << "android_install {" << endl; - deviceStream << " DEFAULT_ANDROID_SDK_ROOT = " << formatPath(dictionary["ANDROID_SDK_ROOT"]) << endl; - deviceStream << " DEFAULT_ANDROID_NDK_ROOT = " << formatPath(dictionary["ANDROID_NDK_ROOT"]) << endl; - if (dictionary.contains("ANDROID_HOST")) - deviceStream << " DEFAULT_ANDROID_NDK_HOST = " << dictionary["ANDROID_HOST"] << endl; - else if (QSysInfo::WordSize == 64) - deviceStream << " DEFAULT_ANDROID_NDK_HOST = windows-x86_64" << endl; - else - deviceStream << " DEFAULT_ANDROID_NDK_HOST = windows" << endl; - QString android_arch(dictionary.contains("ANDROID_TARGET_ARCH") - ? dictionary["ANDROID_TARGET_ARCH"] - : QString("armeabi-v7a")); - QString android_tc_vers(dictionary.contains("ANDROID_NDK_TOOLCHAIN_VERSION") - ? dictionary["ANDROID_NDK_TOOLCHAIN_VERSION"] - : QString("4.9")); - - bool targetIs64Bit = android_arch == QString("arm64-v8a") - || android_arch == QString("x86_64") - || android_arch == QString("mips64"); - QString android_platform(dictionary.contains("ANDROID_PLATFORM") - ? dictionary["ANDROID_PLATFORM"] - : (targetIs64Bit ? QString("android-21") : QString("android-9"))); - - deviceStream << " DEFAULT_ANDROID_PLATFORM = " << android_platform << endl; - deviceStream << " DEFAULT_ANDROID_TARGET_ARCH = " << android_arch << endl; - deviceStream << " DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION = " << android_tc_vers << endl; - deviceStream << "}" << endl; - } - if (!deviceStream.flush()) - dictionary[ "DONE" ] = "error"; } void Configure::generateHeaders() @@ -565,219 +216,6 @@ void Configure::generateHeaders() } } -void Configure::addConfStr(int group, const QString &val) -{ - confStrOffsets[group] += ' ' + QString::number(confStringOff) + ','; - confStrings[group] += " \"" + val + "\\0\"\n"; - confStringOff += val.length() + 1; -} - -void Configure::generateQConfigCpp() -{ - QString hostSpec = dictionary["QMAKESPEC"]; - QString targSpec = dictionary.contains("XQMAKESPEC") ? dictionary["XQMAKESPEC"] : hostSpec; - - dictionary["CFG_SYSROOT"] = QDir::cleanPath(dictionary["CFG_SYSROOT"]); - - bool qipempty = false; - if (dictionary["QT_INSTALL_PREFIX"].isEmpty()) - qipempty = true; - else - dictionary["QT_INSTALL_PREFIX"] = QDir::cleanPath(dictionary["QT_INSTALL_PREFIX"]); - - bool sysrootifyPrefix; - if (dictionary["QT_EXT_PREFIX"].isEmpty()) { - dictionary["QT_EXT_PREFIX"] = dictionary["QT_INSTALL_PREFIX"]; - sysrootifyPrefix = !dictionary["CFG_SYSROOT"].isEmpty(); - } else { - dictionary["QT_EXT_PREFIX"] = QDir::cleanPath(dictionary["QT_EXT_PREFIX"]); - sysrootifyPrefix = false; - } - - bool haveHpx; - if (dictionary["QT_HOST_PREFIX"].isEmpty()) { - dictionary["QT_HOST_PREFIX"] = (sysrootifyPrefix ? dictionary["CFG_SYSROOT"] : QString()) - + dictionary["QT_INSTALL_PREFIX"]; - haveHpx = false; - } else { - dictionary["QT_HOST_PREFIX"] = QDir::cleanPath(dictionary["QT_HOST_PREFIX"]); - haveHpx = true; - } - - static const struct { - const char *basevar, *baseoption, *var, *option; - } varmod[] = { - { "INSTALL_", "-prefix", "DOCS", "-docdir" }, - { "INSTALL_", "-prefix", "HEADERS", "-headerdir" }, - { "INSTALL_", "-prefix", "LIBS", "-libdir" }, - { "INSTALL_", "-prefix", "LIBEXECS", "-libexecdir" }, - { "INSTALL_", "-prefix", "BINS", "-bindir" }, - { "INSTALL_", "-prefix", "PLUGINS", "-plugindir" }, - { "INSTALL_", "-prefix", "IMPORTS", "-importdir" }, - { "INSTALL_", "-prefix", "QML", "-qmldir" }, - { "INSTALL_", "-prefix", "ARCHDATA", "-archdatadir" }, - { "INSTALL_", "-prefix", "DATA", "-datadir" }, - { "INSTALL_", "-prefix", "TRANSLATIONS", "-translationdir" }, - { "INSTALL_", "-prefix", "EXAMPLES", "-examplesdir" }, - { "INSTALL_", "-prefix", "TESTS", "-testsdir" }, - { "INSTALL_", "-prefix", "SETTINGS", "-sysconfdir" }, - { "HOST_", "-hostprefix", "BINS", "-hostbindir" }, - { "HOST_", "-hostprefix", "LIBS", "-hostlibdir" }, - { "HOST_", "-hostprefix", "DATA", "-hostdatadir" }, - }; - - bool prefixReminder = false; - for (uint i = 0; i < sizeof(varmod) / sizeof(varmod[0]); i++) { - QString path = QDir::cleanPath( - dictionary[QLatin1String("QT_") + varmod[i].basevar + varmod[i].var]); - if (path.isEmpty()) - continue; - QString base = dictionary[QLatin1String("QT_") + varmod[i].basevar + "PREFIX"]; - if (!path.startsWith(base)) { - if (i != 13) { - dictionary["PREFIX_COMPLAINTS"] += QLatin1String("\n NOTICE: ") - + varmod[i].option + " is not a subdirectory of " + varmod[i].baseoption + "."; - if (i < 13 ? qipempty : !haveHpx) - prefixReminder = true; - } - } else { - path.remove(0, base.size()); - if (path.startsWith('/')) - path.remove(0, 1); - } - dictionary[QLatin1String("QT_REL_") + varmod[i].basevar + varmod[i].var] - = path.isEmpty() ? "." : path; - } - if (prefixReminder) { - dictionary["PREFIX_COMPLAINTS"] - += "\n Maybe you forgot to specify -prefix/-hostprefix?"; - } - - if (!qipempty) { - // If QT_INSTALL_* have not been specified on the command line, - // default them here, unless prefix is empty (WinCE). - - if (dictionary["QT_REL_INSTALL_HEADERS"].isEmpty()) - dictionary["QT_REL_INSTALL_HEADERS"] = "include"; - - if (dictionary["QT_REL_INSTALL_LIBS"].isEmpty()) - dictionary["QT_REL_INSTALL_LIBS"] = "lib"; - - if (dictionary["QT_REL_INSTALL_BINS"].isEmpty()) - dictionary["QT_REL_INSTALL_BINS"] = "bin"; - - if (dictionary["QT_REL_INSTALL_ARCHDATA"].isEmpty()) - dictionary["QT_REL_INSTALL_ARCHDATA"] = "."; - if (dictionary["QT_REL_INSTALL_ARCHDATA"] != ".") - dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] = dictionary["QT_REL_INSTALL_ARCHDATA"] + '/'; - - if (dictionary["QT_REL_INSTALL_LIBEXECS"].isEmpty()) { - if (targSpec.startsWith("win")) - dictionary["QT_REL_INSTALL_LIBEXECS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "bin"; - else - dictionary["QT_REL_INSTALL_LIBEXECS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "libexec"; - } - - if (dictionary["QT_REL_INSTALL_PLUGINS"].isEmpty()) - dictionary["QT_REL_INSTALL_PLUGINS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "plugins"; - - if (dictionary["QT_REL_INSTALL_IMPORTS"].isEmpty()) - dictionary["QT_REL_INSTALL_IMPORTS"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "imports"; - - if (dictionary["QT_REL_INSTALL_QML"].isEmpty()) - dictionary["QT_REL_INSTALL_QML"] = dictionary["QT_REL_INSTALL_ARCHDATA_PREFIX"] + "qml"; - - if (dictionary["QT_REL_INSTALL_DATA"].isEmpty()) - dictionary["QT_REL_INSTALL_DATA"] = "."; - if (dictionary["QT_REL_INSTALL_DATA"] != ".") - dictionary["QT_REL_INSTALL_DATA_PREFIX"] = dictionary["QT_REL_INSTALL_DATA"] + '/'; - - if (dictionary["QT_REL_INSTALL_DOCS"].isEmpty()) - dictionary["QT_REL_INSTALL_DOCS"] = dictionary["QT_REL_INSTALL_DATA_PREFIX"] + "doc"; - - if (dictionary["QT_REL_INSTALL_TRANSLATIONS"].isEmpty()) - dictionary["QT_REL_INSTALL_TRANSLATIONS"] = dictionary["QT_REL_INSTALL_DATA_PREFIX"] + "translations"; - - if (dictionary["QT_REL_INSTALL_EXAMPLES"].isEmpty()) - dictionary["QT_REL_INSTALL_EXAMPLES"] = "examples"; - - if (dictionary["QT_REL_INSTALL_TESTS"].isEmpty()) - dictionary["QT_REL_INSTALL_TESTS"] = "tests"; - } - - if (dictionary["QT_REL_HOST_BINS"].isEmpty()) - dictionary["QT_REL_HOST_BINS"] = haveHpx ? "bin" : dictionary["QT_REL_INSTALL_BINS"]; - - if (dictionary["QT_REL_HOST_LIBS"].isEmpty()) - dictionary["QT_REL_HOST_LIBS"] = haveHpx ? "lib" : dictionary["QT_REL_INSTALL_LIBS"]; - - if (dictionary["QT_REL_HOST_DATA"].isEmpty()) - dictionary["QT_REL_HOST_DATA"] = haveHpx ? "." : dictionary["QT_REL_INSTALL_ARCHDATA"]; - - confStringOff = 0; - addConfStr(0, dictionary["QT_REL_INSTALL_DOCS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_HEADERS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_LIBS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_LIBEXECS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_BINS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_PLUGINS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_IMPORTS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_QML"]); - addConfStr(0, dictionary["QT_REL_INSTALL_ARCHDATA"]); - addConfStr(0, dictionary["QT_REL_INSTALL_DATA"]); - addConfStr(0, dictionary["QT_REL_INSTALL_TRANSLATIONS"]); - addConfStr(0, dictionary["QT_REL_INSTALL_EXAMPLES"]); - addConfStr(0, dictionary["QT_REL_INSTALL_TESTS"]); - addConfStr(1, dictionary["CFG_SYSROOT"]); - addConfStr(1, dictionary["QT_REL_HOST_BINS"]); - addConfStr(1, dictionary["QT_REL_HOST_LIBS"]); - addConfStr(1, dictionary["QT_REL_HOST_DATA"]); - addConfStr(1, targSpec); - addConfStr(1, hostSpec); - - // Generate the new qconfig.cpp file - { - FileWriter tmpStream(buildPath + "/src/corelib/global/qconfig.cpp"); - tmpStream << "/* Build date */" << endl - << "static const char qt_configure_installation [11 + 12] = \"qt_instdate=2012-12-20\";" << endl - << endl - << "/* Installation Info */" << endl - << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << dictionary["QT_INSTALL_PREFIX"] << "\";" << endl - << "#ifdef QT_BUILD_QMAKE" << endl - << "static const char qt_configure_ext_prefix_path_str [512 + 12] = \"qt_epfxpath=" << dictionary["QT_EXT_PREFIX"] << "\";" << endl - << "static const char qt_configure_host_prefix_path_str [512 + 12] = \"qt_hpfxpath=" << dictionary["QT_HOST_PREFIX"] << "\";" << endl - << "#endif" << endl - << endl - << "static const short qt_configure_str_offsets[] = {\n" - << " " << confStrOffsets[0] << endl - << "#ifdef QT_BUILD_QMAKE\n" - << " " << confStrOffsets[1] << endl - << "#endif\n" - << "};\n" - << "static const char qt_configure_strs[] =\n" - << confStrings[0] << "#ifdef QT_BUILD_QMAKE\n" - << confStrings[1] << "#endif\n" - << ";\n" - << endl; - if ((platform() != WINDOWS) && (platform() != WINDOWS_RT)) - tmpStream << "#define QT_CONFIGURE_SETTINGS_PATH \"" << dictionary["QT_REL_INSTALL_SETTINGS"] << "\"" << endl; - - tmpStream << endl - << "#ifdef QT_BUILD_QMAKE\n" - << "# define QT_CONFIGURE_SYSROOTIFY_PREFIX " << (sysrootifyPrefix ? "true" : "false") << endl - << "#endif\n\n" - << endl - << "#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12\n" - << "#ifdef QT_BUILD_QMAKE\n" - << "# define QT_CONFIGURE_EXT_PREFIX_PATH qt_configure_ext_prefix_path_str + 12\n" - << "# define QT_CONFIGURE_HOST_PREFIX_PATH qt_configure_host_prefix_path_str + 12\n" - << "#endif\n"; - - if (!tmpStream.flush()) - dictionary[ "DONE" ] = "error"; - } -} - void Configure::buildQmake() { { @@ -875,7 +313,10 @@ void Configure::buildQmake() if (confFile.open(QFile::WriteOnly | QFile::Text)) { // Truncates any existing file. QTextStream confStream(&confFile); confStream << "[EffectivePaths]" << endl - << "Prefix=.." << endl; + << "Prefix=.." << endl + << "[Paths]" << endl + << "TargetSpec=dummy" << endl + << "HostSpec=" << dictionary["QMAKESPEC"] << endl; if (sourcePath != buildPath) confStream << "[EffectiveSourcePaths]" << endl << "Prefix=" << sourcePath << endl; @@ -891,7 +332,7 @@ void Configure::configure() QStringList args; args << buildPath + "/bin/qmake" << sourcePathMangled - << "--" << configCmdLine; + << "--" << qmakeCmdLine; QString pwd = QDir::currentPath(); QDir::setCurrent(buildPathMangled); @@ -900,9 +341,6 @@ void Configure::configure() dictionary[ "DONE" ] = "error"; } QDir::setCurrent(pwd); - - if ((dictionary["REDO"] != "yes") && (dictionary["DONE"] != "error")) - saveCmdLine(); } bool Configure::reloadCmdLine(int idx) @@ -924,35 +362,6 @@ bool Configure::reloadCmdLine(int idx) return true; } -void Configure::saveCmdLine() -{ - if (dictionary[ "REDO" ] != "yes") { - if (dictionary["BUILDTYPE"] == "none") { - bool openSource = false; - QFile inFile(buildPath + "/mkspecs/qconfig.pri"); - if (inFile.open(QFile::ReadOnly | QFile::Text)) { - QTextStream inStream(&inFile); - while (!inStream.atEnd()) { - if (inStream.readLine() == "QT_EDITION = OpenSource") - openSource = true; - } - } - configCmdLine.append(openSource ? "-opensource" : "-commercial"); - } - if (dictionary["LICENSE_CONFIRMED"] != "yes") - configCmdLine.append("-confirm-license"); - QFile outFile(buildPathMangled + "/config.opt"); - if (outFile.open(QFile::WriteOnly | QFile::Text)) { - QTextStream outStream(&outFile); - for (QStringList::Iterator it = configCmdLine.begin(); it != configCmdLine.end(); ++it) { - outStream << (*it) << endl; - } - outStream.flush(); - outFile.close(); - } - } -} - bool Configure::isDone() { return !dictionary["DONE"].isEmpty(); @@ -963,66 +372,4 @@ bool Configure::isOk() return (dictionary[ "DONE" ] != "error"); } -int Configure::platform() const -{ - const QString xQMakeSpec = dictionary.value("XQMAKESPEC"); - - if ((xQMakeSpec.startsWith("winphone") || xQMakeSpec.startsWith("winrt"))) - return WINDOWS_RT; - - if (xQMakeSpec.contains("qnx")) - return QNX; - - if (xQMakeSpec.contains("android")) - return ANDROID; - - if (!xQMakeSpec.isEmpty()) - return OTHER; - - return WINDOWS; -} - -FileWriter::FileWriter(const QString &name) - : QTextStream() - , m_name(name) -{ - m_buffer.open(QIODevice::WriteOnly); - setDevice(&m_buffer); -} - -bool FileWriter::flush() -{ - QTextStream::flush(); - QFile oldFile(m_name); - if (oldFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (oldFile.readAll() == m_buffer.data()) - return true; - oldFile.close(); - } - QString dir = QFileInfo(m_name).absolutePath(); - if (!QDir().mkpath(dir)) { - cout << "Cannot create directory " << qPrintable(QDir::toNativeSeparators(dir)) << ".\n"; - return false; - } - QFile file(m_name + ".new"); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - if (file.write(m_buffer.data()) == m_buffer.data().size()) { - file.close(); - if (file.error() == QFile::NoError) { - ::SetFileAttributes((wchar_t*)m_name.utf16(), FILE_ATTRIBUTE_NORMAL); - QFile::remove(m_name); - if (!file.rename(m_name)) { - cout << "Cannot replace file " << qPrintable(QDir::toNativeSeparators(m_name)) << ".\n"; - return false; - } - return true; - } - } - } - cout << "Cannot create file " << qPrintable(QDir::toNativeSeparators(file.fileName())) - << ": " << qPrintable(file.errorString()) << ".\n"; - file.remove(); - return false; -} - QT_END_NAMESPACE diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index b007f3c487..596196c2a9 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -44,27 +44,22 @@ public: void parseCmdLine(); - void generateQConfigCpp(); void buildQmake(); void prepareConfigureInput(); void configure(); void generateHeaders(); - void generateQDevicePri(); - void prepareConfigTests(); bool isDone(); bool isOk(); - int platform() const; - private: int verbose; // Our variable dictionaries QMap<QString,QString> dictionary; - QStringList configCmdLine; + QStringList configCmdLine, qmakeCmdLine; QString outputLine; @@ -73,25 +68,7 @@ private: QString sourcePathMangled, buildPathMangled; QDir sourceDir, buildDir; - QString confStrOffsets[2]; - QString confStrings[2]; - int confStringOff; - - void addConfStr(int group, const QString &val); - QString formatPath(const QString &path); - bool reloadCmdLine(int idx); - void saveCmdLine(); -}; - -class FileWriter : public QTextStream -{ -public: - FileWriter(const QString &name); - bool flush(); -private: - QString m_name; - QBuffer m_buffer; }; QT_END_NAMESPACE diff --git a/tools/configure/main.cpp b/tools/configure/main.cpp index f6c2722529..c6b555d14d 100644 --- a/tools/configure/main.cpp +++ b/tools/configure/main.cpp @@ -45,9 +45,6 @@ int runConfigure( int argc, char** argv ) if (!app.isOk()) return 3; - // Source file with path settings. Needed by qmake. - app.generateQConfigCpp(); - // Bootstrapped includes. Needed by qmake. app.generateHeaders(); if (!app.isOk()) @@ -58,16 +55,6 @@ int runConfigure( int argc, char** argv ) if (!app.isOk()) return 3; - // Generate qdevice.pri - app.generateQDevicePri(); - if (!app.isOk()) - return 3; - - // Prepare the config test build directory. - app.prepareConfigTests(); - if (!app.isOk()) - return 3; - // run qmake based configure app.configure(); if (!app.isOk()) |