Remove simulator_and_device handling for the Makefile generator

This patch moves towards a more sensible layout for UIKit platforms,
where both the device and simulator architectures for binaries are
combined into a single Mach-O file instead of separating out the
simulator architecutures into separate _simulator.a files.

This approach is both more common in the iOS ecosystem at large and
significantly simplifies the implementation details for Qt, especially
with the upcoming support for shared libraries on UIKit platforms.

This patch takes advantage of the -Xarch compiler option to pass the
appropriate -isysroot, -syslibroot, and -m*-version-min compiler and
linker flags to the clang frontend, operating in exactly the same way
as a normal multi-arch build for device or simulator did previously.
Exclusive builds are still enabled for the xcodebuild wrapper Makefile,
which builds all four configurations of a UIKit Xcode project as before,
as expected.

A particularly advantageous benefit of this change is that it flows very
well with existing Xcode workflows, namely that:
- Slicing out unused architectures is handled completely automatically
  for static builds, as an executable linking to a library with more
  architectures than it itself is linked as, the unused architectures
  will be ignored silently, resulting in the same behavior for users
  (and the App Store won't let you submit Intel architectures either).
- Removing architectures from a fat binary using lipo does NOT
  invalidate the code signature of that file or its container if it is a
  bundle. This allows shared library and framework builds of Qt to work
  mostly automatically as well, since an Xcode shell script build phase
  can remove unused architectures from the embedded frameworks when that
  is implemented, and if Qt ever starts signing its SDK releases, it
  won't interfere with that either (though binaries are just resigned).

Change-Id: I6c3578c78f75845a2fcc85f3a5b728ec997dbe90
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Jake Petroules 2016-08-25 06:07:54 -07:00
parent 4eb2feb29c
commit 397f345a6a
7 changed files with 77 additions and 84 deletions

View File

@ -24,12 +24,6 @@ QMAKE_MAC_SDK_PATH = $$xcodeSDKInfo(Path)
QMAKE_MAC_SDK_PLATFORM_PATH = $$xcodeSDKInfo(PlatformPath) QMAKE_MAC_SDK_PLATFORM_PATH = $$xcodeSDKInfo(PlatformPath)
QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion) QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion)
!equals(MAKEFILE_GENERATOR, XCODE) {
QMAKE_CFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH
QMAKE_CXXFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH
QMAKE_LFLAGS += -Wl,-syslibroot,$$QMAKE_MAC_SDK_PATH
}
sysrootified = sysrootified =
for(val, QMAKE_INCDIR_OPENGL): sysrootified += $${QMAKE_MAC_SDK_PATH}$$val for(val, QMAKE_INCDIR_OPENGL): sysrootified += $${QMAKE_MAC_SDK_PATH}$$val
QMAKE_INCDIR_OPENGL = $$sysrootified QMAKE_INCDIR_OPENGL = $$sysrootified
@ -61,15 +55,46 @@ for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_FIX_RPATH QMAKE_AR QMAKE_RANLIB QMAKE_
watchos: os_var = WATCHOS watchos: os_var = WATCHOS
deployment_target = $$eval(QMAKE_$${os_var}_DEPLOYMENT_TARGET) deployment_target = $$eval(QMAKE_$${os_var}_DEPLOYMENT_TARGET)
simulator { !simulator|simulator_and_device: device_archs = $$eval(QMAKE_$${os_var}_DEVICE_ARCHS)
archs = $$eval(QMAKE_$${os_var}_SIMULATOR_ARCHS) simulator: simulator_archs = $$eval(QMAKE_$${os_var}_SIMULATOR_ARCHS)
version_identifier = $$simulator.deployment_identifier archs = $$device_archs $$simulator_archs
} else {
archs = $$eval(QMAKE_$${os_var}_DEVICE_ARCHS) QMAKE_XARCH_CFLAGS =
version_identifier = $$device.deployment_identifier QMAKE_XARCH_LFLAGS =
QMAKE_EXTRA_VARIABLES += QMAKE_XARCH_CFLAGS QMAKE_XARCH_LFLAGS
single_arch {
device_archs = $$first(device_archs)
simulator_archs = $$first(simulator_archs)
archs = $$first(archs)
} }
single_arch: archs = $$first(archs) for(arch, archs) {
contains(simulator_archs, $$arch) {
sdk = $$simulator.sdk
version_identifier = $$simulator.deployment_identifier
} else {
sdk = $$device.sdk
version_identifier = $$device.deployment_identifier
}
version_min_flags = \
-Xarch_$${arch} \
-m$${version_identifier}-version-min=$$deployment_target
QMAKE_XARCH_CFLAGS_$${arch} = $$version_min_flags \
-Xarch_$${arch} \
-isysroot$$xcodeSDKInfo(Path, $$sdk)
QMAKE_XARCH_LFLAGS_$${arch} = $$version_min_flags \
-Xarch_$${arch} \
-Wl,-syslibroot,$$xcodeSDKInfo(Path, $$sdk)
QMAKE_XARCH_CFLAGS += $(EXPORT_QMAKE_XARCH_CFLAGS_$${arch})
QMAKE_XARCH_LFLAGS += $(EXPORT_QMAKE_XARCH_CFLAGS_$${arch})
QMAKE_EXTRA_VARIABLES += \
QMAKE_XARCH_CFLAGS_$${arch} \
QMAKE_XARCH_LFLAGS_$${arch}
}
QMAKE_CFLAGS_USE_PRECOMPILE = QMAKE_CFLAGS_USE_PRECOMPILE =
for(arch, archs) { for(arch, archs) {
@ -85,10 +110,13 @@ for(tool, $$list(QMAKE_CC QMAKE_CXX QMAKE_FIX_RPATH QMAKE_AR QMAKE_RANLIB QMAKE_
} else: osx { } else: osx {
version_identifier = macosx version_identifier = macosx
deployment_target = $$QMAKE_MACOSX_DEPLOYMENT_TARGET deployment_target = $$QMAKE_MACOSX_DEPLOYMENT_TARGET
version_min_flag = -m$${version_identifier}-version-min=$$deployment_target
QMAKE_CFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH $$version_min_flag
QMAKE_CXXFLAGS += -isysroot $$QMAKE_MAC_SDK_PATH $$version_min_flag
QMAKE_LFLAGS += -Wl,-syslibroot,$$QMAKE_MAC_SDK_PATH $$version_min_flag
} }
version_min_flag = -m$${version_identifier}-version-min=$$deployment_target QMAKE_CFLAGS += $(EXPORT_QMAKE_XARCH_CFLAGS)
QMAKE_CFLAGS += $$version_min_flag QMAKE_CXXFLAGS += $(EXPORT_QMAKE_XARCH_CFLAGS)
QMAKE_CXXFLAGS += $$version_min_flag QMAKE_LFLAGS += $(EXPORT_QMAKE_XARCH_LFLAGS)
QMAKE_LFLAGS += $$version_min_flag
} }

