summaryrefslogtreecommitdiffstats
path: root/mkspecs/features
diff options
context:
space:
mode:
Diffstat (limited to 'mkspecs/features')
-rw-r--r--mkspecs/features/configure.prf38
-rw-r--r--mkspecs/features/configure_base.prf54
-rw-r--r--mkspecs/features/create_cmake.prf4
-rw-r--r--mkspecs/features/default_pre.prf7
-rw-r--r--mkspecs/features/mac/sdk.prf5
-rw-r--r--mkspecs/features/no_debug_info.prf3
-rw-r--r--mkspecs/features/qt.prf2
-rw-r--r--mkspecs/features/qt_build_config.prf2
-rw-r--r--mkspecs/features/qt_build_extra.prf3
-rw-r--r--mkspecs/features/qt_common.prf4
-rw-r--r--mkspecs/features/qt_configure.prf1183
-rw-r--r--mkspecs/features/qt_functions.prf2
-rw-r--r--mkspecs/features/qt_module.prf7
-rw-r--r--mkspecs/features/qt_parts.prf2
-rw-r--r--mkspecs/features/qt_plugin.prf1
-rw-r--r--mkspecs/features/uikit/bitcode.prf13
-rw-r--r--mkspecs/features/uikit/default_post.prf109
-rw-r--r--mkspecs/features/uikit/default_pre.prf31
-rwxr-xr-xmkspecs/features/uikit/device_destinations.sh65
-rw-r--r--mkspecs/features/uikit/exclusive_builds_post.prf8
-rw-r--r--mkspecs/features/uikit/qt.prf33
-rw-r--r--mkspecs/features/uikit/qt_config.prf18
-rw-r--r--mkspecs/features/uikit/qt_parts.prf5
-rw-r--r--mkspecs/features/uikit/resolve_config.prf68
-rw-r--r--mkspecs/features/uikit/sdk.prf32
-rw-r--r--mkspecs/features/uikit/testcase.prf12
-rw-r--r--mkspecs/features/uikit/testcase_targets.prf3
-rw-r--r--mkspecs/features/uikit/xcodebuild.mk101
-rw-r--r--mkspecs/features/uikit/xcodebuild.prf61
-rw-r--r--mkspecs/features/win32/console.prf3
-rw-r--r--mkspecs/features/win32/opengl.prf43
-rw-r--r--mkspecs/features/win32/qt_config.prf10
-rw-r--r--mkspecs/features/win32/windows.prf2
33 files changed, 1842 insertions, 92 deletions
diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf
index a890c7f6b9..e1040d250e 100644
--- a/mkspecs/features/configure.prf
+++ b/mkspecs/features/configure.prf
@@ -1,40 +1,4 @@
-equals(QMAKE_HOST.os, Windows) {
- SETENV_PFX = "set "
- SETENV_SFX = "&"
-} else {
- SETENV_PFX =
- SETENV_SFX =
-}
-
-QMAKE_MAKE = $$(MAKE)
-!isEmpty(QMAKE_MAKE) {
- # We were called recursively. Use the same make.
-} else:if(equals(MAKEFILE_GENERATOR, UNIX)|equals(MAKEFILE_GENERATOR, MINGW)) {
- !equals(QMAKE_HOST.os, Windows): \
- QMAKE_MAKE = make
- else: \
- QMAKE_MAKE = mingw32-make
-} else:if(equals(MAKEFILE_GENERATOR, MSVC.NET)|equals(MAKEFILE_GENERATOR, MSBUILD)) {
- QMAKE_MAKE = nmake
-} else {
- error("Configure tests are not supported with the $$MAKEFILE_GENERATOR Makefile generator.")
-}
-# Make sure we don't inherit MAKEFLAGS - -i in particular is fatal.
-QMAKE_MAKE = "$${SETENV_PFX}MAKEFLAGS=$$SETENV_SFX $$QMAKE_MAKE"
-
-# Ensure that a cache is present. If none was found on startup, this will create
-# one in the build directory of the project which loads this feature.
-cache()
-
-QMAKE_CONFIG_LOG = $$dirname(_QMAKE_CACHE_)/config.log
-QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests
-
-defineTest(qtRunLoggedCommand) {
- msg = "+ $$1"
- write_file($$QMAKE_CONFIG_LOG, msg, append)
- system("$$1 >> \"$$QMAKE_CONFIG_LOG\" 2>&1")|return(false)
- return(true)
-}
+load(configure_base)
# Try to build the test project in $$QMAKE_CONFIG_TESTS_DIR/$$1
# ($$_PRO_FILE_PWD_/config.tests/$$1 by default).
diff --git a/mkspecs/features/configure_base.prf b/mkspecs/features/configure_base.prf
new file mode 100644
index 0000000000..fd1730741a
--- /dev/null
+++ b/mkspecs/features/configure_base.prf
@@ -0,0 +1,54 @@
+equals(QMAKE_HOST.os, Windows) {
+ SETENV_PFX = "set "
+ SETENV_SFX = "&"
+} else {
+ SETENV_PFX =
+ SETENV_SFX =
+}
+
+QMAKE_MAKE = $$(MAKE)
+!isEmpty(QMAKE_MAKE) {
+ # We were called recursively. Use the same make.
+} else: if(equals(MAKEFILE_GENERATOR, UNIX)|equals(MAKEFILE_GENERATOR, MINGW)) {
+ !equals(QMAKE_HOST.os, Windows): \
+ QMAKE_MAKE = make
+ else: \
+ QMAKE_MAKE = mingw32-make
+} else: if(equals(MAKEFILE_GENERATOR, MSVC.NET)|equals(MAKEFILE_GENERATOR, MSBUILD)) {
+ QMAKE_MAKE = nmake
+} else {
+ error("Configure tests are not supported with the $$MAKEFILE_GENERATOR Makefile generator.")
+}
+# 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) {
+ msg = "+ $$1"
+ write_file($$QMAKE_CONFIG_LOG, msg, append)
+ $$QMAKE_CONFIG_VERBOSE: log("$$msg$$escape_expand(\\n)")
+}
+
+defineTest(qtRunLoggedCommand) {
+ qtLog($$1)
+ write_file($${QMAKE_CONFIG_LOG}.part, "")
+ result = false
+ system("$$1 > \"$${QMAKE_CONFIG_LOG}.part\" 2>&1"): result = true
+
+ output = $$cat($${QMAKE_CONFIG_LOG}.part, blob)
+
+ write_file($${QMAKE_CONFIG_LOG}, output, append)
+ $$QMAKE_CONFIG_VERBOSE: log($$output)
+
+ return($$result)
+}
+
+isEmpty(QMAKE_CONFIG_TESTS_DIR): QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests
+
+# Ensure that a cache is present. If none was found on startup, this will create
+# one in the build directory of the project which loads this feature.
+cache()
+
+QMAKE_CONFIG_LOG = $$dirname(_QMAKE_CACHE_)/config.log
+write_file($$QMAKE_CONFIG_LOG, "")
diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf
index 11fb52a0b1..1099e14b17 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -78,7 +78,7 @@ contains(CMAKE_PLUGIN_DIR, "^\\.\\./.*") {
CMAKE_PLUGIN_DIR_IS_ABSOLUTE = True
}
-win32:!wince:!static:!staticlib {
+win32:!static:!staticlib {
CMAKE_DLL_DIR = $$cmakeRelativePath($$[QT_INSTALL_BINS], $$[QT_INSTALL_PREFIX])
contains(CMAKE_DLL_DIR, "^\\.\\./.*") {
CMAKE_DLL_DIR = $$[QT_INSTALL_BINS]/
@@ -208,7 +208,7 @@ mac {
CMAKE_PRL_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.prl
CMAKE_PRL_FILE_LOCATION_RELEASE = lib$${CMAKE_QT_STEM}.prl
} else {
- CONFIG(qt_framework, qt_framework|qt_no_framework) {
+ qt_framework {
CMAKE_LIB_FILE_LOCATION_DEBUG = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
CMAKE_LIB_FILE_LOCATION_RELEASE = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
CMAKE_BUILD_IS_FRAMEWORK = "true"
diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf
index 62cd90912e..8841dc19f2 100644
--- a/mkspecs/features/default_pre.prf
+++ b/mkspecs/features/default_pre.prf
@@ -8,7 +8,7 @@ CONFIG = \
testcase_targets import_plugins import_qpa_plugin \
$$CONFIG
-contains(QT_CONFIG, c++11):lessThan(QT_COMPILER_STDCXX, 201103): CONFIG += c++11
+CONFIG += c++11
!build_pass:defined(QT_EDITION, var):!equals(QT_EDITION, "OpenSource"):!equals(QT_EDITION, "Preview") {
#
@@ -56,6 +56,11 @@ isEmpty(QMAKE_DEFAULT_INCDIRS):!host_build {
}
}
QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
+ } else: msvc {
+ LIB = $$getenv("LIB")
+ QMAKE_DEFAULT_LIBDIRS = $$split(LIB, $$QMAKE_DIRLIST_SEP)
+ INCLUDE = $$getenv("INCLUDE")
+ QMAKE_DEFAULT_INCDIRS = $$split(INCLUDE, $$QMAKE_DIRLIST_SEP)
}
unix {
diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf
index ab37b1740f..c4d4c90f09 100644
--- a/mkspecs/features/mac/sdk.prf
+++ b/mkspecs/features/mac/sdk.prf
@@ -55,12 +55,13 @@ for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_FIX_RPATH QMAKE_AR QMAKE_RANLIB QMAKE_
}
!equals(MAKEFILE_GENERATOR, XCODE) {
- ios:!host_buildĀ {
+ uikit:!host_buildĀ {
simulator: \
version_identifier = $$simulator.deployment_identifier
else: \
version_identifier = $$device.deployment_identifier
- deployment_target = $$QMAKE_IOS_DEPLOYMENT_TARGET
+ ios: deployment_target = $$QMAKE_IOS_DEPLOYMENT_TARGET
+ tvos: deployment_target = $$QMAKE_TVOS_DEPLOYMENT_TARGET
} else: osx {
version_identifier = macosx
deployment_target = $$QMAKE_MACOSX_DEPLOYMENT_TARGET
diff --git a/mkspecs/features/no_debug_info.prf b/mkspecs/features/no_debug_info.prf
index 1307679a39..da14b7bb27 100644
--- a/mkspecs/features/no_debug_info.prf
+++ b/mkspecs/features/no_debug_info.prf
@@ -1,5 +1,4 @@
-
-win32-msvc2*|wince*msvc* {
+msvc {
QMAKE_CFLAGS -= -Zi
QMAKE_CFLAGS_DEBUG -= -Zi
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO -= -Zi
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 71e96b4651..8d96d18d06 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -365,7 +365,7 @@ for(QT_CURRENT_VERIFY, $$list($$QT_PLUGIN_VERIFY)) {
# The following block is currently broken, because qt_plugin_XXX.prf files
# are not generated for dynamic builds.
- false:isEqual(QT_CURRENT_VERIFY, DEPLOYMENT_PLUGIN):shared:if(wince*|winrt) {
+ false:isEqual(QT_CURRENT_VERIFY, DEPLOYMENT_PLUGIN):shared:winrt {
QT_ITEM =
debug: QT_ITEM = $${QTPLUG}d4.dll
else: QT_ITEM = $${QTPLUG}4.dll
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 1e2d5c2423..f12cbb88fc 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -64,7 +64,7 @@ CONFIG = qt_build_extra $$CONFIG
cross_compile: \
CONFIG += force_bootstrap
-android|ios|winrt: \
+android|uikit|winrt: \
CONFIG += builtin_testdata
CONFIG += \
diff --git a/mkspecs/features/qt_build_extra.prf b/mkspecs/features/qt_build_extra.prf
index 378f5bbd7c..448da9b797 100644
--- a/mkspecs/features/qt_build_extra.prf
+++ b/mkspecs/features/qt_build_extra.prf
@@ -23,7 +23,8 @@ INCLUDEPATH += $$EXTRA_INCLUDEPATH
# The other flags are relevant only for actual libraries.
equals(TEMPLATE, aux): return()
-LIBS += $$EXTRA_LIBS
+QMAKE_LIBDIR += $$EXTRA_LIBDIR
+QMAKE_FRAMEWORKPATH += $$EXTRA_FRAMEWORKPATH
# Static libs need no rpaths
static: return()
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index b367bc12af..e50fdb767b 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -61,13 +61,15 @@ clang {
QMAKE_CXXFLAGS_WARN_ON += -Wvla
# GCC 5 introduced -Wdate-time
greaterThan(QT_GCC_MAJOR_VERSION, 4): QMAKE_CXXFLAGS_WARN_ON += -Wdate-time
+ # GCC 6 introduced these
+ greaterThan(QT_GCC_MAJOR_VERSION, 5): QMAKE_CXXFLAGS_WARN_ON += -Wshift-overflow=2 -Wduplicated-cond
}
warnings_are_errors:warning_clean {
# If the module declares that it has does its clean-up of warnings, enable -Werror.
# This setting is compiler-dependent anyway because it depends on the version of the
# compiler.
- clang:!ios {
+ clang:!uikit {
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4
# Regular clang 3.3-3.8
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
new file mode 100644
index 0000000000..1a663fe1dc
--- /dev/null
+++ b/mkspecs/features/qt_configure.prf
@@ -0,0 +1,1183 @@
+CONFIG -= qt debug_and_release
+load(configure_base)
+
+QT_CONFIGURE_REPORT =
+QT_CONFIGURE_NOTES =
+QT_CONFIGURE_WARNINGS =
+QT_CONFIGURE_ERRORS =
+
+defineTest(qtConfAddReport) {
+ QT_CONFIGURE_REPORT += "$$join(1, $$escape_expand(\\n))"
+ export(QT_CONFIGURE_REPORT)
+}
+
+defineTest(qtConfAddNote) {
+ QT_CONFIGURE_NOTES += "Note: $$join(1, $$escape_expand(\\n))"
+ export(QT_CONFIGURE_NOTES)
+}
+
+defineTest(qtConfAddWarning) {
+ QT_CONFIGURE_WARNINGS += "WARNING: $$join(1, $$escape_expand(\\n))"
+ export(QT_CONFIGURE_WARNINGS)
+}
+
+defineTest(qtConfAddError) {
+ QT_CONFIGURE_ERRORS += "ERROR: $$join(1, $$escape_expand(\\n))"
+ export(QT_CONFIGURE_ERRORS)
+}
+
+defineTest(qtConfCommandlineSetInput) {
+ arg = $${1}
+ val = $${2}
+ !isEmpty(config.commandline.options.$${arg}.name): \
+ arg = $$eval(config.commandline.options.$${arg}.name)
+
+ config.input.$$arg = $$val
+ export(config.input.$$arg)
+}
+
+defineReplace(qtConfGetNextCommandlineArg) {
+ c = $$take_first(QMAKE_EXTRA_ARGS)
+ export(QMAKE_EXTRA_ARGS)
+ return($$c)
+}
+
+defineReplace(qtConfPeekNextCommandlineArg) {
+ return($$first(QMAKE_EXTRA_ARGS))
+}
+
+defineTest(qtConfCommandline_boolean) {
+ opt = $${1}
+ val = $${2}
+ isEmpty(val): val = yes
+
+ !equals(val, yes):!equals(val, no) {
+ qtConfAddError("Invalid value given for boolean command line option '$$opt'.")
+ return()
+ }
+
+ qtConfCommandlineSetInput($$opt, $$val)
+}
+
+defineTest(qtConfCommandline_void) {
+ opt = $${1}
+ val = $${2}
+ !isEmpty(val) {
+ qtConfAddError("Command line option $$opt expects no argument ('$$val' given).")
+ return()
+ }
+
+ val = $$eval(config.commandline.options.$${opt}.value)
+ isEmpty(val): val = yes
+
+ qtConfCommandlineSetInput($$opt, $$val)
+}
+
+defineTest(qtConfCommandline_enum) {
+ opt = $${1}
+ val = $${2}
+ isEmpty(val): val = yes
+
+ # validate and map value
+ mapped = $$eval(config.commandline.options.$${opt}.values.$${val})
+ isEmpty(mapped) {
+ # just a list of allowed values
+ for (i, config.commandline.options.$${opt}.values._KEYS_) {
+ equals(config.commandline.options.$${opt}.values.$${i}, $$val) {
+ mapped = $$val
+ break()
+ }
+ }
+ }
+ isEmpty(mapped) {
+ qtConfAddError("Invalid value '$$val' supplied to command line option '$$opt'.")
+ return()
+ }
+
+ qtConfCommandlineSetInput($$opt, $$mapped)
+}
+
+defineTest(qtConfValidateValue) {
+ opt = $${1}
+ val = $${2}
+
+ validValues = $$eval(config.commandline.options.$${opt}.values._KEYS_)
+ isEmpty(validValues): \
+ return(true)
+
+ for (i, validValues) {
+ equals(config.commandline.options.$${opt}.values.$${i}, $$val): \
+ return(true)
+ }
+
+ qtConfAddError("Invalid value $$val supplied to command line option '$$opt'.")
+ return(false)
+}
+
+defineTest(qtConfCommandline_string) {
+ opt = $${1}
+ val = $${2}
+ isEmpty(val): val = $$qtConfGetNextCommandlineArg()
+
+ contains(val, "^-.*")|isEmpty(val) {
+ qtConfAddError("No value supplied to command line option $$opt")
+ return()
+ }
+
+ !qtConfValidateValue($$opt, $$val): \
+ return()
+
+ qtConfCommandlineSetInput($$opt, $$val)
+}
+
+defineTest(qtConfCommandline_optionalString) {
+ opt = $${1}
+ val = $${2}
+ isEmpty(val) {
+ v = $$qtConfPeekNextCommandlineArg()
+ contains(v, "^-.*")|isEmpty(v): \
+ val = "yes"
+ else: \
+ val = $$qtConfGetNextCommandlineArg()
+ }
+
+ !qtConfValidateValue($$opt, $$val): \
+ return()
+
+ qtConfCommandlineSetInput($$opt, $$val)
+}
+
+
+defineTest(qtConfCommandline_addString) {
+ opt = $${1}
+ val = $${2}
+ isEmpty(val): val = $$qtConfGetNextCommandlineArg()
+
+ contains(val, "^-.*")|isEmpty(val) {
+ qtConfAddError("No value supplied to command line option $$opt")
+ return()
+ }
+
+ !qtConfValidateValue($$opt, $$val): \
+ return()
+
+ !isEmpty(config.commandline.options.$${opt}.name): \
+ opt = $$eval(config.commandline.options.$${opt}.name)
+
+ config.input.$$opt += $$val
+ export(config.input.$$opt)
+}
+
+defineTest(qtConfParseCommandLine) {
+ for (ever) {
+ 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()
+ }
+
+ # parse out opt and val
+ contains(c, "^--?enable-(.*)") {
+ opt = $$replace(c, "^--?enable-(.*)", "\\1")
+ val = yes
+ } else: contains(c, "^--?(disable|no)-(.*)") {
+ opt = $$replace(c, "^--?(disable|no)-(.*)", "\\2")
+ val = no
+ } else: contains(c, "^--?qt-(.*)") {
+ opt = $$replace(c, "^--?qt-(.*)", "\\1")
+ val = qt
+ } else: contains(c, "^--?system-(.*)") {
+ opt = $$replace(c, "^--?system-(.*)", "\\1")
+ val = system
+ } else: contains(c, "^--?([^-].*)=(.*)") {
+ opt = $$replace(c, "^--?([^-].*)=(.*)", "\\1")
+ val = $$replace(c, "^--?([^-].*)=(.*)", "\\2")
+ } else: contains(c, "^--?([^-].*)") {
+ opt = $$replace(c, "^--?([^-].*)", "\\1")
+ val =
+ } else {
+ error("Invalid command line parameter $$c")
+ }
+
+ type = $$eval(config.commandline.options.$${opt})
+ isEmpty(type): \
+ type = $$eval(config.commandline.options.$${opt}.type)
+ isEmpty(type) {
+ # no match in the regular options, try matching the prefixes
+ for (p, config.commandline.prefix._KEYS_) {
+ e = "^-$${p}(.*)"
+ contains(c, $$e) {
+ opt = $$eval(config.commandline.prefix.$${p})
+ val = $$replace(c, $$e, "\\1")
+ type = "addString"
+ break()
+ }
+ }
+ }
+ # handle builtin [-no]-feature-xxx
+ isEmpty(type):contains(opt, "feature-(.*)") {
+ # simply skip for now
+ next()
+ }
+
+ isEmpty(type): \
+ error("Unknown command line option $$c")
+
+ call = "qtConfCommandline_$${type}"
+ !defined($$call, test): \
+ error("Command line option '$$c' has unknown type '$$type'.")
+
+ # now that we have opt and value, process it
+ $${call}($$opt, $$val)
+ }
+}
+
+defineTest(qtConfTest_shell) {
+ test = $$eval($${1}.test)
+ dir = $$replace(test, [^/]*$, "")
+ test = $$replace(test, ([^/]*/)*, "")
+ args = $$eval($${1}.args)
+ # replace any things like $$QMAKE_CXX by their values
+ eval(args = $$args)
+
+ test_dir = $$QMAKE_CONFIG_TESTS_DIR/$$dir
+ test_out_dir = $$shadowed($$test_dir)
+ test_cmd_base = "cd $$system_quote($$system_path($$test_out_dir)) &&"
+
+ mkpath($$test_out_dir)|error("Aborting.")
+
+ qtRunLoggedCommand("$$test_cmd_base $$test_dir/$${test} $${args}"): \
+ return(false)
+ return(true)
+}
+
+defineReplace(qtConfToolchainSupportsFlag) {
+ test_out_dir = $$shadowed($$QMAKE_CONFIG_TESTS_DIR)
+ test_cmd_base = "cd $$system_quote($$system_path($$test_out_dir)) &&"
+
+ conftest = "int main() { return 0; }"
+ write_file("$$test_out_dir/conftest.cpp", conftest)|error("Aborting.")
+
+ qtRunLoggedCommand("$$test_cmd_base $$QMAKE_CXX $${1} -o conftest-out conftest.cpp"): \
+ return(true)
+ return(false)
+}
+
+defineTest(qtConfTest_compilerSupportsFlag) {
+ flag = $$eval($${1}.flag)
+
+ return($$qtConfToolchainSupportsFlag($$flag))
+}
+
+defineTest(qtConfTest_linkerSupportsFlag) {
+ flag = $$eval($${1}.flag)
+
+ use_gold_linker: \
+ LFLAGS = -fuse-ld=gold
+
+ return($$qtConfToolchainSupportsFlag($$LFLAGS "-Wl,$$flag"))
+}
+
+defineReplace(qtConfFindInPath) {
+ ensurePathEnv()
+ for (dir, QMAKE_PATH_ENV) {
+ exists("$$dir/$${1}"): \
+ return("$$dir/$${1}")
+ }
+ return()
+}
+
+defineReplace(qtConfPkgConfigEnv) {
+ env =
+ !isEmpty(PKG_CONFIG_SYSROOT_DIR): env = "$${SETENV_PFX}PKG_CONFIG_SYSROOT_DIR=$${PKG_CONFIG_SYSROOT_DIR}$${SETENV_SFX} "
+ !isEmpty(PKG_CONFIG_LIBDIR): env = "$$env$${SETENV_PFX}PKG_CONFIG_LIBDIR=$${PKG_CONFIG_LIBDIR}$${SETENV_SFX} "
+ return($$env)
+}
+
+defineReplace(qtConfPkgConfig) {
+ host = $$1
+ isEmpty(host): host = false
+
+ $$host {
+ pkg_config = $$qtConfFindInPath("pkg-config")
+ isEmpty(pkg_config): \
+ return(false)
+ } else {
+ pkg_config = "$$qtConfPkgConfigEnv()$$PKG_CONFIG"
+ }
+
+ return($$pkg_config)
+}
+
+defineTest(qtConfPkgConfigPackageExists) {
+ isEmpty(1)|isEmpty(2): \
+ return(false)
+
+ !qtRunLoggedCommand("$${1} --exists --silence-errors $${2}"): \
+ return(false)
+
+ return(true)
+}
+
+defineReplace(qtConfPrepareArgs) {
+ arglist = $$split(1)
+ args =
+ for (a, arglist): \
+ args += $$system_quote($$a)
+ return($$args)
+}
+
+defineTest(qtConfTest_pkgConfig) {
+ pkg_config = $$qtConfPkgConfig($$eval($${1}.host))
+ args = $$qtConfPrepareArgs($$eval($${1}.pkg-config-args))
+
+ !qtConfPkgConfigPackageExists($$pkg_config, $$args): \
+ return(false)
+
+ $${1}.libs = $$system("$$pkg_config --libs $$args")
+ $${1}.cflags = $$system("$$pkg_config --cflags $$args")
+ includes = $$system("$$pkg_config --cflags-only-I $$args")
+ includes ~= s/^-I//g
+ $${1}.includedir = $$includes
+ version = $$system("$$pkg_config --modversion $$args")
+ $${1}.version = $$first(version)
+ export($${1}.libs)
+ export($${1}.cflags)
+ export($${1}.includedir)
+ export($${1}.version)
+ return(true)
+}
+
+defineTest(qtConfTest_getPkgConfigVariable) {
+ pkg_config = $$qtConfPkgConfig($$eval($${1}.host))
+ args = $$qtConfPrepareArgs($$eval($${1}.pkg-config-args))
+
+ !qtConfPkgConfigPackageExists($$pkg_config, $$args): \
+ return(false)
+
+ variable = $$eval($${1}.pkg-config-variable)
+ $${1}.value = $$system("$$pkg_config --variable=$$variable $$args")
+ export($${1}.value)
+ return(true)
+}
+
+defineTest(qtConfTest_compile) {
+ test = $$eval($${1}.test)
+ host = $$eval($${1}.host)
+ isEmpty(host): host = false
+
+ # get package config information
+ qtConfTest_pkgConfig($${1})
+
+ test_dir = $$QMAKE_CONFIG_TESTS_DIR/$$test
+ test_out_dir = $$shadowed($$test_dir)
+ !isEmpty($${1}.pro): \
+ test_dir = $$test_dir/$$eval($${1}.pro)
+ test_cmd_base = "cd $$system_quote($$system_path($$test_out_dir)) &&"
+
+ # Disable qmake features which are typically counterproductive for tests
+ qmake_args = "\"CONFIG -= qt debug_and_release app_bundle lib_bundle\""
+
+ # allow tests to behave differently depending on the type of library
+ # being built (shared/static). e.g. see config.tests/unix/icu
+ shared: \
+ qmake_configs = "shared"
+ else: \
+ qmake_configs = "static"
+
+ # add console to the CONFIG variable when running the tests, so that they
+ # can work with a regular main() entry point on Windows.
+ qmake_configs += "console"
+
+ qmake_args += "\"CONFIG += $$qmake_configs\""
+
+ # On WinRT we need to change the entry point as we cannot create windows
+ # applications
+ winrt: \
+ qmake_args += " \"QMAKE_LFLAGS += /ENTRY:main\""
+
+ !$$host {
+ # add compiler flags, these are set for the target and should not be applied to host tests
+ !isEmpty(EXTRA_DEFINES): \
+ qmake_args += "\"DEFINES += $$EXTRA_DEFINES\""
+ !isEmpty(EXTRA_LIBDIR) \
+ qmake_args += "\"QMAKE_LIBDIR += $$EXTRA_LIBDIR\""
+ !isEmpty(EXTRA_FRAMEWORKPATH) \
+ qmake_args += "\"QMAKE_FRAMEWORKPATH += $$EXTRA_FRAMEWORKPATH\""
+ !isEmpty(EXTRA_INCLUDEPATH): \
+ qmake_args += "\"INCLUDEPATH += $$EXTRA_INCLUDEPATH\""
+ qmake_args += $$EXTRA_QMAKE_ARGS
+ }
+
+ libs = $$eval($${1}.libs)
+ !isEmpty(libs): \
+ qmake_args += "\"LIBS += $$libs\""
+
+ includedir = $$eval($${1}.includedir)
+ !isEmpty(includedir): \
+ qmake_args += "\"INCLUDEPATH *= $$includedir\""
+
+ # Clean up after previous run
+ exists($$test_out_dir/Makefile): qtRunLoggedCommand("$$test_cmd_base $$QMAKE_MAKE distclean")
+
+ mkpath($$test_out_dir)|error("Aborting.")
+
+ !isEmpty(QMAKE_QTCONF): qtconfarg = -qtconf $$QMAKE_QTCONF
+
+ # add possible command line args
+ qmake_args += $$qtConfPrepareArgs($$eval($${1}.args))
+
+ qtRunLoggedCommand("$$test_cmd_base $$qtConfPkgConfigEnv()$$system_quote($$system_path($$QMAKE_QMAKE)) $$qtconfarg $$qmake_args $$shell_quote($$test_dir)") {
+ qtRunLoggedCommand("$$test_cmd_base $$QMAKE_MAKE"): \
+ return(true)
+ }
+
+ return(false)
+}
+
+defineTest(logn) {
+ log("$${1}$$escape_expand(\\n)")
+}
+
+defineTest(qtLogTestResult) {
+ !isEmpty($${1}.log) {
+ field = $$eval($${1}.log)
+ log_msg = $$eval($${1}.$$field)
+ msg = "test $$1 gave result $$log_msg"
+ } else: $${2} {
+ log_msg = yes
+ msg = "test $$1 succeeded"
+ } else {
+ log_msg = no
+ msg = "test $$1 FAILED"
+ }
+ $$QMAKE_CONFIG_VERBOSE: log_msg = $$msg
+ logn("$$log_msg")
+ write_file($$QMAKE_CONFIG_LOG, msg, append)
+}
+
+defineTest(qtConfIsBoolean) {
+ equals(1, "true")|equals(1, "false"): \
+ return(true)
+ return(false)
+}
+
+defineTest(qtRunSingleTest) {
+ tpfx = config.tests.$${1}
+ defined($${tpfx}.result, var): \
+ return()
+
+ type = $$eval($${tpfx}.type)
+ call = "qtConfTest_$$type"
+ !defined($$call, test): \
+ error("Configure test $${1} refers to nonexistent type $$type")
+
+ description = $$eval($${tpfx}.description)
+ !isEmpty(description) {
+ msg = "checking for $${description}... "
+ log($$msg)
+ $$QMAKE_CONFIG_VERBOSE: log("$$escape_expand(\\n)")
+ write_file($$QMAKE_CONFIG_LOG, msg, append)
+ }
+
+ msg = "executing config test $${1}"
+ write_file($$QMAKE_CONFIG_LOG, msg, append)
+
+ result = false
+ $${call}($${tpfx}): result = true
+
+ !isEmpty(description): qtLogTestResult($${tpfx}, $$result)
+ $${tpfx}.result = $$result
+ export($${tpfx}.result)
+}
+
+defineReplace(qtConfEvaluate) {
+ isEmpty(1): return(true)
+
+ expr = $${1}
+ expr ~= s/&&/ && /g
+ expr ~= s/\|\|/ || /g
+ expr ~= s/!/ ! /g
+ expr ~= s/\\(/ ( /g
+ expr ~= s/\\)/ ) /g
+ expr ~= s/ *== */==/g
+ expr ~= s/ *! = */!=/g
+ expr_list = $$eval($$list($$expr))
+ return($$qtConfEvaluateSubExpression($${1}, $$expr_list, 0))
+}
+
+defineReplace(qtConfEvaluateSingleExpression) {
+ e = $${2}
+
+ equals(e, true) {
+ result = true
+ } else: equals(e, false) {
+ result = false
+ } else: contains(e, "^[0-9]+$") {
+ # numbers
+ result = $$e
+ } else: contains(e, "^'.*'$") {
+ # quoted literals
+ result = $$replace(e, "^'(.*)'$", "\\1")
+ } else: contains(e, "^tests\..*") {
+ !qt_conf_tests_allowed: \
+ error("Expression '$${1}' refers to a test, which is not allowed at this stage of configuring.")
+ test = $$section(e, ".", 1, 1)
+ var = $$section(e, ".", 2, -1)
+ isEmpty(var): \
+ var = result
+ !contains(config.tests._KEYS_, $$test): \
+ error("Unknown test object $${test} in expression '$${1}'.")
+ qtRunSingleTest($$test)
+ result = $$eval(config.tests.$${test}.$${var})
+ } else: contains(e, "^features\..*") {
+ feature = $$section(e, ".", 1, 1)
+ var = $$section(e, ".", 2, -1)
+ isEmpty(var): \
+ var = available
+ !contains(config.features._KEYS_, $$feature): \
+ error("Unknown feature object $${feature} in expression '$${1}'.")
+ !qtConfCheckFeature($$feature): \
+ error("Expression '$$1' is accessing non-emitted feature $${feature}.")
+ result = $$eval(config.features.$${feature}.$${var})
+ } else: contains(e, "^config\..*") {
+ var = $$replace(e, "^config\.", "")
+ result = false
+ contains(CONFIG, $$var): result = true
+ } else: contains(e, "^arch\..*") {
+ var = $$replace(e, "^arch\.", "")
+ result = false
+ contains(QT_ARCH, $$var): result = true
+ } else: contains(e, "^input\..*") {
+ result = $$eval(config.$$e)
+ } else: contains(e, "^var\..*") {
+ var = $$replace(e, "^var\.", "")
+ result = $$eval($$var)
+ } else: contains(e, "^call\..*") {
+ call = $$replace(e, "^call\.", "qtConfFunc_")
+ !defined($$call, replace): \
+ error("Call $$call referenced in expression '$${1}' does not exist")
+ eval(result = \$\$"$$call"())
+ } else {
+ error("Unrecognized token $$e in expression '$${1}'")
+ }
+ return($$result)
+}
+
+defineReplace(qtConfEvaluateSubExpression) {
+ expr_list = $${2}
+ result = true
+ negate = false
+ runSubExpression = false
+ nesting_level = 0
+ for (n, $${3}..$$num_add($$size(expr_list), -1)) {
+ e = $$member(expr_list, $$n)
+ $$runSubExpression {
+ runSubExpression = false
+ result = $$qtConfEvaluateSubExpression($${1}, $$expr_list, $$n)
+ } else: isEqual(e, "(") {
+ isEqual(nesting_level, 0): runSubExpression = true
+ nesting_level = $$num_add($$nesting_level, 1)
+ next()
+ } else: isEqual(e, ")") {
+ nesting_level = $$num_add($$nesting_level, -1)
+ lessThan(nesting_level, 0): break()
+ next()
+ } else: greaterThan(nesting_level, 0) {
+ next()
+ } else: isEqual(e, "!") {
+ negate = true
+ next()
+ } else: isEqual(e, "&&") {
+ !qtConfIsBoolean($$result): \
+ error("Left hand side of && is non-boolean value '$$result' in expression '$${1}'")
+ !$$result: return(false)
+ } else: isEqual(e, "||") {
+ !qtConfIsBoolean($$result): \
+ error("Left hand side of || is non-boolean value '$$result' in expression '$${1}'")
+ $$result: return(true)
+ } else {
+ contains(e, ".*==.*") {
+ lhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, "==.*", ""))
+ rhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, ".*==", ""))
+ result = false
+ equals(lhs, $$rhs): result = true
+ } else: contains(e, ".*!=.*") {
+ lhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, "!=.*", ""))
+ rhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, ".*!=", ""))
+ result = false
+ !equals(lhs, $$rhs): result = true
+ } else {
+ result = $$qtConfEvaluateSingleExpression($${1}, $$e)
+ }
+ }
+ $$negate {
+ !qtConfIsBoolean($$result): \
+ error("Attempting to negate a non-boolean value '$$result' in expression '$${1}'")
+ $$result: \
+ result = false
+ else: \
+ result = true
+ negate = false
+ }
+ }
+ return($$result)
+}
+
+defineReplace(qtIsFeatureEnabled) {
+ enable = $$eval(config.features.$${1}.enable)
+ !isEmpty(enable) {
+ $$qtConfEvaluate($$enable): \
+ return(true)
+ } else {
+ equals(config.input.$${1}, "yes"): \
+ return(true)
+ }
+
+ return(false)
+}
+
+defineReplace(qtIsFeatureDisabled) {
+ disable = $$eval(config.features.$${1}.disable)
+ !isEmpty(disable) {
+ $$qtConfEvaluate($$disable): \
+ return(true)
+ } else {
+ equals(config.input.$${1}, "no"): \
+ return(true)
+ }
+
+ return(false)
+}
+
+defineReplace(qtConfCheckSingleCondition) {
+ result = $$qtConfEvaluate($$2)
+
+ !qtConfIsBoolean($$result): \
+ error("Evaluation of condition '$$2' yielded non-boolean value '$$result' in feature '$${1}'.")
+
+ !$$result {
+ $${3} {
+ qtConfAddError("Feature '$${1}' was enabled, but the pre-condition '$$2' failed.")
+ $$result = true
+ }
+ }
+ return($$result)
+}
+
+defineTest(qtConfCheckFeature) {
+ fpfx = config.features.$${1}
+
+ available = $$eval($${fpfx}.available)
+ !isEmpty(available): return(true)
+
+ # skip features that will not get emitted anyway
+ emitIf = $$qtConfEvaluate($$eval($${fpfx}.emitIf))
+ enabled = $$qtIsFeatureEnabled($$1)
+ disabled = $$qtIsFeatureDisabled($$1)
+
+ !$$emitIf {
+ $$enabled|$$disabled: \
+ qtConfAddWarning("Feature $${1} is insignificant in this configuration, ignoring related command line option(s).")
+ return(false)
+ }
+
+ $$disabled {
+ result = false
+ } else: !$$enabled:!$$qtConfEvaluate($$eval($${fpfx}.autoDetect)) {
+ # feature not auto-detected and not explicitly enabled
+ result = false
+ } else {
+ condition = $$eval($${fpfx}.condition)
+ !isEmpty(condition) {
+ result = $$qtConfCheckSingleCondition($$1, $$condition, $$enabled)
+ } else {
+ result = true
+ # check whether we have an array of conditions
+ for (i, $${fpfx}.condition._KEYS_) {
+ condition = $$eval($${fpfx}.condition.$$i)
+ result = $$qtConfCheckSingleCondition($$1, $$condition, $$enabled)
+ !$$result: break()
+ }
+ }
+ }
+ $${fpfx}.available = $$result
+ export($${fpfx}.available)
+
+ for (i, config.features.$${feature}.output._KEYS_): \
+ qtConfProcessOneOutput($$feature, $$i)
+
+ return(true)
+}
+
+
+defineTest(qtConfProcessFeatures) {
+ priorities = 0
+ for (feature, config.features._KEYS_): \
+ priorities += $$eval(config.features.$${feature}.priority)
+ priorities = $$unique(priorities)
+
+ for (p, priorities): \
+ opriorities += $$format_number($$num_add($$p, 10000), width=5 zeropad)
+ opriorities = $$sorted(opriorities)
+
+ priorities =
+ for (op, opriorities): \
+ priorities += $$num_add($$op, -10000)
+
+ for (priority, priorities) {
+ for (feature, config.features._KEYS_) {
+ p = $$eval(config.features.$${feature}.priority)
+ isEmpty(p): p = 0
+ equals(p, $$priority): \
+ qtConfCheckFeature($$feature)
+ }
+ }
+}
+
+#
+# reporting
+#
+
+QT_CONF_REPORT_PADDING = "........................................"
+
+defineTest(qtConfReportPadded) {
+ pad = $$num_add($$str_size($$QT_CONF_REPORT_PADDING), -$$str_size($${1}))
+ lessThan(pad, 0): pad = 0
+ str = "$$1 $$str_member($$QT_CONF_REPORT_PADDING, 0, $$pad)"
+
+ qtConfAddReport("$$str $${2}")
+}
+
+defineReplace(qtConfCollectFeatures) {
+ l =
+ for (feature, $$list($${1})) {
+ $$eval(config.features.$${feature}.available): \
+ l += $$feature
+ }
+
+ isEmpty(l): return("<none>")
+ return($$join(l, ' '))
+}
+
+defineTest(qtConfReport_featureList) {
+ qtConfReportPadded($${1}, $$qtConfCollectFeatures($${2}))
+}
+
+defineReplace(qtConfFindFirstAvailableFeature) {
+ for (feature, $$list($${1})) {
+ isEmpty(config.features.$${feature}._KEYS_): \
+ error("Asking for a report on undefined feature $${2}.")
+ $$eval(config.features.$${feature}.available): \
+ return($$feature)
+ }
+
+ return("<none>")
+}
+
+defineTest(qtConfReport_firstAvailableFeature) {
+ qtConfReportPadded($${1}, $$qtConfFindFirstAvailableFeature($${2}))
+}
+
+defineTest(qtConfReport_feature) {
+ !contains(config.features._KEYS_, $$2): \
+ error("Asking for a report on undefined feature $${2}.")
+
+ # hide report for not emitted features
+ isEmpty(config.features.$${2}.available): \
+ return()
+
+ $$eval(config.features.$${2}.available) {
+ result = "yes"
+ !isEmpty(3): result = "$${3}"
+ } else {
+ result = "no"
+ !isEmpty(4): result = "$${4}"
+ }
+
+ qtConfReportPadded($${1}, $$result)
+}
+
+defineTest(qtConfReport_note) {
+ qtConfAddNote($${1})
+}
+
+defineTest(qtConfReport_warning) {
+ qtConfAddWarning($${1})
+}
+
+defineTest(qtConfReport_error) {
+ qtConfAddError($${1})
+}
+
+defineTest(qtConfCreateReportRecurse) {
+ equals(2, false) {
+ indent = ""
+ recurse = false
+ } else {
+ indent = $${2}
+ recurse = true
+ }
+
+ keys = $$eval($${1}._KEYS_)
+ for (n, keys) {
+ entry = $${1}.$$n
+ subKeys = $$eval($${entry}._KEYS_)
+ contains(subKeys, condition) {
+ condition = $$eval($${entry}.condition)
+ r = $$qtConfEvaluate($$condition)
+ !qtConfIsBoolean($$r): \
+ error("Evaluation of condition '$$condition' in report entry $${entry} yielded non-boolean value '$$r'.")
+ !$$r: next()
+ }
+ contains(subKeys, "section") {
+ !$$recurse: \
+ error("Report type 'section' is not allowed in '$$1'.")
+ section = $$eval($${entry}.section)
+ qtConfAddReport("$$indent$$section:")
+ qtConfCreateReportRecurse("$${entry}.entries", "$$indent ")
+ } else: !isEmpty($${entry}) {
+ feature = $$eval($${entry})
+ text = $$eval(config.features.$${feature}.description)
+ qtConfReport_feature($$indent$$text, $$feature)
+ } else {
+ text = $$eval($${entry}.message)
+ isEmpty($${entry}.type): \
+ error("Report entry $${entry} doesn't define a type.")
+ r = "qtConfReport_$$eval($${entry}.type)"
+ !defined($$r, test): \
+ error("Undefined report type $$eval($${entry}.type) used in report entry $${entry}.")
+ args = $$eval($${entry}.args)
+ $${r}($$indent$${text}, $$args)
+ }
+ }
+}
+
+defineTest(qtConfProcessEarlyChecks) {
+ qtConfCreateReportRecurse(config.earlyReport, false)
+ qtConfCheckErrors()
+}
+
+
+defineTest(qtConfCreateReport) {
+ qtConfAddReport(" ")
+ qtConfCreateReportRecurse(config.report, false)
+}
+
+defineTest(qtConfCreateSummary) {
+ qtConfCreateReportRecurse(config.summary, "")
+}
+
+defineTest(qtConfPrintReport) {
+ for (n, QT_CONFIGURE_REPORT): \
+ logn($$n)
+ logn(" ")
+
+ !isEmpty(QT_CONFIGURE_NOTES) {
+ for (n, QT_CONFIGURE_NOTES): \
+ logn($$n)
+ logn(" ")
+ }
+
+ !isEmpty(QT_CONFIGURE_WARNINGS) {
+ for (w, QT_CONFIGURE_WARNINGS): \
+ logn($$w)
+ logn(" ")
+ }
+
+ !isEmpty(QT_CONFIGURE_ERRORS) {
+ for (e, QT_CONFIGURE_ERRORS): \
+ logn($$e)
+ !$$QMAKE_CONFIG_VERBOSE: logn("Check config.log for details.")
+ logn(" ")
+
+ !equals(config.input.continue, yes): \
+ error("Aborting.")
+ }
+}
+
+defineTest(qtConfCheckErrors) {
+ !isEmpty(QT_CONFIGURE_ERRORS):!equals(config.input.continue, yes): \
+ qtConfPrintReport()
+}
+
+#
+# output generation
+#
+
+defineReplace(qtConfOutputSelectProFile) {
+ !isEmpty($${1}.public) {
+ $$eval($${1}.public): \
+ return(publicPro)
+ }
+ return(privatePro)
+}
+
+
+# qtConfOutputVar(modifier, output, name, value)
+defineTest(qtConfOutputVar) {
+ modifier = $$1
+ output = $$2
+ name = $$3
+ value = $$val_escape(4)
+
+ !isEmpty(config.output.$${output}.assign.$${name}): \
+ error("Trying to overwrite assigned variable '$$name' in '$$output' using modifier '$$modifier'.")
+
+ equals(modifier, assign) {
+ !isEmpty(config.output.$${output}.append.$${name})|!isEmpty(config.output.$${output}.remove.$${name}): \
+ error("Trying to assign variable '$$name' in '$$output', which has already appended or removed parts.")
+ config.output.$${output}.$${modifier}.$${name} = $$value
+ } else: equals(modifier, append) {
+ contains(config.output.$${output}.remove.$${name}, $$value): \
+ error("Trying to append removed '$$value' to variable '$$name' in '$$output'.")
+ config.output.$${output}.$${modifier}.$${name} += $$value
+ } else: equals(modifier, remove) {
+ contains(config.output.$${output}.append.$${name}, $$value): \
+ error("Trying to remove appended '$$value' to variable '$$name' in '$$output'.")
+ config.output.$${output}.$${modifier}.$${name} += $$value
+ } else {
+ error("Invalid modifier '$$modifier' passed to qtConfOutputVar.")
+ }
+ config.output.$${output}.$${modifier}._KEYS_ *= $${name}
+ export(config.output.$${output}.$${modifier}.$${name})
+ export(config.output.$${output}.$${modifier}._KEYS_)
+}
+
+defineTest(qtConfOutputVarHelper) {
+ negative = $$eval($${2}.negative)
+ isEmpty(negative): negative = false
+ !$${3}:!$$negative: return()
+ $${3}:$$negative: return()
+
+ output = $$qtConfOutputSelectProFile($${2})
+ name = $$eval($${2}.name)
+ isEmpty(name): \
+ error("Output type 'var$$title($$1)' used in feature '$$eval($${2}.feature)' without a 'name' entry.")
+
+ value = $$qtConfEvaluate($$eval($${2}.value))
+ qtConfOutputVar($$1, $$output, $$name, $$value)
+}
+
+defineTest(qtConfOutput_varAssign) {
+ qtConfOutputVarHelper(assign, $$1, $$2)
+}
+
+defineTest(qtConfOutput_varAppend) {
+ qtConfOutputVarHelper(append, $$1, $$2)
+}
+
+defineTest(qtConfOutput_varRemove) {
+ qtConfOutputVarHelper(remove, $$1, $$2)
+}
+
+defineTest(qtConfOutputConfigVar) {
+ pro = $$3
+ var = $$4
+ negative = $$eval($${1}.negative)
+ isEmpty(negative): negative = false
+
+ val = $$eval($${1}.name)
+ isEmpty(val) {
+ val = $$eval($${1}.feature)
+ $$negative: val = no-$$val
+ }
+
+ $${2} {
+ !$$negative: qtConfOutputVar(append, $$pro, $$var, $$val)
+ } else {
+ $$negative: qtConfOutputVar(append, $$pro, $$var, $$val)
+ }
+}
+
+defineTest(qtConfOutput_publicQtConfig) {
+ qtConfOutputConfigVar($$1, $$2, "publicPro", "QT_CONFIG")
+}
+
+defineTest(qtConfOutput_publicConfig) {
+ qtConfOutputConfigVar($$1, $$2, "publicPro", "CONFIG")
+}
+
+defineTest(qtConfOutput_privateConfig) {
+ qtConfOutputConfigVar($$1, $$2, "privatePro", "CONFIG")
+}
+
+defineTest(qtConfOutputSetDefine) {
+ config.output.$${1}.$${2} = $${3}
+ config.output.$${1}._KEYS_ *= $${2}
+ export(config.output.$${1}.$${2})
+ export(config.output.$${1}._KEYS_)
+}
+
+defineTest(qtConfOutput_define) {
+ output = publicHeader
+ define = $$eval($${1}.name)
+ value = $$qtConfEvaluate($$eval($${1}.value))
+ isEmpty(define): \
+ error("Output type 'define' used in feature '$$eval($${1}.feature)' without a 'name' entry.")
+
+ negative = $$eval($${1}.negative)
+ isEmpty(negative): negative = false
+
+ $${2} {
+ !$$negative: qtConfOutputSetDefine($$output, $$define, $$value)
+ } else {
+ $$negative: qtConfOutputSetDefine($$output, $$define, $$value)
+ }
+}
+
+defineTest(qtConfOutput_feature) {
+ name = "$$eval($${1}.name)"
+ isEmpty(name): \
+ name = $$eval($${1}.feature)
+
+ $${2} {
+ qtConfOutputVar(append, "publicPro", "QT_CONFIG", $$name)
+ } else {
+ f = $$upper($$replace(name, -, _))
+ qtConfOutputSetDefine("publicHeader", "QT_NO_$$f")
+ }
+}
+
+# currently this is somewhat inconsistent, as the feature is output to the public pro file,
+# whereas the define is being added to the private pro file.
+# This should get cleaned up to add to the private pro and header instead.
+defineTest(qtConfOutput_privateFeature) {
+ name = "$$eval($${1}.name)"
+ isEmpty(name): \
+ name = $$eval($${1}.feature)
+
+ $${2} {
+ qtConfOutputVar(append, "publicPro", "QT_CONFIG", $$name)
+ } else {
+ f = $$upper($$replace(name, -, _))
+ qtConfOutputVar(append, "privatePro", "DEFINES", "QT_NO_$$f")
+ }
+}
+
+
+defineTest(qtConfOutput_library) {
+ !$${2}: return()
+
+ output = privatePro
+ name = "$$eval($${1}.name)"
+ isEmpty(name): \
+ name = $$eval($${1}.feature)
+ NAME = $$upper($$replace(name, [-.], _))
+
+ lookup = "config.tests.$$eval($${1}.test)"
+ isEmpty(lookup): \
+ error("Output type 'library' used in feature '$$eval($${1}.feature)' without a 'test' entry.")
+
+ libs = $$eval($${lookup}.libs)
+ cflags = $$eval($${lookup}.cflags)
+ includes = $$eval($${lookup}.includedir)
+ version = $$split($${lookup}.version, '.')
+
+ !isEmpty(libs): qtConfOutputVar(assign, $$output, QMAKE_LIBS_$$NAME, $$libs)
+ !isEmpty(cflags): qtConfOutputVar(assign, $$output, QMAKE_CFLAGS_$$NAME, $$cflags)
+ !isEmpty(includes): qtConfOutputVar(assign, $$output, QMAKE_INCDIR_$$NAME, $$includes)
+ !isEmpty(version) {
+ qtConfOutputVar(assign, $$output, QMAKE_$${NAME}_VERSION_MAJOR, $$first(version))
+ qtConfOutputVar(assign, $$output, QMAKE_$${NAME}_VERSION_MINOR, $$member(version, 1))
+ qtConfOutputVar(assign, $$output, QMAKE_$${NAME}_VERSION_PATCH, $$member(version, 2))
+ }
+ export(config.output.$${output})
+}
+
+defineTest(qtConfProcessOneOutput) {
+ feature = $${1}
+ fpfx = config.features.$${feature}
+ opfx = $${fpfx}.output.$${2}
+
+ condition = $$eval($${opfx}.condition)
+ !isEmpty(condition):!$$qtConfEvaluate($$condition): \
+ return()
+
+ call = $$eval($${opfx}.type)
+ isEmpty(call) {
+ # output is just a string, not an object
+ call = $$eval($$opfx)
+ }
+ !defined("qtConfOutput_$$call", test): \
+ error("Undefined type '$$call' in output '$$2' of feature '$$feature'.")
+
+ isEmpty($${opfx}.feature): \
+ $${opfx}.feature = $$feature
+
+ condition = $$eval($${opfx}.condition)
+ !isEmpty(condition) {
+ !$$qtConfEvaluate($$condition): \
+ return(false)
+ }
+
+ qtConfOutput_$${call}($$opfx, $$eval($${fpfx}.available))
+}
+
+defineTest(qtConfProcessOutput) {
+ # write it to the output files
+ for (type, config.files._KEYS_) {
+ file = $$OUT_PWD/$$eval(config.files.$${type})
+ contains(type, ".*Pro") {
+ for (k, config.output.$${type}.assign._KEYS_): \
+ config.output.$$type += "$$k = $$eval(config.output.$${type}.assign.$$k)"
+ for (k, config.output.$${type}.remove._KEYS_): \
+ config.output.$$type += "$$k -= $$eval(config.output.$${type}.remove.$$k)"
+ for (k, config.output.$${type}.append._KEYS_): \
+ config.output.$$type += "$$k += $$eval(config.output.$${type}.append.$$k)"
+ } else {
+ for (define, config.output.$${type}._KEYS_) {
+ value = $$eval(config.output.$${type}.$${define})
+ config.output.$$type += "$${LITERAL_HASH}ifndef $$define"
+ config.output.$$type += "$${LITERAL_HASH}define $$define $$value"
+ config.output.$$type += "$${LITERAL_HASH}endif"
+ }
+ }
+ defined(qtConfOutputPostProcess_$${type}, test): \
+ qtConfOutputPostProcess_$${type}()
+
+ write_file($$file, config.output.$${type})|error("Aborting.")
+ }
+}
+
+#
+# tie it all together
+#
+
+defineTest(qtConfigure) {
+ # load configuration data
+ configure_data = $$cat($${1}, blob)
+ !parseJson(configure_data, config): \
+ error("Invalid or non-existent file $${1}.")
+
+ qtConfParseCommandLine()
+
+ # do early checks, mainly to validate the command line
+ qtConfProcessEarlyChecks()
+
+ CONFIG += qt_conf_tests_allowed
+ logn(" ")
+ logn("Running configuration tests...")
+
+ # process all features
+ qtConfProcessFeatures()
+
+ # generate files and reports
+ qtConfProcessOutput()
+ qtConfCreateReport()
+ qtConfCreateSummary()
+
+ logn("Done running configuration tests.")
+ logn(" ")
+}
+
+qtConfigure($$_PRO_FILE_PWD_/configure.json)
+
+logn("Configure summary:")
+logn(" ")
+
+qtConfPrintReport()
diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf
index 54641ce5a1..6dd4a36b5e 100644
--- a/mkspecs/features/qt_functions.prf
+++ b/mkspecs/features/qt_functions.prf
@@ -1,6 +1,6 @@
defineReplace(qtPlatformTargetSuffix) {
- ios:CONFIG(simulator, simulator|device): \
+ uikit:CONFIG(simulator, simulator|device): \
suffix = _$${simulator.sdk}
else: \
suffix =
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index d9011f5482..923ac73200 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -74,7 +74,7 @@ header_module {
TEMPLATE = lib
}
DESTDIR = $$MODULE_BASE_OUTDIR/lib
-win32:!wince:!prefix_build: DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
+win32:!prefix_build: DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
CONFIG += qmake_cache target_qt
@@ -114,10 +114,13 @@ lib_bundle {
CONFIG += sliced_bundle
header_module {
CONFIG += bundle
+ QMAKE_BUNDLE_NAME = $$TARGET
QMAKE_BUNDLE_EXTENSION = .framework
QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib
}
- !debug_and_release|!build_all|CONFIG(release, debug|release) {
+ !build_all| \
+ if(if(!debug_and_release|CONFIG(release, debug|release)): \
+ if(!simulator_and_device|CONFIG(device, simulator|device))) {
FRAMEWORK_HEADERS.version = Versions
FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
FRAMEWORK_HEADERS.path = Headers
diff --git a/mkspecs/features/qt_parts.prf b/mkspecs/features/qt_parts.prf
index 877bd60321..fa62f40e35 100644
--- a/mkspecs/features/qt_parts.prf
+++ b/mkspecs/features/qt_parts.prf
@@ -60,7 +60,7 @@ exists($$_PRO_FILE_PWD_/tests/tests.pro) {
sub_tests.CONFIG = no_default_install
!contains(QT_BUILD_PARTS, tests) {
sub_tests.CONFIG += no_default_target
- } else: !ios {
+ } else: !uikit {
# Make sure these are there in case we need them
sub_tools.CONFIG -= no_default_target
sub_examples.CONFIG -= no_default_target
diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf
index 8e47d91133..e11b543cb4 100644
--- a/mkspecs/features/qt_plugin.prf
+++ b/mkspecs/features/qt_plugin.prf
@@ -92,5 +92,4 @@ CONFIG += create_cmake
load(qt_targets)
load(qt_common)
-wince: LIBS += $$QMAKE_LIBS_GUI
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
diff --git a/mkspecs/features/uikit/bitcode.prf b/mkspecs/features/uikit/bitcode.prf
new file mode 100644
index 0000000000..ecc6542b3c
--- /dev/null
+++ b/mkspecs/features/uikit/bitcode.prf
@@ -0,0 +1,13 @@
+lessThan(QMAKE_XCODE_VERSION, "7.0") {
+ warning("You need to update Xcode to version 7 or newer to support bitcode")
+} else {
+ release:device {
+ QMAKE_CFLAGS += -fembed-bitcode
+ QMAKE_CXXFLAGS += -fembed-bitcode
+ QMAKE_OBJECTIVE_CFLAGS += -fembed-bitcode
+ } else {
+ QMAKE_CFLAGS += -fembed-bitcode-marker
+ QMAKE_CXXFLAGS += -fembed-bitcode-marker
+ QMAKE_OBJECTIVE_CFLAGS += -fembed-bitcode-marker
+ }
+}
diff --git a/mkspecs/features/uikit/default_post.prf b/mkspecs/features/uikit/default_post.prf
new file mode 100644
index 0000000000..7c92a24556
--- /dev/null
+++ b/mkspecs/features/uikit/default_post.prf
@@ -0,0 +1,109 @@
+equals(TEMPLATE, app):qt {
+ # If the application uses Qt, it needs to be an application bundle
+ # to be able to deploy and run on iOS. The only exception to this
+ # is if you're working with a jailbroken device and can run the
+ # resulting binary from the console/over SSH, but that's not a
+ # use-case we care about, so no need to complicate the logic.
+ CONFIG *= app_bundle
+
+ # For Qt applications we want Xcode project files as the generated output,
+ # but since qmake doesn't handle the transition between makefiles and Xcode
+ # project files (which happens when using subdirs), we can't just override
+ # MAKEFILE_GENERATOR. Instead, we generate the Xcode project by spawning a
+ # child qmake process with -spec macx-xcode and let the top level qmake
+ # process generate a wrapper makefile that forwards everything to xcodebuild.
+ equals(MAKEFILE_GENERATOR, UNIX): \
+ CONFIG = xcodebuild $$CONFIG
+}
+
+load(default_post)
+
+macx-xcode {
+ device_family.name = TARGETED_DEVICE_FAMILY
+ ios: device_family.value = $$QMAKE_IOS_TARGETED_DEVICE_FAMILY
+ tvos: device_family.value = $$QMAKE_TVOS_TARGETED_DEVICE_FAMILY
+ QMAKE_MAC_XCODE_SETTINGS += device_family
+
+ ios {
+ # If QMAKE_BUNDLE_DATA contains an asset catalog that includes an
+ # AppIcon.appiconset, we configure Xcode to use it for app icons.
+ for(bundle_data, QMAKE_BUNDLE_DATA) {
+ for(bundle_file, $${bundle_data}.files) {
+ !contains(bundle_file, .*\.xcassets$): next()
+ !exists($$absolute_path($$bundle_file/AppIcon.appiconset, $$_PRO_FILE_PWD_)): next()
+
+ asset_catalog_appicon.name = "ASSETCATALOG_COMPILER_APPICON_NAME"
+ asset_catalog_appicon.value = "AppIcon"
+ QMAKE_MAC_XCODE_SETTINGS += asset_catalog_appicon
+ break()
+ }
+ !isEmpty(asset_catalog_appicon.name): break()
+ }
+
+ # Set up default 4-inch iPhone/iPod launch image so that our apps
+ # support the full screen resolution of those devices.
+ qmake_launch_image = Default-568h@2x.png
+ qmake_copy_image.input = $$QMAKESPEC/$$qmake_launch_image
+ qmake_copy_image.output = $$OUT_PWD/$${TARGET}.xcodeproj/$$qmake_launch_image
+ qmake_copy_image.CONFIG = verbatim
+ QMAKE_SUBSTITUTES += qmake_copy_image
+ qmake_launch_images.files = $$qmake_copy_image.output
+ QMAKE_BUNDLE_DATA += qmake_launch_images
+
+ lessThan(QMAKE_XCODE_VERSION, "6.0") {
+ warning("You need to update Xcode to version 6 or newer to fully support iPhone6/6+")
+ } else {
+ # Set up default LaunchScreen to support iPhone6/6+
+ qmake_launch_screen = LaunchScreen.xib
+ qmake_copy_launch_screen.input = $$QMAKESPEC/$$qmake_launch_screen
+ qmake_copy_launch_screen.output = $$OUT_PWD/$${TARGET}.xcodeproj/$$qmake_launch_screen
+ QMAKE_SUBSTITUTES += qmake_copy_launch_screen
+ qmake_launch_screens.files = $$qmake_copy_launch_screen.output
+ QMAKE_BUNDLE_DATA += qmake_launch_screens
+ }
+ }
+}
+
+macx-xcode {
+ arch_device.name = "ARCHS[sdk=$${device.sdk}*]"
+ arch_simulator.name = "ARCHS[sdk=$${simulator.sdk}*]"
+ ios {
+ arch_device.value = $$QMAKE_IOS_DEVICE_ARCHS
+ arch_simulator.value = $$QMAKE_IOS_SIMULATOR_ARCHS
+ QMAKE_XCODE_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS $$QMAKE_IOS_SIMULATOR_ARCHS
+ }
+ tvos {
+ arch_device.value = $$QMAKE_TVOS_DEVICE_ARCHS
+ arch_simulator.value = $$QMAKE_TVOS_SIMULATOR_ARCHS
+ QMAKE_XCODE_ARCHS = $$QMAKE_TVOS_DEVICE_ARCHS $$QMAKE_TVOS_SIMULATOR_ARCHS
+ }
+
+ QMAKE_MAC_XCODE_SETTINGS += arch_device arch_simulator
+
+ only_active_arch.name = ONLY_ACTIVE_ARCH
+ only_active_arch.value = YES
+ only_active_arch.build = debug
+ QMAKE_MAC_XCODE_SETTINGS += only_active_arch
+} else {
+ # Be more specific about which architecture we're targeting
+ contains(QT_ARCH, arm.*) {
+ ios: VALID_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS
+ tvos: VALID_ARCHS = $$QMAKE_TVOS_DEVICE_ARCHS
+ } else {
+ ios: VALID_ARCHS = $$QMAKE_IOS_SIMULATOR_ARCHS
+ tvos: VALID_ARCHS = $$QMAKE_TVOS_SIMULATOR_ARCHS
+ }
+
+ single_arch: VALID_ARCHS = $$first(VALID_ARCHS)
+
+ ACTIVE_ARCHS = $(filter $(EXPORT_VALID_ARCHS), $(ARCHS))
+ ARCH_ARGS = $(foreach arch, $(if $(EXPORT_ACTIVE_ARCHS), $(EXPORT_ACTIVE_ARCHS), $(EXPORT_VALID_ARCHS)), -arch $(arch))
+
+ QMAKE_EXTRA_VARIABLES += VALID_ARCHS ACTIVE_ARCHS ARCH_ARGS
+
+ arch_flags = $(EXPORT_ARCH_ARGS)
+
+ QMAKE_CFLAGS += $$arch_flags
+ QMAKE_CXXFLAGS += $$arch_flags
+ QMAKE_LFLAGS += $$arch_flags
+}
diff --git a/mkspecs/features/uikit/default_pre.prf b/mkspecs/features/uikit/default_pre.prf
new file mode 100644
index 0000000000..ff45c1de0d
--- /dev/null
+++ b/mkspecs/features/uikit/default_pre.prf
@@ -0,0 +1,31 @@
+
+load(default_pre)
+
+# In case Qt was built for a specific SDK
+!contains(QT_CONFIG, simulator_and_device):contains(QMAKE_MAC_SDK, ^$${simulator.sdk}.*): \
+ CONFIG += simulator $${simulator.sdk}
+
+# Check for supported Xcode versions
+lessThan(QMAKE_XCODE_VERSION, "4.3"): \
+ error("This mkspec requires Xcode 4.3 or later")
+
+build_pass:simulator {
+ # For a simulator_and_device build all the config tests
+ # are based on the iPhoneOS ARM SDK, but we know that the simulator
+ # is i386 and that we support SSE/SSE2.
+ QT_ARCH = i386
+ QT_CPU_FEATURES.i386 = sse sse2
+ DEFINES += QT_COMPILER_SUPPORTS_SSE2
+ CONFIG -= neon
+ CONFIG += sse sse2
+}
+build_pass:appletvsimulator {
+ # For a simulator_and_device build all the config tests
+ # are based on the AppleTVOS ARM SDK, but we know that the simulator
+ # is x64 and that we support SSE/SSE2.
+ QT_ARCH = x64
+ QT_CPU_FEATURES.x64 = sse sse2
+ DEFINES += QT_COMPILER_SUPPORTS_SSE2
+ CONFIG -= neon
+ CONFIG += sse sse2
+}
diff --git a/mkspecs/features/uikit/device_destinations.sh b/mkspecs/features/uikit/device_destinations.sh
new file mode 100755
index 0000000000..af7cb91e85
--- /dev/null
+++ b/mkspecs/features/uikit/device_destinations.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+booted_simulator=$(xcrun simctl list devices | grep -E '$1' | grep -v unavailable | grep Booted | perl -lne 'print $2 if /\((.*?)\)/')
+echo "SIMULATOR_DEVICES = $booted_simulator"
+
+xcodebuild test -scheme $2 -destination 'id=0' -destination-timeout 1 2>&1| sed -n 's/{ \(platform:.*\) }/\1/p' | while read destination; do
+ id=$(echo $destination | sed -n -E 's/.*id:([^ ,]+).*/\1/p')
+ echo $destination | tr ',' '\n' | while read keyval; do
+ key=$(echo $keyval | cut -d ':' -f 1 | tr '[:lower:]' '[:upper:]')
+ val=$(echo $keyval | cut -d ':' -f 2)
+ echo "%_$id: DESTINATION_${key} = $val"
+
+ if [ $key = 'PLATFORM' ]; then
+ if [ "$val" = "iOS" ]; then
+ echo "HARDWARE_DEVICES += $id"
+ elif [ "$val" = "iOS Simulator" -a "$id" != "$booted_simulator" ]; then
+ echo "SIMULATOR_DEVICES += $id"
+ elif [ "$val" = "tvOS" ]; then
+ echo "HARDWARE_DEVICES += $id"
+ elif [ "$val" = "tvOS Simulator" -a "$id" != "$booted_simulator" ]; then
+ echo "SIMULATOR_DEVICES += $id"
+ fi
+ fi
+ done
+ echo
+done
diff --git a/mkspecs/features/uikit/exclusive_builds_post.prf b/mkspecs/features/uikit/exclusive_builds_post.prf
new file mode 100644
index 0000000000..1fb0a55846
--- /dev/null
+++ b/mkspecs/features/uikit/exclusive_builds_post.prf
@@ -0,0 +1,8 @@
+
+xcodebuild {
+ # Prevent qmake from generating empty output dirs for each exclusive build,
+ # as Xcode will do this by itself, and with a different name.
+ QMAKE_DIR_REPLACE =
+}
+
+load(exclusive_builds_post)
diff --git a/mkspecs/features/uikit/qt.prf b/mkspecs/features/uikit/qt.prf
new file mode 100644
index 0000000000..af047be466
--- /dev/null
+++ b/mkspecs/features/uikit/qt.prf
@@ -0,0 +1,33 @@
+
+qt_depends = $$resolve_depends(QT, "QT.")
+equals(TEMPLATE, app):contains(qt_depends, gui(-private)?) {
+ LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
+
+ lib_name = qios
+ lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
+ LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+
+ !bitcode {
+ # By marking qt_registerPlatformPlugin as undefined, we ensure that
+ # the plugin.o translation unit is considered for inclusion in
+ # the final binary, which in turn ensures that the plugin's
+ # static initializer is included and run.
+ QMAKE_LFLAGS += -u _qt_registerPlatformPlugin
+
+ # We do link and dependency resolution for the platform plugin
+ # manually, since we know we always need the plugin, so we don't
+ # need to generate an import for it.
+ QTPLUGIN.platforms = -
+ }
+
+ !no_main_wrapper {
+ # The LC_MAIN load command available in iOS 6.0 and above allows dyld to
+ # directly call the entrypoint instead of going through _start in crt.o.
+ # Passing -e to the linker changes the entrypoint from _main to our custom
+ # wrapper that calls UIApplicationMain and dispatches back to main() once
+ # the application has started up and is ready to initialize QApplication.
+ QMAKE_LFLAGS += -Wl,-e,_qt_main_wrapper
+ }
+}
+
+load(qt)
diff --git a/mkspecs/features/uikit/qt_config.prf b/mkspecs/features/uikit/qt_config.prf
new file mode 100644
index 0000000000..71e0982f7e
--- /dev/null
+++ b/mkspecs/features/uikit/qt_config.prf
@@ -0,0 +1,18 @@
+load(qt_config)
+
+isEmpty(QT_ARCH) {
+ # The configure tests are run without QT_ARCH being resolved yet, which
+ # means we fail to pass -arch to the compiler, resulting in broke tests.
+ # As the Xcode toolchain doesn't seem to have a way to auto-detect the
+ # arch based on the SDK, we have to hard-code the arch for configure.
+ contains(QMAKE_MAC_SDK, $${device.sdk}.*) {
+ QT_ARCH = arm
+ } else { # Simulator
+ ios: QT_ARCH = i386
+ tvos: QT_ARCH = x64
+ }
+
+ # Prevent the arch/config tests from building as multi-arch binaries,
+ # as we only want the lowest common denominator features.
+ CONFIG += single_arch
+}
diff --git a/mkspecs/features/uikit/qt_parts.prf b/mkspecs/features/uikit/qt_parts.prf
new file mode 100644
index 0000000000..81814a62b0
--- /dev/null
+++ b/mkspecs/features/uikit/qt_parts.prf
@@ -0,0 +1,5 @@
+
+# Disable tests for anything but qtbase for now
+!equals(TARGET, qtbase): QT_BUILD_PARTS -= tests
+
+load(qt_parts)
diff --git a/mkspecs/features/uikit/resolve_config.prf b/mkspecs/features/uikit/resolve_config.prf
new file mode 100644
index 0000000000..c3ab90f45e
--- /dev/null
+++ b/mkspecs/features/uikit/resolve_config.prf
@@ -0,0 +1,68 @@
+
+xcodebuild {
+ # Xcode project files always support both Debug and Release configurations
+ # and iOS device and simulator targets, so we make sure the wrapper-makefile
+ # also does.
+ CONFIG += debug_and_release simulator_and_device
+}
+
+load(resolve_config)
+
+# Legacy exclusive build configurations for backwards compatibility
+CONFIG($${device.CONFIG}, $${device.CONFIG}|$${simulator.CONFIG}): \
+ CONFIG += device
+else: CONFIG($${simulator.CONFIG}, $${device.CONFIG}|$${simulator.CONFIG}): \
+ CONFIG += simulator
+
+CONFIG(simulator, simulator|device): \
+ CONFIG -= device $${device.CONFIG}
+else: \
+ CONFIG -= simulator $${simulator.CONFIG}
+
+macx-xcode {
+ # There is no way to genereate Xcode projects that are limited to either
+ # simulator or device builds, so simulator_and_device is always
+ # effectivly active, even if the user disabled it explicitly.
+ # The Xcode generator doesn't support multiple BUILDS though (exclusive
+ # builds), so we have to manually set up the simulator suffix.
+ library_suffix_simulator.name = "$${QMAKE_XCODE_LIBRARY_SUFFIX_SETTING}[sdk=$${simulator.sdk}*]"
+ library_suffix_simulator.value = "_$${simulator.sdk}$($${QMAKE_XCODE_LIBRARY_SUFFIX_SETTING})"
+ QMAKE_MAC_XCODE_SETTINGS += library_suffix_simulator
+ CONFIG *= xcode_dynamic_library_suffix
+} else {
+ addExclusiveBuilds(simulator, device)
+}
+
+equals(TEMPLATE, subdirs) {
+ # Prevent recursion into host_builds
+ for(subdir, SUBDIRS) {
+ contains($${subdir}.CONFIG, host_build) {
+ $${subdir}.CONFIG += no_$${simulator.target}_target no_$${device.target}_target
+
+ # Other targets which we do want to recurse into may depend on this target,
+ # for example corelib depends on moc, rcc, bootstrap, etc, and other libs
+ # may depend on host-tools that are needed to build the lib, so we resolve
+ # the final target name and redirect it to the base target, so that the
+ # dependency chain is not broken for the other targets.
+
+ !isEmpty($${subdir}.target) {
+ target = $$eval($${subdir}.target)
+ } else {
+ !isEmpty($${subdir}.file): \
+ file = $$eval($${subdir}.file)
+ else: !isEmpty($${subdir}.subdir): \
+ file = $$eval($${subdir}.subdir)
+ else: \
+ file = $$subdir
+
+ target = sub-$$file
+ }
+
+ target ~= s,[^a-zA-Z0-9_],-,
+
+ $${target}-$${simulator.target}.depends = $$target
+ $${target}-$${device.target}.depends = $$target
+ QMAKE_EXTRA_TARGETS += $${target}-$${simulator.target} $${target}-$${device.target}
+ }
+ }
+}
diff --git a/mkspecs/features/uikit/sdk.prf b/mkspecs/features/uikit/sdk.prf
new file mode 100644
index 0000000000..94451ea196
--- /dev/null
+++ b/mkspecs/features/uikit/sdk.prf
@@ -0,0 +1,32 @@
+
+# In case the user sets the SDK manually
+contains(QMAKE_MAC_SDK, ^$${simulator.sdk}.*) {
+ contains(QT_CONFIG, simulator_and_device): \
+ error("Simulator is handled automatically for simulator_and_device")
+
+ CONFIG += simulator $${simulator.sdk}
+}
+
+build_pass:simulator: \
+ QMAKE_MAC_SDK ~= s,^$${device.sdk},$${simulator.sdk},
+
+load(sdk)
+
+lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \
+ error("Current $$QMAKE_MAC_SDK SDK version ($$QMAKE_MAC_SDK_VERSION) is too old. Please upgrade Xcode.")
+
+macx-xcode {
+ sdk_path_device.name = "QMAKE_MAC_SDK_PATH[sdk=$${device.sdk}*]"
+ sdk_path_device.value = $$xcodeSDKInfo(Path, $${device.sdk})
+ sdk_path_simulator.name = "QMAKE_MAC_SDK_PATH[sdk=$${simulator.sdk}*]"
+ sdk_path_simulator.value = $$xcodeSDKInfo(Path, $${simulator.sdk})
+ QMAKE_MAC_XCODE_SETTINGS += sdk_path_device sdk_path_simulator
+ QMAKE_MAC_SDK_PATH = "$(QMAKE_MAC_SDK_PATH)"
+
+ sdk_platform_path_device.name = "QMAKE_MAC_SDK_PLATFORM_PATH[sdk=$${device.sdk}*]"
+ sdk_platform_path_device.value = $$xcodeSDKInfo(PlatformPath, $${device.sdk})
+ sdk_platform_path_simulator.name = "QMAKE_MAC_SDK_PLATFORM_PATH[sdk=$${simulator.sdk}*]"
+ sdk_platform_path_simulator.value = $$xcodeSDKInfo(PlatformPath, $${simulator.sdk})
+ QMAKE_MAC_XCODE_SETTINGS += sdk_platform_path_device sdk_platform_path_simulator
+ QMAKE_MAC_SDK_PLATFORM_PATH = "$(QMAKE_MAC_SDK_PLATFORM_PATH)"
+}
diff --git a/mkspecs/features/uikit/testcase.prf b/mkspecs/features/uikit/testcase.prf
new file mode 100644
index 0000000000..e16c163ffa
--- /dev/null
+++ b/mkspecs/features/uikit/testcase.prf
@@ -0,0 +1,12 @@
+# Pretend we have a target, even though our template is aux
+xcodebuild: \
+ CONFIG += have_target
+
+load(testcase)
+
+# We provide our own check logic
+xcodebuild {
+ check.depends =
+ check.commands =
+ QMAKE_EXTRA_TARGETS *= check
+}
diff --git a/mkspecs/features/uikit/testcase_targets.prf b/mkspecs/features/uikit/testcase_targets.prf
new file mode 100644
index 0000000000..e0a2922c3f
--- /dev/null
+++ b/mkspecs/features/uikit/testcase_targets.prf
@@ -0,0 +1,3 @@
+# For the xcodebuild wrapper makefile we deal with test targets manually
+!xcodebuild: \
+ load(testcase_targets)
diff --git a/mkspecs/features/uikit/xcodebuild.mk b/mkspecs/features/uikit/xcodebuild.mk
new file mode 100644
index 0000000000..5cbad60804
--- /dev/null
+++ b/mkspecs/features/uikit/xcodebuild.mk
@@ -0,0 +1,101 @@
+
+# We don't want xcodebuild to run in parallel
+.NOTPARALLEL:
+
+# Functions
+targets = $(foreach target, $(EXPORT_SUBTARGETS), $(target)-$(strip $(1)))
+toupper = $(shell echo $1 | tr '[:lower:]' '[:upper:]')
+tolower = $(shell echo $1 | tr '[:upper:]' '[:lower:]')
+basesdk = $(shell echo $1 | sed 's/[0-9.]*$$//')
+
+# Explicit comma variable
+, := ,
+
+# Default targets
+first: build
+all: build_all
+
+.DEFAULT_GOAL = first
+
+# Top level targets
+build: build_first
+clean: clean_first
+install: install_first
+check: check_first
+distclean: clean_all
+
+$(EXPORT_SUBTARGETS): % : %-build
+
+# Generic targets
+%_first: $(firstword $(call targets, %)) ;
+%_all: $(call targets, %) ;
+
+# Actions
+%-build: ACTION = build
+%-build: xcodebuild-% ;
+
+%-clean: ACTION = clean
+%-clean: xcodebuild-% ;
+
+%-install: ACTION = install
+%-install: xcodebuild-% ;
+
+# Simulator doesn't support archiving
+%-simulator-install: ACTION = build
+simulator-install: ACTION = build
+
+# Limit check to a single configuration
+%-device-check: check-device ;
+%-simulator-check: check-simulator ;
+
+# SDK
+%-device: SDK = $(DEVICE_SDK)
+%-simulator: SDK = $(SIMULATOR_SDK)
+
+# Configuration
+release-%: CONFIGURATION = Release
+debug-%: CONFIGURATION = Debug
+
+# Test and build (device) destinations
+ifneq ($(filter check%,$(MAKECMDGOALS)),)
+ ifeq ($(DEVICES),)
+ $(info Enumerating test destinations (you may override this by setting DEVICES explicitly), please wait...)
+ SPECDIR := $(dir $(lastword $(MAKEFILE_LIST)))
+ DESTINATIONS_INCLUDE = /tmp/device_destinations.mk
+ $(shell $(SPECDIR)/../features/uikit/device_destinations.sh '$(EXPORT_DEVICE_FILTER)' $(TARGET) > $(DESTINATIONS_INCLUDE))
+ include $(DESTINATIONS_INCLUDE)
+ endif
+endif
+
+%-simulator: DEVICES = $(firstword $(SIMULATOR_DEVICES))
+%-device: DEVICES = $(HARDWARE_DEVICES)
+
+GENERIC_DEVICE_DESTINATION := $(EXPORT_GENERIC_DEVICE_DESTINATION)
+GENERIC_SIMULATOR_DESTINATION := "id=$(shell xcrun simctl list devices | grep -E '$(EXPORT_DEVICE_FILTER)' | grep -v unavailable | perl -lne 'print $$1 if /\((.*?)\)/' | tail -n 1)"
+
+%-simulator: DESTINATION = $(if $(DESTINATION_ID),"id=$(DESTINATION_ID)",$(GENERIC_SIMULATOR_DESTINATION))
+%-device: DESTINATION = $(if $(DESTINATION_ID),"id=$(DESTINATION_ID)",$(GENERIC_DEVICE_DESTINATION))
+
+# Xcodebuild
+
+DESTINATION_MESSAGE = "Running $(call tolower,$(CONFIGURATION)) $(ACTION) \
+ on '$(DESTINATION_NAME)' ($(DESTINATION_ID))$(if $(DESTINATION_OS),$(,) $(DESTINATION_PLATFORM) $(DESTINATION_OS),)"
+
+xcodebuild-%:
+ @$(if $(DESTINATION_NAME), echo $(DESTINATION_MESSAGE),)
+ xcodebuild $(ACTION) -scheme $(TARGET) $(if $(SDK), -sdk $(SDK),) $(if $(CONFIGURATION), -configuration $(CONFIGURATION),) $(if $(DESTINATION), -destination $(DESTINATION) -destination-timeout 1,)
+
+xcodebuild-check-device_%: DESTINATION_ID=$(lastword $(subst _, ,$@))
+
+# Special check target (requires SECONDEXPANSION due to devices)
+.SECONDEXPANSION:
+check-%: ACTION = test
+check-%: $$(foreach device, $$(DEVICES), xcodebuild-check-device_$$(device)) ;
+ @echo $(if $^, Ran $(call tolower,$(CONFIGURATION)) tests on $(words $^) $(SDK) destination\(s\): $(DEVICES), No compatible test devices found for \'$(SDK)\' SDK && false)
+
+# Determined by device
+check-%: SDK =
+
+# Default to debug for testing
+check-%: CONFIGURATION = Debug
+
diff --git a/mkspecs/features/uikit/xcodebuild.prf b/mkspecs/features/uikit/xcodebuild.prf
new file mode 100644
index 0000000000..6e50bbcf50
--- /dev/null
+++ b/mkspecs/features/uikit/xcodebuild.prf
@@ -0,0 +1,61 @@
+
+# For Qt applications we want Xcode project files as the generated output,
+# but since qmake doesn't handle the transition between makefiles and Xcode
+# project files (which happens when using subdirs), we can't just override
+# MAKEFILE_GENERATOR. Instead, we generate the Xcode project by spawing a
+# child qmake process with -spec macx-xcode and let the top level qmake
+# process generate a wrapper makefile that forwards everything to xcodebuild.
+
+TEMPLATE = aux
+
+SOURCES =
+OBJECTIVE_SOURCES =
+RESOURCES =
+INSTALLS =
+QMAKE_EXTRA_COMPILERS =
+
+!mkpath($$OUT_PWD): \
+ error("Failed to create $$OUT_PWD")
+
+args =
+for(arg, QMAKE_ARGS): \
+ args += $$system_quote($$arg)
+
+cmd = "$$QMAKE_QMAKE $$args $$system_quote($$_PRO_FILE_) -spec macx-xcode"
+debug(1, "Generating Xcode project in $$OUT_PWD using '$$cmd'")
+system("cd $$system_quote($$OUT_PWD) && $$cmd")
+
+# Subtargets
+
+for(build, BUILDS): \
+ SUBTARGETS += $$eval($${build}.target)
+QMAKE_EXTRA_VARIABLES += SUBTARGETS
+
+CONFIG += no_default_goal_deps
+
+DEVICE_SDK = $${device.sdk}
+SIMULATOR_SDK = $${simulator.sdk}
+ios {
+ DEVICE_FILTER = "iPhone|iPad"
+ GENERIC_DEVICE_DESTINATION = "generic/platform=iOS"
+}
+tvos {
+ DEVICE_FILTER = "Apple TV"
+ GENERIC_DEVICE_DESTINATION = "generic/platform=tvOS"
+}
+QMAKE_EXTRA_VARIABLES += DEVICE_SDK SIMULATOR_SDK DEVICE_FILTER GENERIC_DEVICE_DESTINATION
+
+QMAKE_EXTRA_INCLUDES += $$shell_quote($$PWD/xcodebuild.mk)
+
+# Distclean
+
+distfiles = $${TARGET}.xcodeproj
+for(build, BUILDS): \
+ distfiles += $$title($$eval($${build}.target))
+distclean_xcodebuild.commands = -$(DEL_FILE) -R $$distfiles
+
+distclean.depends += clean_all distclean_xcodebuild
+QMAKE_EXTRA_TARGETS += distclean distclean_xcodebuild
+
+# Empty exclusive builds, we've set them up manually
+BUILDS =
diff --git a/mkspecs/features/win32/console.prf b/mkspecs/features/win32/console.prf
index 629f3af59b..739bb0e01b 100644
--- a/mkspecs/features/win32/console.prf
+++ b/mkspecs/features/win32/console.prf
@@ -1,6 +1,5 @@
CONFIG -= windows
-QMAKE_LFLAGS += $$replace(QMAKE_LFLAGS_CONSOLE, @QMAKE_SUBSYSTEM_SUFFIX@, $$QMAKE_SUBSYSTEM_SUFFIX)
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_CONSOLE
contains(TEMPLATE, ".*app") {
- wince: QMAKE_LFLAGS += /ENTRY:mainACRTStartup
QMAKE_LFLAGS += $$QMAKE_LFLAGS_EXE
}
diff --git a/mkspecs/features/win32/opengl.prf b/mkspecs/features/win32/opengl.prf
index 8173348bc4..c26ab62f50 100644
--- a/mkspecs/features/win32/opengl.prf
+++ b/mkspecs/features/win32/opengl.prf
@@ -1,32 +1,23 @@
-# WinCE does not have a platform directory for .prf files, and the
-# win32 directory is searched for .prfs by qmake on WinCE. Ideally
-# there should be a features/wince/opengl.prf which contains the wince
-# block below.
-
-wince* {
- include(../unix/opengl.prf)
-} else {
- contains(QT_CONFIG, opengles2) {
-# For Desktop, use the ANGLE library location passed on from configure.
- INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2
- CONFIG(debug, debug|release) {
- QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_DEBUG
- contains(QT_CONFIG, angle) {
- LIBS += $$QMAKE_LIBS_OPENGL_ES2_DEBUG
- } else {
- LIBS += $$QMAKE_LIBS_OPENGL_ES2
- }
+contains(QT_CONFIG, opengles2) {
+# For Desktop, use the ANGLE library location passed on from configure.
+ INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2
+ CONFIG(debug, debug|release) {
+ QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_DEBUG
+ contains(QT_CONFIG, angle) {
+ LIBS += $$QMAKE_LIBS_OPENGL_ES2_DEBUG
} else {
LIBS += $$QMAKE_LIBS_OPENGL_ES2
- QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_RELEASE
}
- DEFINES += QT_OPENGL_ES_2 QT_OPENGL_ES_2_ANGLE
- contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC GL_APICALL= EGLAPI=
- QT_CONFIG -= opengl
} else {
- !contains(QT_CONFIG, dynamicgl) {
- QMAKE_LIBS += $$QMAKE_LIBS_OPENGL
- QMAKE_LFLAGS += $$QMAKE_LFLAGS_OPENGL
- }
+ LIBS += $$QMAKE_LIBS_OPENGL_ES2
+ QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_RELEASE
+ }
+ DEFINES += QT_OPENGL_ES_2 QT_OPENGL_ES_2_ANGLE
+ contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC GL_APICALL= EGLAPI=
+ QT_CONFIG -= opengl
+} else {
+ !contains(QT_CONFIG, dynamicgl) {
+ QMAKE_LIBS += $$QMAKE_LIBS_OPENGL
+ QMAKE_LFLAGS += $$QMAKE_LFLAGS_OPENGL
}
}
diff --git a/mkspecs/features/win32/qt_config.prf b/mkspecs/features/win32/qt_config.prf
deleted file mode 100644
index 49b4c79431..0000000000
--- a/mkspecs/features/win32/qt_config.prf
+++ /dev/null
@@ -1,10 +0,0 @@
-load(qt_config)
-
-equals(QMAKE_TARGET_OS, xp) {
- # http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx?PageIndex=3
- equals(QT_ARCH, x86_64) {
- QMAKE_SUBSYSTEM_SUFFIX = ,5.02
- } else {
- QMAKE_SUBSYSTEM_SUFFIX = ,5.01
- }
-}
diff --git a/mkspecs/features/win32/windows.prf b/mkspecs/features/win32/windows.prf
index 986067fc8c..ecb167bf18 100644
--- a/mkspecs/features/win32/windows.prf
+++ b/mkspecs/features/win32/windows.prf
@@ -1,5 +1,5 @@
CONFIG -= console
-QMAKE_LFLAGS += $$replace(QMAKE_LFLAGS_WINDOWS, @QMAKE_SUBSYSTEM_SUFFIX@, $$QMAKE_SUBSYSTEM_SUFFIX)
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_WINDOWS
contains(TEMPLATE, ".*app") {
QMAKE_LFLAGS += $$QMAKE_LFLAGS_EXE
mingw:DEFINES += QT_NEEDS_QMAIN