diff options
Diffstat (limited to 'mkspecs/features')
-rw-r--r-- | mkspecs/features/android/android.prf | 18 | ||||
-rw-r--r-- | mkspecs/features/data/testserver/Dockerfile | 29 | ||||
-rw-r--r-- | mkspecs/features/data/testserver/docker-compose-common.yml | 38 | ||||
-rw-r--r-- | mkspecs/features/exclusive_builds.prf | 4 | ||||
-rw-r--r-- | mkspecs/features/lex.prf | 50 | ||||
-rw-r--r-- | mkspecs/features/ltcg.prf | 2 | ||||
-rw-r--r-- | mkspecs/features/qmltestcase.prf | 10 | ||||
-rw-r--r-- | mkspecs/features/qt_common.prf | 4 | ||||
-rw-r--r-- | mkspecs/features/qt_configure.prf | 7 | ||||
-rw-r--r-- | mkspecs/features/qt_module.prf | 9 | ||||
-rw-r--r-- | mkspecs/features/qt_plugin.prf | 1 | ||||
-rw-r--r-- | mkspecs/features/sanitizer.prf | 25 | ||||
-rw-r--r-- | mkspecs/features/testcase.prf | 16 | ||||
-rw-r--r-- | mkspecs/features/unsupported/testserver.prf | 231 | ||||
-rw-r--r-- | mkspecs/features/win32/dumpcpp.prf | 16 | ||||
-rw-r--r-- | mkspecs/features/yacc.prf | 59 |
16 files changed, 459 insertions, 60 deletions
diff --git a/mkspecs/features/android/android.prf b/mkspecs/features/android/android.prf index 1dc8f87313..0e6f4a4592 100644 --- a/mkspecs/features/android/android.prf +++ b/mkspecs/features/android/android.prf @@ -1,3 +1,21 @@ +APK_PATH = $$shell_path($$OUT_PWD/android-build/$${TARGET}.apk) +!contains(TEMPLATE, subdirs): { + apk_install_target.target = apk_install_target + apk_install_target.depends = first + apk_install_target.commands = $(MAKE) -f $(MAKEFILE) INSTALL_ROOT=$$OUT_PWD/android-build install + + apk.target = apk + apk.depends = apk_install_target + qtPrepareTool(ANDROIDDEPLOYQT, androiddeployqt) + isEmpty(ANDROID_DEPLOYMENT_SETTINGS_FILE): ANDROID_DEPLOYMENT_SETTINGS_FILE = $$OUT_PWD/android-$$TARGET-deployment-settings.json + contains(QMAKE_HOST.os, Windows): extension = .exe + apk.commands = $$ANDROIDDEPLOYQT --input $$ANDROID_DEPLOYMENT_SETTINGS_FILE --output $$OUT_PWD/android-build --apk $$APK_PATH +} else { + prepareRecursiveTarget(apk) + prepareRecursiveTarget(apk_install_target) +} +QMAKE_EXTRA_TARGETS *= apk apk_install_target + contains(TEMPLATE, ".*app") { !android_app { !contains(TARGET, ".so"): TARGET = lib$${TARGET}.so diff --git a/mkspecs/features/data/testserver/Dockerfile b/mkspecs/features/data/testserver/Dockerfile new file mode 100644 index 0000000000..a20d289d3f --- /dev/null +++ b/mkspecs/features/data/testserver/Dockerfile @@ -0,0 +1,29 @@ +# This Dockerfile is used to provision the shared scripts (e.g. startup.sh) and configurations. It +# relies on the arguments passed by docker-compose file to build additional images for each service. +# To lean more how it works, please check the topic "Use multi-stage builds". +# https://docs.docker.com/develop/develop-images/multistage-build/ + +ARG provisioningImage +FROM $provisioningImage as testserver_tier2 + +# Add and merge the testdata into service folder +ARG serviceDir +ARG shareDir=$serviceDir +COPY $serviceDir $shareDir service/ + +# create the shared script of testserver +RUN echo "#!/usr/bin/env bash\n" \ + "set -ex\n" \ + "for RUN_CMD; do \$RUN_CMD; done\n" \ + "service dbus restart\n" \ + "service avahi-daemon restart\n" \ + "sleep infinity\n" > startup.sh +RUN chmod +x startup.sh + +# rewrite the default configurations of avahi-daemon +# Disable IPv6 of avahi-daemon to resolve the unstable connections on Windows +ARG test_domain +RUN sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \ + -e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \ + -e "s,use-ipv6=yes,use-ipv6=no," \ + /etc/avahi/avahi-daemon.conf diff --git a/mkspecs/features/data/testserver/docker-compose-common.yml b/mkspecs/features/data/testserver/docker-compose-common.yml new file mode 100644 index 0000000000..58282c1273 --- /dev/null +++ b/mkspecs/features/data/testserver/docker-compose-common.yml @@ -0,0 +1,38 @@ +version: '2.1' + +# This is a template docker-compose file shared with all modules. It is based +# on 'extending services' feature of compose file version 2.1. +# See https://docs.docker.com/compose/extends/#extending-services for details. +# +# Example: testserver/docker-compose.yml +# services: +# foo: +# extends: +# file: ${SHARED_DATA}/docker-compose-common.yml +# service: ${SHARED_SERVICE} +# container_name: qt-test-server-foo +# hostname: ${HOST_NAME:-foo} +# build: +# context: . +# args: +# provisioningImage: qt-test-server-foo:537fe302f61851d1663... +# serviceDir: ./foo +# command: service/foo.sh + +x-services: + &default-service + domainname: ${TEST_DOMAIN} + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + test_domain: ${TEST_DOMAIN} + entrypoint: ./startup.sh + +services: + bridge-network: *default-service + host-network: + << : *default-service + network_mode: "host" + extra_hosts: + - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf index 1ff9a04d42..b28e74146a 100644 --- a/mkspecs/features/exclusive_builds.prf +++ b/mkspecs/features/exclusive_builds.prf @@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) { } # Default directories to process -QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR -QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR +QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR LEX_DIR YACC_DIR +QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR DESTDIR $$QMAKE_DIR_REPLACE_SANE diff --git a/mkspecs/features/lex.prf b/mkspecs/features/lex.prf index 7d8325bedb..ee06215103 100644 --- a/mkspecs/features/lex.prf +++ b/mkspecs/features/lex.prf @@ -2,37 +2,49 @@ # Lex extra-compiler for handling files specified in the LEXSOURCES variable # -{ - lex.name = Lex ${QMAKE_FILE_IN} - lex.input = LEXSOURCES - lex.dependency_type = TYPE_C - lex_included { - lex.CONFIG += no_link - } else { - lex.variable_out = GENERATED_SOURCES - } +isEmpty(LEX_DIR): LEX_DIR = . - isEmpty(QMAKE_LEXFLAGS_MANGLE):QMAKE_LEXFLAGS_MANGLE = -P${QMAKE_FILE_BASE} +defineReplace(lexCommands) { + input = $$relative_path($$absolute_path($$1, $$OUT_PWD), $$OUT_PWD/$$LEX_DIR) + output = $$basename(2) + input_base = $$basename(1) + input_base ~= s/\.[^.]*$// + + isEmpty(QMAKE_LEXFLAGS_MANGLE): QMAKE_LEXFLAGS_MANGLE = -P$${input_base} QMAKE_LEXEXTRAFLAGS = $$QMAKE_LEXFLAGS - !yacc_no_name_mangle:QMAKE_LEXEXTRAFLAGS += $$QMAKE_LEXFLAGS_MANGLE + !yacc_no_name_mangle: QMAKE_LEXEXTRAFLAGS += $$QMAKE_LEXFLAGS_MANGLE contains(QMAKE_LEX, .*flex) { # GNU flex, we can use -o outfile - lex.commands = $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS --nounistd -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + commands = $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS --nounistd -o $$output $$input } else { # stupid POSIX lex, it only generates a file called lex.yy.c # or lex.prefix.c if the -P<prefix> option is active intermediate_file = lex.yy.c QMAKE_LEXEXTRAFLAGS = $$QMAKE_LEXFLAGS $$QMAKE_LEXFLAGS_MANGLE - lex.commands = \ - -$(DEL_FILE) ${QMAKE_FILE_OUT}$$escape_expand(\\n\\t) \ - $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS ${QMAKE_FILE_IN}$$escape_expand(\\n\\t) \ - $(MOVE) $$intermediate_file ${QMAKE_FILE_OUT} $$escape_expand(\\n\\t) - unset(intermediate_file) + commands = \ + -$(DEL_FILE) $${output}$$escape_expand(\\n\\t) \ + $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS $${input}$$escape_expand(\\n\\t) \ + $(MOVE) $$intermediate_file $$output $$escape_expand(\\n\\t) + } + !equals(LEX_DIR, .): \ + commands = cd $$LEX_DIR && $$commands + silent: commands = @echo Lex $$1 && $$commands + return($$commands) +} + +{ + lex.name = Lex ${QMAKE_FILE_IN} + lex.input = LEXSOURCES + lex.dependency_type = TYPE_C + lex_included { + lex.CONFIG += no_link + } else { + lex.variable_out = GENERATED_SOURCES } - lex.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_LEX}$${first(QMAKE_EXT_CPP)} - silent:lex.commands = @echo Lex ${QMAKE_FILE_IN} && $$lex.commands + lex.commands = ${QMAKE_FUNC_lexCommands} + lex.output = $$LEX_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_LEX}$${first(QMAKE_EXT_CPP)} QMAKE_EXTRA_COMPILERS += lex } diff --git a/mkspecs/features/ltcg.prf b/mkspecs/features/ltcg.prf index a94f6d0eeb..10d14dfe85 100644 --- a/mkspecs/features/ltcg.prf +++ b/mkspecs/features/ltcg.prf @@ -4,7 +4,7 @@ static:no-static-ltcg { # We need fat object files when creating static libraries on some platforms # so the linker will know to load a particular object from the library # in the first place. On others, we have special ar and nm to create the symbol - # tables so the linker will know better. For other compilers, we disable LTCG + # tables so the linker will know better. For other compilers, we disable LTCG # for static libraries. msvc { # Nothing to do diff --git a/mkspecs/features/qmltestcase.prf b/mkspecs/features/qmltestcase.prf index b4b1224781..ae4ebef513 100644 --- a/mkspecs/features/qmltestcase.prf +++ b/mkspecs/features/qmltestcase.prf @@ -1,8 +1,14 @@ !isEmpty(SOURCES) { QT += qml qmltest load(testcase) - contains(TEMPLATE, vc.*): DEFINES += QUICK_TEST_SOURCE_DIR=\"$$_PRO_FILE_PWD_\" - else: DEFINES += QUICK_TEST_SOURCE_DIR=$$shell_quote(\"$$_PRO_FILE_PWD_\") + !android { + contains(TEMPLATE, vc.*): DEFINES += QUICK_TEST_SOURCE_DIR=\"$$_PRO_FILE_PWD_\" + else: DEFINES += QUICK_TEST_SOURCE_DIR=$$shell_quote(\"$$_PRO_FILE_PWD_\") + } else { + !isEmpty(RESOURCES): warning("The RESOURCES qmake variable is empty, the test will probably fail to run") + DEFINES += QUICK_TEST_SOURCE_DIR=\":/\" + } + } else { # Allow a project to run tests without a CPP stub TEMPLATE = aux diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index e64dfa98c2..c24f2c6062 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -152,8 +152,8 @@ warnings_are_errors:warning_clean { android: QMAKE_CXXFLAGS_WARN_ON += -Wno-error=literal-suffix } } else:msvc:!intel_icl { - # enable for MSVC 2012, MSVC 2013, MSVC 2015 - contains(MSVC_VER, "1[124].0"): QMAKE_CXXFLAGS_WARN_ON += -WX + # enable for MSVC 2015, MSVC 2017 + contains(MSVC_VER, "1[45].0"): QMAKE_CXXFLAGS_WARN_ON += -WX } unset(ver) } diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 9be4fb6f1f..2ac9de266f 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -61,6 +61,13 @@ defineTest(qtConfCommandlineSetInput) { val = $${2} !isEmpty($${currentConfig}.commandline.options.$${arg}.name): \ arg = $$eval($${currentConfig}.commandline.options.$${arg}.name) + !isEmpty(config.input.$$arg) { + oldval = $$eval(config.input.$$arg) + equals(oldval, $$val): \ + qtConfAddNote("Option '$$arg' with value '$$val' was specified twice") + else: \ + qtConfAddNote("Overriding option '$$arg' with '$$val' (was: '$$oldval')") + } config.input.$$arg = $$val export(config.input.$$arg) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 46687f262e..169d91c746 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -269,7 +269,7 @@ load(qt_installs) load(qt_targets) # this builds on top of qt_common -!internal_module:if(unix|mingw) { +!internal_module:if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) { CONFIG += create_pc QMAKE_PKGCONFIG_DESTDIR = pkgconfig host_build: \ @@ -282,11 +282,13 @@ load(qt_targets) } else { QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw] QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME + for(inc, MODULE_AUX_INCLUDES): \ + QMAKE_PKGCONFIG_CFLAGS += -I${includedir}/$$section(inc, /, 1, 1) } QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$QT_MAJOR_VERSION ") - QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION) + QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION)$$qtPlatformTargetSuffix() for(i, MODULE_DEPENDS): \ - QMAKE_PKGCONFIG_REQUIRES += $$replace(QT.$${i}.name, ^Qt, Qt$$section(QT.$${i}.VERSION, ., 0, 0)) + QMAKE_PKGCONFIG_REQUIRES += $$replace(QT.$${i}.name, ^Qt, Qt$$section(QT.$${i}.VERSION, ., 0, 0))$$qtPlatformTargetSuffix() isEmpty(QMAKE_PKGCONFIG_DESCRIPTION): \ QMAKE_PKGCONFIG_DESCRIPTION = $$replace(TARGET, ^Qt, "Qt ") module !isEmpty(lib_replace0.match) { @@ -334,5 +336,6 @@ win32 { # On other platforms, Qt's own compilation goes needs to compile the Qt 5.0 API DEFINES *= QT_DISABLE_DEPRECATED_BEFORE=0x050000 } +DEFINES *= QT_DEPRECATED_WARNINGS_SINCE=0x060000 TARGET = $$qt5LibraryTarget($$TARGET$$QT_LIBINFIX) # Do this towards the end diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf index 40528a65e2..6e7388c352 100644 --- a/mkspecs/features/qt_plugin.prf +++ b/mkspecs/features/qt_plugin.prf @@ -91,6 +91,7 @@ CONFIG(static, static|shared)|prefix_build { target.path = $$[QT_INSTALL_PLUGINS]/$$PLUGIN_TYPE INSTALLS += target +qt_libinfix_plugins: TARGET = $$TARGET$$QT_LIBINFIX TARGET = $$qt5LibraryTarget($$TARGET) CONFIG += create_cmake diff --git a/mkspecs/features/sanitizer.prf b/mkspecs/features/sanitizer.prf index 9e7ff0218a..c7d72aec80 100644 --- a/mkspecs/features/sanitizer.prf +++ b/mkspecs/features/sanitizer.prf @@ -1,10 +1,33 @@ # Sanitizer flags - sanitize_address { QMAKE_CFLAGS += $$QMAKE_SANITIZE_ADDRESS_CFLAGS QMAKE_CXXFLAGS += $$QMAKE_SANITIZE_ADDRESS_CXXFLAGS QMAKE_LFLAGS += $$QMAKE_SANITIZE_ADDRESS_LFLAGS + android { + # ARM 32 (armeabi-v7a & arm5) are not supported because Qt must be rebuilt with -marm + equals(ANDROID_TARGET_ARCH, arm64-v8a): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-aarch64-android.so" + else: equals(ANDROID_TARGET_ARCH, x86): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-i686-android.so" + else: equals(ANDROID_TARGET_ARCH, x86_64): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-x86_64-android.so" + else: error("ASAN: Unsupported platform $${ANDROID_TARGET_ARCH}") + + ANDROID_LIBCLANG_RT_PATH = $${NDK_LLVM_PATH}/lib64/clang + ANDROID_CLANG_RT_VERSIONS = $$files($$ANDROID_LIBCLANG_RT_PATH/*) + for (VERSION, ANDROID_CLANG_RT_VERSIONS) { + greaterThan(VERSION, $$ANDROID_LIBCLANG_RT_PATH): ANDROID_LIBCLANG_RT_PATH = $$VERSION + } + ANDROID_LIBCLANG_RT_PATH = "$${ANDROID_LIBCLANG_RT_PATH}/lib/linux/" + ANDROID_WRAP_SH_CONTENT = "$$LITERAL_HASH!/system/bin/sh" + ANDROID_WRAP_SH_CONTENT += "HERE=\"$(cd \"$(dirname \"$0\")\" && pwd)\"" + isEmpty(ANDROID_ASAN_OPTIONS): ANDROID_ASAN_OPTIONS = "log_to_syslog=false,allow_user_segv_handler=1" + ANDROID_WRAP_SH_CONTENT += "export ASAN_OPTIONS=$${ANDROID_ASAN_OPTIONS}" + ANDROID_WRAP_SH_CONTENT += "export LD_PRELOAD=$HERE/$${ANDROID_LIBCLANG_RT_FILE}" + ANDROID_WRAP_SH_CONTENT += "exec \"$@\"" + write_file($$OUT_PWD/android-build/resources/lib/$${ANDROID_TARGET_ARCH}/wrap.sh, ANDROID_WRAP_SH_CONTENT) | error() + libclang_rt.path = /libs/$$ANDROID_TARGET_ARCH/ + libclang_rt.files = "$${ANDROID_LIBCLANG_RT_PATH}/$${ANDROID_LIBCLANG_RT_FILE}" + INSTALLS += libclang_rt + } } sanitize_memory { diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index b8102c26b5..d4f08835f1 100644 --- a/mkspecs/features/testcase.prf +++ b/mkspecs/features/testcase.prf @@ -52,14 +52,26 @@ debug_and_release:debug_and_release_target { } # Allow for a custom test runner script -$${type}.commands += $(TESTRUNNER) + +android: isEmpty($(TESTRUNNER)) { + APK_PATH = $$shell_path($$OUT_PWD/android-build/$${TARGET}.apk) + qtPrepareTool(ANDROIDTESTRUNNER, androidtestrunner) + qtPrepareTool(ANDROIDDEPLOYQT, androiddeployqt) + isEmpty(ANDROID_DEPLOYMENT_SETTINGS_FILE): ANDROID_DEPLOYMENT_SETTINGS_FILE = $$OUT_PWD/android-$$TARGET-deployment-settings.json + contains(QMAKE_HOST.os, Windows): extension = .exe + $${type}.commands = $$ANDROIDTESTRUNNER --androiddeployqt \"$$ANDROIDDEPLOYQT --input $$ANDROID_DEPLOYMENT_SETTINGS_FILE\" + $${type}.commands += --path \"$$OUT_PWD/android-build\" + $${type}.commands += --adb \"$$shell_path($${ANDROID_SDK_ROOT}$${QMAKE_DIR_SEP}platform-tools$${QMAKE_DIR_SEP}adb$${extension})\" + $${type}.commands += --make \"$(MAKE) -f $(MAKEFILE)\" + $${type}.commands += --apk $$APK_PATH +} else: $${type}.commands += $(TESTRUNNER) unix { isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = . app_bundle: \ $${type}.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET) - else: \ + else: !android: \ $${type}.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET) } else { # Windows diff --git a/mkspecs/features/unsupported/testserver.prf b/mkspecs/features/unsupported/testserver.prf new file mode 100644 index 0000000000..bca88ea2d8 --- /dev/null +++ b/mkspecs/features/unsupported/testserver.prf @@ -0,0 +1,231 @@ +# Integrating docker-based test servers into Qt Test framework +# +# This file adds support for docker-based test servers built by testcase +# projects that need them. To enable this feature, any automated test can +# include testserver.pri in its project file. This instructs qmake to insert +# additional targets into the generated Makefile. The 'check' target then brings +# up test servers before running the testcase, and shuts them down afterwards. +# +# TESTSERVER_COMPOSE_FILE +# - Contains the path of docker-compose file +# This configuration file defines the services used for autotests. It tells the +# docker engine how to build up the docker images and containers. In qtbase, a +# shared docker-compose file is located in the tests folder. +# Example: TESTSERVER_COMPOSE_FILE = \ +# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml +# +# The user must run the provisioning scripts in advance before attempting to +# build the test servers. The docker_testserver.sh script is used to build up +# the docker images into the docker-cache. It handles the immutable parts of the +# server installation that rarely need adjustment, such as downloading packages. +# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh +# +# QT_TEST_SERVER_LIST +# - A list of test servers to bring up for this testcase +# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each +# testcase can define the test servers it depends on. +# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted +# +# Pre-processor defines needed for the application: +# QT_TEST_SERVER +# - A preprocessor macro used for testcase to change testing parameters at +# compile time +# This macro is predefined for docker-based test servers and is passed as a +# compiler option (-DQT_TEST_SERVER). The testcase can then check whether +# docker-based servers are in use and change the testing parameters, such as +# host name or port number, at compile time. An example can be found in +# network-settings.h. +# +# Example: +# #if defined(QT_TEST_SERVER) +# Change the testing parameters at compile time +# #endif +# +# QT_TEST_SERVER_DOMAIN +# - A preprocessor macro that holds the server domain name +# Provided for the helper functions in network-settings.h. Use function +# serverDomainName() in your application instead. +# +# Additional make targets: +# 1. check_network - A renamed target from the check target of testcase feature. +# 2. testserver_clean - Clean up server containers/images and tidy away related +# files. + +# The docker test server should only be integrated in the leaf Makefile. +# If debug_and_release option is in use, skip the meta-Makefile except for +# Makefile.Debug and Makefile.Release. +debug_and_release:!build_pass: return() + +DOCKER_ENABLED = 1 + +equals(QMAKE_HOST.os, Darwin) { + DOCKER_ENABLED = 0 + message("Not using docker network test server on macOS, see QTQAINFRA-2717 and QTQAINFRA-2750") +} + +TESTSERVER_VERSION = "" + +equals(DOCKER_ENABLED, 1) { + TESTSERVER_VERSION = $$system(docker-compose --version) +} + +isEmpty(TESTSERVER_VERSION) { + # Make check with server "qt-test-server.qt-test-net" as a fallback +} else { + # Make check with docker test servers + equals(QMAKE_HOST.os, Linux) { + # For the platform supporting docker bridge network, each container is + # assigned a unique hostname and connected to the same network domain + # to communicate with the others. + DEFINES += QT_TEST_SERVER_NAME + DNSDOMAIN = test-net.qt.local + } else { + # For the others, the containers are deployed into a virtual machine + # using the host network. All the containers share the same hostname of + # the virtual machine, and they are connected to the same network domain. + # NOTE: In Windows, Apple Bonjour only works within a single local domain. + DNSDOMAIN = local + } + + equals(QMAKE_HOST.os, Darwin) { + # There is no docker bridge on macOS. It is impossible to ping a container. + # Docker docs recommends using port mapping to connect to a container; + # but it causes a port conflict if the user is running a service that + # binds the same port on the host. An alternative solution is to deploy + # the docker environment into VirtualBox using docker-machine. + isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \ + $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-host-network.yml + + # The connection configuration for the target machine + MACHINE_CONFIG = $(shell docker-machine config qt-test-server) + + # The environment variables passed to the docker-compose file + TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)' + TEST_ENV += 'HOST_NAME=qt-test-server' + TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN' + TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver' + TEST_ENV += 'SHARED_SERVICE=host-network' + TEST_CMD = env + } else:equals(QMAKE_HOST.os, Windows) { + # There is no docker bridge on Windows. It is impossible to ping a container. + # Use docker-machine to deploy the docker environment into VirtualBox. + isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \ + $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-host-network.yml + + # The connection configuration for the target machine + MACHINE_CONFIG = (docker-machine config qt-test-server) + + # The environment variables passed to the docker-compose file + TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;' + TEST_ENV += '\$\$env:HOST_NAME = $$shell_quote(\"qt-test-server\");' + TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");' + TEST_ENV += '\$\$env:SHARED_DATA = $$shell_quote(\"$$PWD/../data/testserver\");' + TEST_ENV += '\$\$env:SHARED_SERVICE = $$shell_quote(\"host-network\");' + + # Docker-compose CLI environment variables: + # Enable path conversion from Windows-style to Unix-style in volume definitions. + TEST_ENV += '\$\$env:COMPOSE_CONVERT_WINDOWS_PATHS = $$shell_quote(\"true\");' + + TEST_CMD = 'PowerShell -noprofile' + CONFIG += PowerShell + } else { + isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \ + $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-bridge-network.yml + # The environment variables passed to the docker-compose file + TEST_ENV = 'TEST_DOMAIN=$$DNSDOMAIN' + TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver' + TEST_ENV += 'SHARED_SERVICE=bridge-network' + TEST_CMD = env + } + + # If $$TESTSERVER_COMPOSE_FILE defined by platform doesn't exist, the default + # docker-compose.yml is used as a fallback. + !exists($$TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \ + $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml + !exists($$TESTSERVER_COMPOSE_FILE): error("Invalid TESTSERVER_COMPOSE_FILE specified") + + + # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem). + DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\") + + # Ensure that the docker-compose file is provided. It is a configuration + # file which is mandatory for all docker-compose commands. You can get more + # detail from the description of TESTSERVER_COMPOSE_FILE above. There is + # also an example showing how to configure it manually. + FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set" + PowerShell { + testserver_pretest.commands = echo $$TESTSERVER_VERSION && + testserver_pretest.commands += \ + $$TEST_CMD if ([String]::IsNullOrEmpty($$shell_quote(\"$$TESTSERVER_COMPOSE_FILE\"))) \ + {Write-Error $$shell_quote(\"$$FILE_PRETEST_MSG\")} && + } else { + testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION) + testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG)) + } + + # Make sure docker-machine is both created and running. The docker_machine + # script is used to deploy the docker environment into VirtualBox. + # Example: qt5/coin/provisioning/common/shared/testserver/docker_machine.sh + !isEmpty(MACHINE_CONFIG) { + MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server\$\$" + MACHINE_LIST_MSG = "Docker machine qt-test-server not found" + PowerShell { + testserver_pretest.commands += $$TEST_CMD if (!($$MACHINE_LIST_CMD)) \ + {Write-Error $$shell_quote(\"$$MACHINE_LIST_MSG\")} && + } else { + testserver_pretest.commands += \ + $(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG)) + } + + MACHINE_STATE_CMD = \ + docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server\$\$" + MACHINE_START_CMD = docker-machine start qt-test-server + MACHINE_RECERT = docker-machine regenerate-certs -f qt-test-server + PowerShell { + testserver_pretest.commands += \ + $$TEST_CMD if (!($$MACHINE_STATE_CMD)) {$$MACHINE_START_CMD; $$MACHINE_RECERT} && + } else { + testserver_pretest.commands += \ + $(if $(shell $$MACHINE_STATE_CMD),,\ + $(shell $$MACHINE_START_CMD > /dev/null && $$MACHINE_RECERT > /dev/null)) + } + } + + # Before starting the test servers, it requires the user to run the setup + # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance. + IMAGE_PRETEST_CMD = docker $$MACHINE_CONFIG images -aq "qt-test-server-*" + IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found" + PowerShell { + testserver_pretest.commands += $$TEST_CMD if (!($$IMAGE_PRETEST_CMD)) \ + {Write-Error $$shell_quote(\"$$IMAGE_PRETEST_MSG\")} + } else { + testserver_pretest.commands += \ + $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG)) + } + + # Rename the check target of testcase feature + check.target = check_network + testserver_test.target = check + + # Pretesting test servers environment + testserver_test.depends = testserver_pretest + + # Bring up test servers and make sure the services are ready. + !isEmpty(TEST_CMD): testserver_test.commands = $$TEST_CMD $$TEST_ENV + testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \ + --build -d --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && + + # Check test cases with docker-based test servers. + testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network && + + # Stop and remove test servers after testing. + !isEmpty(TEST_CMD): testserver_test.commands += $$TEST_CMD $$TEST_ENV + testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \ + --timeout 1 + + # Destroy test servers and tidy away related files. + testserver_clean.commands = docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \ + --rmi all + + QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean +} diff --git a/mkspecs/features/win32/dumpcpp.prf b/mkspecs/features/win32/dumpcpp.prf index c8cb0dd24b..d19da3d077 100644 --- a/mkspecs/features/win32/dumpcpp.prf +++ b/mkspecs/features/win32/dumpcpp.prf @@ -22,15 +22,15 @@ dumpcpp_impl.depends += ${QMAKE_FILE_BASE}.h QMAKE_EXTRA_COMPILERS += dumpcpp_impl -# Create dependencies from every object file to our generated header files. -if(isEmpty(BUILDS)|build_pass):have_target:!contains(TEMPLATE, vc.*) { +# Call dumpcpp the first time if the files do not exist to help find dependencies +!build_pass:have_target:!contains(TEMPLATE, vc.*) { for(tlb, TYPELIBS) { + tlbCopy = $$replace(tlb, \", ) hdr = $$basename(tlb) - hdr = $$section(hdr, ., 0, -2).h - TYPELIB_HEADERS += $$hdr + hdr = $$section(hdr, ., 0, -2) + tmp_command = $$QMAKE_DUMPCPP $$system_quote($$absolute_path($$tlb, $$_PRO_FILE_PWD_)) \ + -o $$system_quote($$OUT_PWD/$$hdr) + qaxcontainer_compat: tmp_command += -compat + !exists($$OUT_PWD/$${hdr}.h): system($$tmp_command) } - - objtgt.target = $(OBJECTS) - objtgt.depends += $$TYPELIB_HEADERS - QMAKE_EXTRA_TARGETS += objtgt } diff --git a/mkspecs/features/yacc.prf b/mkspecs/features/yacc.prf index 618f0668c2..0c7ff7321e 100644 --- a/mkspecs/features/yacc.prf +++ b/mkspecs/features/yacc.prf @@ -2,32 +2,49 @@ # Yacc extra-compiler for handling files specified in the YACCSOURCES variable # -{ - yacc_decl.name = Yacc header - yacc_decl.input = YACCSOURCES - yacc_decl.variable_out = GENERATED_FILES +isEmpty(YACC_DIR): YACC_DIR = . +defineReplace(yaccCommands) { + input = $$relative_path($$absolute_path($$1, $$OUT_PWD), $$OUT_PWD/$$YACC_DIR) + input_base = $$basename(1) + input_base ~= s/\.[^.]*$// + hpp_output = $$2 + cpp_output = $$hpp_output + cpp_output ~= s/$$re_escape($$first(QMAKE_EXT_H))$/$$first(QMAKE_EXT_CPP)/ isEmpty(QMAKE_YACCFLAGS_MANGLE) { - QMAKE_YACCFLAGS_MANGLE = -p ${QMAKE_FILE_BASE} -b ${QMAKE_FILE_BASE} - QMAKE_YACC_HEADER = ${QMAKE_FILE_BASE}.tab.h - QMAKE_YACC_SOURCE = ${QMAKE_FILE_BASE}.tab.c + QMAKE_YACCFLAGS_MANGLE = -p $${input_base} -b $${input_base} + QMAKE_YACC_HEADER = $${input_base}.tab.h + QMAKE_YACC_SOURCE = $${input_base}.tab.c } else { - QMAKE_YACCFLAGS_MANGLE ~= s/\\$base/${QMAKE_FILE_BASE}/g #backwards compat - QMAKE_YACC_HEADER ~= s/\\$base/${QMAKE_FILE_BASE}/g - QMAKE_YACC_SOURCE ~= s/\\$base/${QMAKE_FILE_BASE}/g + QMAKE_YACCFLAGS_MANGLE ~= s/\\$base/$${input_base}/g #backwards compat + QMAKE_YACC_HEADER ~= s/\\$base/$${input_base}/g + QMAKE_YACC_SOURCE ~= s/\\$base/$${input_base}/g } QMAKE_YACCDECLFLAGS = $$QMAKE_YACCFLAGS - !yacc_no_name_mangle:QMAKE_YACCDECLFLAGS += $$QMAKE_YACCFLAGS_MANGLE + !yacc_no_name_mangle: QMAKE_YACCDECLFLAGS += $$QMAKE_YACCFLAGS_MANGLE - yacc_decl.commands = \ - -$(DEL_FILE) $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)}$$escape_expand(\\n\\t) \ - $$QMAKE_YACC $$QMAKE_YACCDECLFLAGS ${QMAKE_FILE_IN}$$escape_expand(\\n\\t) \ - $(MOVE) $${QMAKE_YACC_HEADER} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)}$$escape_expand(\\n\\t) \ - $(MOVE) $${QMAKE_YACC_SOURCE} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)}$$escape_expand(\\n\\t) - yacc_decl.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)} + !equals(YACC_DIR, .): yacc_call = cd $$YACC_DIR && + yacc_call += $$QMAKE_YACC $$QMAKE_YACCDECLFLAGS $${input} + + commands = \ + -$(DEL_FILE) $${hpp_output} $${cpp_output}$$escape_expand(\\n\\t) \ + $${yacc_call}$$escape_expand(\\n\\t) \ + $(MOVE) $${YACC_DIR}/$${QMAKE_YACC_HEADER} $${hpp_output}$$escape_expand(\\n\\t) \ + $(MOVE) $${YACC_DIR}/$${QMAKE_YACC_SOURCE} $${cpp_output}$$escape_expand(\\n\\t) + + silent: commands = @echo Yacc $$1 && $$commands + return($$commands) +} - silent:yacc_decl.commands = @echo Yacc ${QMAKE_FILE_IN} && $$yacc_decl.commands +yacc_output_base = $${YACC_DIR}/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC} + +{ + yacc_decl.name = Yacc header + yacc_decl.input = YACCSOURCES + yacc_decl.variable_out = GENERATED_FILES + yacc_decl.commands = ${QMAKE_FUNC_yaccCommands} + yacc_decl.output = $${yacc_output_base}$$first(QMAKE_EXT_H) QMAKE_EXTRA_COMPILERS += yacc_decl } @@ -37,7 +54,9 @@ yacc_impl.variable_out = GENERATED_SOURCES yacc_impl.dependency_type = TYPE_C yacc_impl.commands = $$escape_expand(\\n) # We don't want any commands where, but if command is empty no rules are created - yacc_impl.depends += $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)} # Make sure we depend on the step above - yacc_impl.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)} # Faked output from this step, output really created in step above + yacc_impl.depends += $${yacc_output_base}$$first(QMAKE_EXT_H) # Make sure we depend on the step above + yacc_impl.output = $${yacc_output_base}$$first(QMAKE_EXT_CPP) # Faked output from this step, output really created in step above QMAKE_EXTRA_COMPILERS += yacc_impl } + +unset(yacc_output_base) |