qtbase/mkspecs/features/qt_functions.prf

310 lines
9.7 KiB
Plaintext
Raw Normal View History

defineReplace(qtPlatformTargetSuffix) {
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>
2016-08-25 13:07:54 +00:00
suffix =
CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
mac: return($${suffix}_debug)
win32: return($${suffix}d)
}
}
return($$suffix)
}
defineReplace(qtLibraryTarget) {
LIBRARY_NAME = $$1
CONFIG(shared, static|shared):qtConfig(framework) {
QMAKE_FRAMEWORK_BUNDLE_NAME = $$LIBRARY_NAME
export(QMAKE_FRAMEWORK_BUNDLE_NAME)
}
return($$LIBRARY_NAME$$qtPlatformTargetSuffix())
}
defineReplace(qt5LibraryTarget) {
LIBRARY_NAME = $$qtLibraryTarget($$1)
isEmpty(QMAKE_FRAMEWORK_BUNDLE_NAME) {
# Insert the major version of Qt in the library name
# unless it's a framework build.
LIBRARY_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION,
}
return($$LIBRARY_NAME)
}
defineReplace(qtRelativeRPathBase) {
darwin {
if(equals(TEMPLATE, app):app_bundle)|\
if(equals(TEMPLATE, lib):plugin:plugin_bundle) {
ios: return($$target.path/$${TARGET}.app)
return($$target.path/$${TARGET}.app/Contents/MacOS)
}
equals(TEMPLATE, lib):!plugin:lib_bundle: \
return($$target.path/$${TARGET}.framework/Versions/Current)
}
return($$target.path)
}
defineTest(qtAddLibrary) {
warning("qtAddLibrary() is deprecated. Use QT+= instead.")
# Reverse-engineer the module name from the library name.
for(var, QT_MODULES) {
isEqual(QT.$${var}.name, $$1) {
QT += $$var
export(QT)
return(true)
}
}
error("No module matching library '$$1' found.")
}
# qt module
defineTest(qtHaveModule) {
!isEmpty(QT.$$replace(1, -, _).name): \
return(true)
return(false)
}
# variable, default, [suffix for variable for system() use], [prepare primary variable for system() use]
defineTest(qtPrepareTool) {
cmd = $$eval(QT_TOOL.$${2}.binary)
isEmpty(cmd) {
cmd = $$[QT_HOST_BINS]/$$2
exists($${cmd}.pl) {
$${1}_EXE = $${cmd}.pl
cmd = perl -w $$system_path($${cmd}.pl)
} else: contains(QMAKE_HOST.os, Windows) {
$${1}_EXE = $${cmd}.exe
cmd = $$system_path($${cmd}.exe)
} else:contains(QMAKE_HOST.os, Darwin) {
BUNDLENAME = $${cmd}.app/Contents/MacOS/$$2
exists($$BUNDLENAME) {
cmd = $$BUNDLENAME
}
$${1}_EXE = $$cmd
} else {
$${1}_EXE = $$cmd
}
} else {
$${1}_EXE = $$last(cmd)
}
export($${1}_EXE)
QT_TOOL_ENV += $$eval(QT_TOOL.$${2}.envvars)
QT_TOOL_NAME = $$2
!isEmpty(3)|!isEmpty(4) {
$$1$$3 =
for (arg, cmd): \
$$1$$3 += $$system_quote($$arg)
qtAddTargetEnv($$1$$3, QT_TOOL.$${2}.depends, system)
}
isEmpty(4) {
$$1 =
for (arg, cmd): \
$$1 += $$shell_quote($$arg)
qtAddTargetEnv($$1, QT_TOOL.$${2}.depends, )
}
}
# target variable, list of env var names, [non-empty: prepare for system(), not make]
defineTest(qtAddToolEnv) {
isEmpty(3): \
ds = $$QMAKE_DIR_SEP
else: \
ds = $$DIR_SEPARATOR
batch_sets =
for(env, 2) {
value = $$eval($${env}.value)
!isEmpty(value) {
name = $$eval($${env}.name)
config = $$eval($${env}.CONFIG)
equals(ds, /) {
contains(config, prepend): infix = \${$$name:+:\$$$name}
else: contains(config, always_prepend): infix = :\$$$name
else: infix =
# Under msys, this path is taken only in the non-system()
# case, so using shell_quote() always works.
batch_sets += \
"$$name=$$shell_quote($$join(value, :))$$infix" \
"export $$name"
} else {
value ~= s,\\^,^^^^,g
value ~= s,!,^^!,g
value ~= s,\\),^),g
contains(config, prepend) {
batch_sets += \
"if defined $$name (" \
" set $$name=$$join(value, ;);!$$name!" \
") else (" \
" set $$name=$$join(value, ;)" \
")"
} else: contains(config, always_prepend) {
batch_sets += "(set $$name=$$join(value, ;);!$$name!)"
} else {
batch_sets += "(set $$name=$$join(value, ;))"
}
}
}
}
!isEmpty(batch_sets) {
batch_name = wrapper
!isEmpty(QT_TOOL_NAME): batch_name = $${QT_TOOL_NAME}_wrapper
cmd = $$eval($$1)
!isEmpty(cmd): cmd = "$$cmd "
equals(ds, /) {
batch_name = $${batch_name}.sh
batch_cont = \
"$$LITERAL_HASH!/bin/sh" \
$$batch_sets \
"exec $$cmd\"$@\""
# It would be nicer to use the '.' command (without 'exec' above),
# but that doesn't set the positional arguments under (d)ash.
$$1 =
} else {
batch_name = $${batch_name}.bat
batch_cont = \
"@echo off" \
"SetLocal EnableDelayedExpansion" \
$$batch_sets \
"$$cmd%*" \
"EndLocal"
$$1 = call
}
!build_pass:!write_file($$OUT_PWD/$$batch_name, batch_cont, exe): error()
isEmpty(3): \
$$1 += $$shell_quote($$shell_path($$OUT_PWD/$$batch_name))
else: \
$$1 += $$system_quote($$system_path($$OUT_PWD/$$batch_name))
QMAKE_DISTCLEAN += $$OUT_PWD/$$batch_name
}
export($$1)
export(QMAKE_DISTCLEAN)
}
# target variable, dependency var name, [non-empty: prepare for system(), not make]
defineTest(qtAddTargetEnv) {
deps = $$replace($$2, -private$, _private)
deps = $$resolve_depends(deps, "QT.", ".depends" ".run_depends")
!isEmpty(deps) {
deppath.CONFIG = prepend
equals(QMAKE_HOST.os, Windows) {
deppath.CONFIG = always_prepend
deppath.name = PATH
} else:contains(QMAKE_HOST.os, Linux|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|HP-UX|QNX|GNU) {
deppath.name = LD_LIBRARY_PATH
} else:contains(QMAKE_HOST.os, Haiku) {
deppath.name = LIBRARY_PATH
} else:equals(QMAKE_HOST.os, Darwin) {
qtConfig(framework): \
deppath.name = DYLD_FRAMEWORK_PATH
else: \
deppath.name = DYLD_LIBRARY_PATH
} else:equals(QMAKE_HOST.os, AIX) {
deppath.name = LIBPATH
} else {
error("Operating system not supported.")
}
ptypes =
for(dep, deps) {
isEmpty(3): \
deppath += $$shell_path($$eval(QT.$${dep}.libs))
else: \
deppath += $$system_path($$eval(QT.$${dep}.libs))
ptypes += $$eval(QT.$${dep}.plugin_types)
}
deppath.value = $$unique(deppath)
pluginpath.value =
ppaths = $$[QT_INSTALL_PLUGINS/get]
for(qplug, QT_PLUGINS): \
contains(ptypes, $$eval(QT_PLUGIN.$${qplug}.TYPE)): \
ppaths += $$eval(QT_PLUGIN.$${qplug}.PATH)
ppaths = $$unique(ppaths)
for(qplug, ppaths) {
isEmpty(3): \
pluginpath.value += $$shell_path($$qplug)
else: \
pluginpath.value += $$system_path($$qplug)
}
pluginpath.name = QT_PLUGIN_PATH
pluginpath.CONFIG = prepend
QT_TOOL_ENV += deppath pluginpath
}
qtAddToolEnv($$1, $$QT_TOOL_ENV, $$3)
}
defineReplace(pkgConfigExecutable) {
isEmpty(PKG_CONFIG) {
!isEmpty(QMAKE_PKG_CONFIG): \
PKG_CONFIG = $$QMAKE_PKG_CONFIG
else: \
PKG_CONFIG = pkg-config
sysroot.name = PKG_CONFIG_SYSROOT_DIR
sysroot.value = $$PKG_CONFIG_SYSROOT_DIR
libdir.name = PKG_CONFIG_LIBDIR
libdir.value = $$PKG_CONFIG_LIBDIR
QT_TOOL_NAME = pkg-config
qtAddToolEnv(PKG_CONFIG, sysroot libdir, SYS)
}
equals(QMAKE_HOST.os, Windows): \
PKG_CONFIG += 2> NUL
else: \
PKG_CONFIG += 2> /dev/null
return($$PKG_CONFIG)
}
defineTest(packagesExist) {
!qtConfig(pkg-config) {
warning("pkg-config disabled, can't check package existence")
return(false)
}
# this can't be done in global scope here because qt_functions is loaded
# before the .pro is parsed, so if the .pro set PKG_CONFIG, we wouldn't know it
# yet. oops.
pkg_config = $$pkgConfigExecutable()
for(package, ARGS) {
!system($$pkg_config --exists $$package):return(false)
}
return(true)
}
# Prepares target that will iterate through all subdirs (except those
# with no_default_target or no_{name_of_target}_target. The prepared
# target must still be manually added to QMAKE_EXTRA_TARGETS.
defineTest(prepareRecursiveTarget) {
target = $$1
no_$${target}_target: return()
for(subdir, SUBDIRS) {
subdir_config = $$eval($${subdir}.CONFIG)
contains(subdir_config, no_default_target): next()
contains(subdir_config, no_$${target}_target): next()
$${target}.recurse += $$subdir
}
# Set up the recurse target only when there
# is something to recurse into.
isEmpty($${target}.recurse): return()
$${target}.CONFIG = recursive
$${target}.recurse_target = $${target}
export($${target}.recurse)
export($${target}.CONFIG)
export($${target}.recurse_target)
}
defineTest(qtConfig) {
contains(QT.global.enabled_features, $$1): \
return(true)
contains(QT.global.disabled_features, $$1): \
return(false)
error("Could not find feature $${1}.")
}