View File

@ -25,8 +25,9 @@ win32:count(MOC_INCLUDEPATH, 40, >) {
} }
# QNX's compiler sets "gcc" config, but does not support the -dM option; # QNX's compiler sets "gcc" config, but does not support the -dM option;
# iOS builds are multi-arch, so this feature cannot possibly work. # UIKit builds are always multi-arch due to simulator_and_device (unless
if(gcc|intel_icl|msvc):!rim_qcc:!ios { # -sdk is used) so this feature cannot possibly work.
if(gcc|intel_icl|msvc):!rim_qcc:!uikit {
moc_predefs.CONFIG = no_link moc_predefs.CONFIG = no_link
gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}

View File

@ -1,10 +1,6 @@
defineReplace(qtPlatformTargetSuffix) { defineReplace(qtPlatformTargetSuffix) {
uikit:CONFIG(simulator, simulator|device): \ suffix =
suffix = _$${simulator.sdk}
else: \
suffix =
CONFIG(debug, debug|release) { CONFIG(debug, debug|release) {
!debug_and_release|build_pass { !debug_and_release|build_pass {
mac: return($${suffix}_debug) mac: return($${suffix}_debug)

View File

@ -119,8 +119,7 @@ lib_bundle {
QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib
} }
!build_all| \ !build_all| \
if(if(!debug_and_release|CONFIG(release, debug|release)): \ if(if(!debug_and_release|CONFIG(release, debug|release))) {
if(!simulator_and_device|CONFIG(device, simulator|device))) {
FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.version = Versions
FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
FRAMEWORK_HEADERS.path = Headers FRAMEWORK_HEADERS.path = Headers

View File

@ -91,15 +91,16 @@ macx-xcode {
only_active_arch.build = debug only_active_arch.build = debug
QMAKE_MAC_XCODE_SETTINGS += only_active_arch QMAKE_MAC_XCODE_SETTINGS += only_active_arch
} else { } else {
# Be more specific about which architecture we're targeting VALID_ARCHS =
contains(QT_ARCH, arm.*) { !simulator|simulator_and_device {
ios: VALID_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS ios: VALID_ARCHS += $$QMAKE_IOS_DEVICE_ARCHS
tvos: VALID_ARCHS = $$QMAKE_TVOS_DEVICE_ARCHS tvos: VALID_ARCHS += $$QMAKE_TVOS_DEVICE_ARCHS
watchos: VALID_ARCHS = $$QMAKE_WATCHOS_DEVICE_ARCHS watchos: VALID_ARCHS += $$QMAKE_WATCHOS_DEVICE_ARCHS
} else { }
ios: VALID_ARCHS = $$QMAKE_IOS_SIMULATOR_ARCHS simulator {
tvos: VALID_ARCHS = $$QMAKE_TVOS_SIMULATOR_ARCHS ios: VALID_ARCHS += $$QMAKE_IOS_SIMULATOR_ARCHS
watchos: VALID_ARCHS = $$QMAKE_WATCHOS_SIMULATOR_ARCHS tvos: VALID_ARCHS += $$QMAKE_TVOS_SIMULATOR_ARCHS
watchos: VALID_ARCHS += $$QMAKE_WATCHOS_SIMULATOR_ARCHS
} }
single_arch: VALID_ARCHS = $$first(VALID_ARCHS) single_arch: VALID_ARCHS = $$first(VALID_ARCHS)

View File

@ -1,31 +1,22 @@
load(default_pre) load(default_pre)
# In case Qt was built for a specific SDK !isEmpty(QT_VERSION) {
!isEmpty(QT_VERSION):!qtConfig(simulator_and_device):contains(QMAKE_MAC_SDK, ^$${simulator.sdk}.*): \ qtConfig(simulator_and_device)|contains(QMAKE_MAC_SDK, ^$${device.sdk}.*): \
CONFIG += simulator $${simulator.sdk} CONFIG += device $${device.sdk}
qtConfig(simulator_and_device)|contains(QMAKE_MAC_SDK, ^$${simulator.sdk}.*): \
CONFIG += simulator $${simulator.sdk}
qtConfig(simulator_and_device) {
# For a simulator_and_device build all the config tests
# are based on the device's ARM SDK, but we know that the simulator
# is Intel and that we support SSE/SSE2.
QT_CPU_FEATURES.$$QT_ARCH += sse sse2
CONFIG += sse sse2
DEFINES += QT_COMPILER_SUPPORTS_SSE2
}
}
# Check for supported Xcode versions # Check for supported Xcode versions
lessThan(QMAKE_XCODE_VERSION, "4.3"): \ lessThan(QMAKE_XCODE_VERSION, "4.3"): \
error("This mkspec requires Xcode 4.3 or later") 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/WatchOS 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
}

View File

@ -1,34 +1,11 @@
xcodebuild { xcodebuild {
# Xcode project files always support both Debug and Release configurations # Xcode project files always support both Debug and Release configurations
# and iOS device and simulator targets, so we make sure the wrapper-makefile # and device and simulator targets, so we make sure the wrapper-makefile
# also does. # also does.
CONFIG += debug_and_release simulator_and_device CONFIG += debug_and_release simulator_and_device
} }
load(resolve_config) load(resolve_config)
# Legacy exclusive build configurations for backwards compatibility !macx-xcode:xcodebuild: addExclusiveBuilds(simulator, device)
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)
}