summaryrefslogtreecommitdiffstats
path: root/mkspecs/macx-ios-clang
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>2015-06-16 17:14:53 +0200
committerTor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>2015-08-04 11:59:01 +0000
commite405665318a7a666a945929eb6ef7829af804557 (patch)
tree6802de8f95d3822173e8bd951441e9b0447d013c /mkspecs/macx-ios-clang
parent5d511039f71a110fa757132cdca079e72fe87654 (diff)
iOS: Refactor xcodebuild exclusive build logic into standalone makefile
Instead of going to qmake to generate the makefile that we want, we write the makefile directly and include it from the generated makefile. This leaves us with a single top level makefile for handling exclusive builds through xcodebuild, and covers all the various build configurations in a unified manner. It also allows for improved test device handling. Change-Id: I66851f181ac4da2c8938645e0aa95ffa0fee33c7 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
Diffstat (limited to 'mkspecs/macx-ios-clang')
-rw-r--r--mkspecs/macx-ios-clang/features/testcase_targets.prf3
-rw-r--r--mkspecs/macx-ios-clang/features/xcodebuild.prf90
-rwxr-xr-xmkspecs/macx-ios-clang/ios_destinations.sh55
-rw-r--r--mkspecs/macx-ios-clang/xcodebuild.mk96
4 files changed, 177 insertions, 67 deletions
diff --git a/mkspecs/macx-ios-clang/features/testcase_targets.prf b/mkspecs/macx-ios-clang/features/testcase_targets.prf
new file mode 100644
index 0000000000..e0a2922c3f
--- /dev/null
+++ b/mkspecs/macx-ios-clang/features/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/macx-ios-clang/features/xcodebuild.prf b/mkspecs/macx-ios-clang/features/xcodebuild.prf
index 627e1e2930..b897432a43 100644
--- a/mkspecs/macx-ios-clang/features/xcodebuild.prf
+++ b/mkspecs/macx-ios-clang/features/xcodebuild.prf
@@ -14,80 +14,36 @@ RESOURCES =
INSTALLS =
QMAKE_EXTRA_COMPILERS =
-!build_pass {
- # Top level makefile that aggregates all exclusive builds
+!mkpath($$OUT_PWD): \
+ error("Failed to create $$OUT_PWD")
- !mkpath($$OUT_PWD): \
- error("Failed to create $$OUT_PWD")
+args =
+for(arg, QMAKE_ARGS): \
+ args += $$system_quote($$arg)
- 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")
- 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
- distclean_files += $${TARGET}.xcodeproj
+for(build, BUILDS): \
+ SUBTARGETS += $$eval($${build}.target)
+QMAKE_EXTRA_VARIABLES += SUBTARGETS
- # Pretend we have a target, even though our template is aux
- CONFIG += have_target
+CONFIG += no_default_goal_deps
-} else {
- # Leaf makefile for a single exclusive build
+QMAKE_EXTRA_INCLUDES += $$shell_quote($$QMAKESPEC/xcodebuild.mk)
- iphonesimulator: \
- sdk = iphonesimulator
- else: \
- sdk = iphoneos
+# Distclean
- debug: \
- cfg = debug
- else: \
- cfg = release
+distfiles = $${TARGET}.xcodeproj
+for(build, BUILDS): \
+ distfiles += $$title($$eval($${build}.target))
+distclean_xcodebuild.commands = -$(DEL_FILE) -R $$distfiles
- for(action, $$list(build install clean test)) {
- equals(action, build) {
- action_target_suffix =
- action_target = all
- } else: equals(action, test) {
- action_target_suffix = -check
- action_target = check
- } else {
- action_target_suffix = -$$action
- action_target = $$action
- }
-
- target = $${sdk}-$${cfg}$${action_target_suffix}
-
- xcodebuild = "xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg)"
-
- equals(action, test):equals(sdk, iphoneos) {
- AVAILABLE_DEVICE_IDS = "$(shell system_profiler SPUSBDataType | sed -n -E -e '/(iPhone|iPad|iPod)/,/Serial/s/ *Serial Number: *(.+)/\1/p')"
- CUSTOM_DEVICE_IDS = "$(filter $(EXPORT_AVAILABLE_DEVICE_IDS), $(IOS_TEST_DEVICE_IDS))"
- TEST_DEVICE_IDS = "$(strip $(if $(EXPORT_CUSTOM_DEVICE_IDS), $(EXPORT_CUSTOM_DEVICE_IDS), $(EXPORT_AVAILABLE_DEVICE_IDS)))"
-
- QMAKE_EXTRA_VARIABLES += AVAILABLE_DEVICE_IDS CUSTOM_DEVICE_IDS TEST_DEVICE_IDS
-
- xcodebuild = "@$(if $(EXPORT_TEST_DEVICE_IDS),"\
- "echo Running tests on $(words $(EXPORT_TEST_DEVICE_IDS)) device\\(s\\): && ("\
- "$(foreach deviceid, $(EXPORT_TEST_DEVICE_IDS),"\
- "(echo Testing on device ID '$(deviceid)' ... && $${xcodebuild} -destination 'platform=iOS,id=$(deviceid)' && echo) &&"\
- ") echo Tests completed successfully on all devices"\
- "), $(error No iOS devices connected, please connect at least one device that can be used for testing.))"
- }
-
- $${target}.commands = $$xcodebuild
- QMAKE_EXTRA_TARGETS += $$target
-
- $${action_target}.depends += $$target
- QMAKE_EXTRA_TARGETS *= $${action_target}
- }
-
- # Remove build dir
- distclean_files += $$title($$cfg)-$${sdk}
-}
-
-distclean_xcodebuild.commands = -$(DEL_FILE) -R $$distclean_files
-distclean.depends += distclean_xcodebuild
+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/macx-ios-clang/ios_destinations.sh b/mkspecs/macx-ios-clang/ios_destinations.sh
new file mode 100755
index 0000000000..aebf8f6403
--- /dev/null
+++ b/mkspecs/macx-ios-clang/ios_destinations.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## 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 http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://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 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+booted_simulator=$(xcrun simctl list devices | grep -v unavailable | grep Booted | perl -lne 'print $1 if /\((.*?)\)/')
+echo "IPHONESIMULATOR_DEVICES = $booted_simulator"
+
+xcodebuild test -scheme $1 -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 "IPHONEOS_DEVICES += $id"
+ elif [ "$val" = "iOS Simulator" -a "$id" != "$booted_simulator" ]; then
+ echo "IPHONESIMULATOR_DEVICES += $id"
+ fi
+ fi
+ done
+ echo
+done
diff --git a/mkspecs/macx-ios-clang/xcodebuild.mk b/mkspecs/macx-ios-clang/xcodebuild.mk
new file mode 100644
index 0000000000..f50010abc1
--- /dev/null
+++ b/mkspecs/macx-ios-clang/xcodebuild.mk
@@ -0,0 +1,96 @@
+
+# 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-% ;
+
+# Limit check to a single configuration
+%-iphoneos-check: check-iphoneos ;
+%-iphonesimulator-check: check-iphonesimulator ;
+
+# SDK
+%-iphoneos: SDK = iphoneos
+%-iphonesimulator: SDK = iphonesimulator
+
+# 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/ios_destinations.mk
+ $(shell $(SPECDIR)/ios_destinations.sh $(TARGET) > $(DESTINATIONS_INCLUDE))
+ include $(DESTINATIONS_INCLUDE)
+ endif
+endif
+
+%-iphonesimulator: DEVICES = $(firstword $(IPHONESIMULATOR_DEVICES))
+%-iphoneos: DEVICES = $(IPHONEOS_DEVICES)
+
+IPHONEOS_GENERIC_DESTINATION := "generic/platform=iOS"
+IPHONESIMULATOR_GENERIC_DESTINATION := "id=$(shell xcrun simctl list devices | grep -v unavailable | perl -lne 'print $$1 if /\((.*?)\)/' | tail -n 1)"
+
+DESTINATION = $(if $(DESTINATION_ID),"id=$(DESTINATION_ID)",$(value $(call toupper,$(call basesdk,$(SDK)))_GENERIC_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
+