From 7c7d8f870e028bd288dee6b2cab9869e17794ce9 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 7 Mar 2016 20:11:11 +0000 Subject: Refactor iOS builds to facilitate tvOS port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - moved prf files to shared location (uikit, added to QMAKE_PLATFORM) - prepare some formatting (unconditional blocks mostly) to add conditions later - make device detection script more generic, passing filter strings as a parameter and returning non-os specific variables Change-Id: I61f2b77093304ff985bec9da04fda57ff296b16b Reviewed-by: Oswald Buddenhagen Reviewed-by: Tor Arne Vestbø --- mkspecs/features/uikit/default_post.prf | 101 +++++++++++++++++++++++ mkspecs/features/uikit/default_pre.prf | 21 +++++ mkspecs/features/uikit/device_destinations.sh | 61 ++++++++++++++ mkspecs/features/uikit/exclusive_builds_post.prf | 8 ++ mkspecs/features/uikit/qt.prf | 33 ++++++++ mkspecs/features/uikit/qt_config.prf | 17 ++++ mkspecs/features/uikit/qt_parts.prf | 5 ++ mkspecs/features/uikit/resolve_config.prf | 62 ++++++++++++++ mkspecs/features/uikit/sdk.prf | 32 +++++++ mkspecs/features/uikit/testcase.prf | 12 +++ mkspecs/features/uikit/testcase_targets.prf | 3 + mkspecs/features/uikit/xcodebuild.mk | 101 +++++++++++++++++++++++ mkspecs/features/uikit/xcodebuild.prf | 55 ++++++++++++ 13 files changed, 511 insertions(+) create mode 100644 mkspecs/features/uikit/default_post.prf create mode 100644 mkspecs/features/uikit/default_pre.prf create mode 100755 mkspecs/features/uikit/device_destinations.sh create mode 100644 mkspecs/features/uikit/exclusive_builds_post.prf create mode 100644 mkspecs/features/uikit/qt.prf create mode 100644 mkspecs/features/uikit/qt_config.prf create mode 100644 mkspecs/features/uikit/qt_parts.prf create mode 100644 mkspecs/features/uikit/resolve_config.prf create mode 100644 mkspecs/features/uikit/sdk.prf create mode 100644 mkspecs/features/uikit/testcase.prf create mode 100644 mkspecs/features/uikit/testcase_targets.prf create mode 100644 mkspecs/features/uikit/xcodebuild.mk create mode 100644 mkspecs/features/uikit/xcodebuild.prf (limited to 'mkspecs/features/uikit') diff --git a/mkspecs/features/uikit/default_post.prf b/mkspecs/features/uikit/default_post.prf new file mode 100644 index 0000000000..f21d1e6427 --- /dev/null +++ b/mkspecs/features/uikit/default_post.prf @@ -0,0 +1,101 @@ +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 + device_family.value = $$QMAKE_IOS_TARGETED_DEVICE_FAMILY + QMAKE_MAC_XCODE_SETTINGS += device_family + + { + # 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}*]" + { + 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 + } + + 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.*) { + VALID_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS + } else { + VALID_ARCHS = $$QMAKE_IOS_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..a857c49007 --- /dev/null +++ b/mkspecs/features/uikit/default_pre.prf @@ -0,0 +1,21 @@ + +load(default_pre) + +# In case Qt was built for a specific SDK +!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") + +simulator_and_device:iphonesimulator { + # 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 +} diff --git a/mkspecs/features/uikit/device_destinations.sh b/mkspecs/features/uikit/device_destinations.sh new file mode 100755 index 0000000000..978e1149b5 --- /dev/null +++ b/mkspecs/features/uikit/device_destinations.sh @@ -0,0 +1,61 @@ +#!/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" + 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..7edec819d5 --- /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) + + { + # 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..00e2c0c258 --- /dev/null +++ b/mkspecs/features/uikit/qt_config.prf @@ -0,0 +1,17 @@ +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 + QT_ARCH = i386 + } + + # 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..38d6c74ccb --- /dev/null +++ b/mkspecs/features/uikit/resolve_config.prf @@ -0,0 +1,62 @@ + +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) + +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..ce44ac79fd --- /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}.*) { + simulator_and_device: \ + error("Simulator is handled automatically for simulator_and_device") + + CONFIG += simulator $${simulator.sdk} +} + +simulator_and_device: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..c6f20a5109 --- /dev/null +++ b/mkspecs/features/uikit/xcodebuild.prf @@ -0,0 +1,55 @@ + +# 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} +DEVICE_FILTER = "iPhone|iPad" +GENERIC_DEVICE_DESTINATION = "generic/platform=iOS" +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 = -- cgit v1.2.3