qt5base-lts/mkspecs/features/toolchain.prf
Tor Arne Vestbø 9082cc8e8d macOS: Don't hard-code x86_64 as the architecture when using qmake
The qmake variable QMAKE_APPLE_DEVICE_ARCHS was added for iOS,
to support universal builds, as the QT_ARCH is a single value.

Since the qmake macOS builds are non-universal (at the moment),
we remove the hard-coded value for QMAKE_APPLE_DEVICE_ARCHS on
macOS, and let the normal architecture test resolve the arch,
like on other platforms.

To ensure that the following configuration tests are run with
an -arch argument, we trigger a commit of the preliminary Qt
configuration after running the architecture test. This is not
strictly necessary, but makes it clearer what's going on during
configure.

The device_and_simulator configuration option was used by the
iOS toolchain, and needed to be moved up in the configuration
test order to not break later tests.

The logic in mac/default_post.prf for both Xcode and Makefiles
to add -arch flags was kept as is, based on the existing
variable, to avoid too many changes to this logic.

The logic in toolchain.prf was amended to make it clear and
ensure that it only applies to iOS builds. macOS builds do
not have this issue.

Pick-to: 6.0
Pick-to: 5.15
Pick-to: 5.12
Change-Id: I70db7e4c27f0d3da5d0af33cb491d72c312d3fa8
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2020-12-07 15:35:55 +01:00

443 lines
18 KiB
Plaintext

defineTest(qtToolchainError) {
msg = \
$$1 \
"===================" \
$$2 \
"===================" \
$$3
error($$join(msg, $$escape_expand(\\n)))
}
defineTest(qtCompilerError) {
!cross_compile: \
what =
else: host_build: \
what = " host"
else: \
what = " target"
qtToolchainError("Cannot run$$what compiler '$$1'. Output:", $$2, \
"Maybe you forgot to setup the environment?")
}
cross_compile:host_build: \
target_prefix = QMAKE_HOST_CXX
else: \
target_prefix = QMAKE_CXX
#
# Determine and cache the compiler version
#
defineReplace(qtVariablesFromMSVC) {
ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) 2>NUL", lines, ec)
!equals(ec, 0): qtCompilerError($$1, $$ret)
return($$ret)
}
defineReplace(qtVariablesFromGCC) {
ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) \
2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec)
!equals(ec, 0): qtCompilerError($$1, $$ret)
return($$ret)
}
isEmpty($${target_prefix}.COMPILER_MACROS) {
msvc {
clang_cl {
# We need to obtain the cl.exe version first
vars = $$qtVariablesFromMSVC(cl)
for (v, vars) {
isEmpty(v)|contains(v, $${LITERAL_HASH}.*): next()
eval($$v)
}
isEmpty(QMAKE_MSC_FULL_VER): error("Could not determine the Visual Studio version")
QMAKE_CFLAGS_MSVC_COMPAT = $$replace(QMAKE_MSC_FULL_VER, "(..)(..)(.*)", \
"-fms-compatibility-version=\\1.\\2.\\3")
cache($${target_prefix}.QMAKE_CFLAGS_MSVC_COMPAT, set stash, QMAKE_CFLAGS_MSVC_COMPAT)
$${target_prefix}.COMPILER_MACROS += QMAKE_CFLAGS_MSVC_COMPAT
vars = $$qtVariablesFromMSVC($$QMAKE_CXX, $$QMAKE_CFLAGS_MSVC_COMPAT)
} else {
vars = $$qtVariablesFromMSVC($$QMAKE_CXX)
}
} else: gcc|ghs {
vars = $$qtVariablesFromGCC($$QMAKE_CXX)
}
for (v, vars) {
!contains(v, "[A-Z_]+ = .*"): next()
# Set both <varname> for the outer scope ...
eval($$v)
v ~= s/ .*//
isEmpty($$v): error("Compiler produced empty value for $${v}.")
# ... and save QMAKE_(HOST_)?CXX.<varname> in the cache.
cache($${target_prefix}.$$v, set stash, $$v)
$${target_prefix}.COMPILER_MACROS += $$v
}
cache($${target_prefix}.COMPILER_MACROS, set stash)
} else {
# load from the cache
for (i, $${target_prefix}.COMPILER_MACROS): \
$$i = $$eval($${target_prefix}.$$i)
}
# Populate QMAKE_COMPILER_DEFINES and some compatibility variables.
# The $$format_number() calls strip leading zeros to avoid misinterpretation as octal.
QMAKE_COMPILER_DEFINES += __cplusplus=$$QT_COMPILER_STDCXX
!isEmpty(QMAKE_MSC_VER): \
QMAKE_COMPILER_DEFINES += _MSC_VER=$$QMAKE_MSC_VER _MSC_FULL_VER=$$QMAKE_MSC_FULL_VER
!isEmpty(QMAKE_ICC_VER): \
QMAKE_COMPILER_DEFINES += __INTEL_COMPILER=$$QMAKE_ICC_VER __INTEL_COMPILER_UPDATE=$$QMAKE_ICC_UPDATE_VER
!isEmpty(QMAKE_APPLE_CC): \
QMAKE_COMPILER_DEFINES += __APPLE_CC__=$$QMAKE_APPLE_CC
!isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += __clang__ \
__clang_major__=$$QMAKE_APPLE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_APPLE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_APPLE_CLANG_PATCH_VERSION
!isEmpty(QMAKE_CLANG_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += __clang__ \
__clang_major__=$$QMAKE_CLANG_MAJOR_VERSION \
__clang_minor__=$$QMAKE_CLANG_MINOR_VERSION \
__clang_patchlevel__=$$QMAKE_CLANG_PATCH_VERSION
!isEmpty(QMAKE_GCC_MAJOR_VERSION): \
QMAKE_COMPILER_DEFINES += \
__GNUC__=$$QMAKE_GCC_MAJOR_VERSION \
__GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \
__GNUC_PATCHLEVEL__=$$QMAKE_GCC_PATCH_VERSION
!isEmpty(QMAKE_GHS_VERSION): \
QMAKE_COMPILER_DEFINES += __ghs__ __GHS_VERSION_NUMBER=$$QMAKE_GHS_VERSION
QMAKE_CFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT
clang_cl|intel_icl {
include(../common/msvc-based-version.conf)
} else: msvc {
include(../common/msvc-version.conf)
}
#
# Determine and cache the default search paths
#
defineReplace(qtMakeExpand) {
out = "$$1"
for(ever) {
m = $$replace(out, ".*\\$\\(EXPORT_([^)]+)\\).*", \\1)
equals(m, $$out): \
return($$out)
out = $$replace(out, "\\$\\(EXPORT_$$m\\)", $$eval($$m))
}
}
defineReplace(qtSplitPathList) {
paths = $$split(1, $$QMAKE_DIRLIST_SEP)
ret =
for (p, paths): \
ret += $$clean_path($$p)
return($$ret)
}
defineReplace(qtNmakePathList) {
paths =
for (p, 1): \
paths += $$shell_path($$p)
paths ~= s,$${LITERAL_HASH},^$${LITERAL_HASH},g
paths ~= s,\\$,\$\$,g
return($$join(paths, $$QMAKE_DIRLIST_SEP))
}
msvc {
arch = $$lower($$VCPROJ_ARCH)
equals(arch, x64): \ # may be "win32" or undefined
arch = amd64
else: !equals(arch, arm):!equals(arch, arm64): \ # may be "win32" or undefined
arch = x86
# Consider only ARM64 desktop builds to be cross-builds -
# the host is assumed to be Intel and capable of running the target
# executables (so building for x64 on x86 will break).
equals(arch, arm64): \
CONFIG += msvc_cross
}
isEmpty($${target_prefix}.INCDIRS) {
#
# Get default include and library paths from compiler
#
wasm {
# wasm compiler does not work here, just use defaults
} else: gcc {
cmd_suffix = "<$$QMAKE_SYSTEM_NULL_DEVICE >$$QMAKE_SYSTEM_NULL_DEVICE"
equals(QMAKE_HOST.os, Windows): \
cmd_prefix = "set LC_ALL=C&"
else: \
cmd_prefix = "LC_ALL=C"
cxx_flags = $$QMAKE_CXXFLAGS
# Manually inject the sysroot for Apple Platforms because its resolution
# normally does not happen until default_post.prf. This is especially
# important for moc to gain the correct default include directory list.
# While technically incorrect but without any likely practical effect,
# UIKit simulator platforms will see the device SDK's sysroot in
# QMAKE_DEFAULT_*DIRS, because they're handled in a single build pass.
darwin {
uikit {
# Clang doesn't automatically pick up the architecture, just because
# we're passing the iOS sysroot below, and we will end up building the
# test for the host architecture, resulting in linker errors when
# linking against the iOS libraries. We work around this by passing
# the architecture explicitly.
cxx_flags += -arch $$first(QMAKE_APPLE_DEVICE_ARCHS)
}
uikit:macx-xcode: \
cxx_flags += -isysroot $$sdk_path_device.value
else: \
cxx_flags += -isysroot $$QMAKE_MAC_SDK_PATH
}
rim_qcc: \
# Need the cc1plus and ld command lines to pick up the paths
cxx_flags += $$QMAKE_LFLAGS_SHLIB -o $$QMAKE_SYSTEM_NULL_DEVICE -v
else: darwin:clang: \
# Need to link to pick up library paths
cxx_flags += -g0 $$QMAKE_LFLAGS_SHLIB -o /dev/null -v -Wl,-v
else: \
# Just preprocess, might not pick up library paths
cxx_flags += -E -v
output = $$system("$$cmd_prefix $$QMAKE_CXX $$qtMakeExpand($$cxx_flags) -xc++ - 2>&1 $$cmd_suffix", lines, ec)
!equals(ec, 0): qtCompilerError($$QMAKE_CXX, $$output)
rim_qcc {
for (line, output) {
contains(line, "^[^ ]*cc1plus .*") {
take_next = false
for (parameter, $$list($$line)) {
$$take_next {
QMAKE_DEFAULT_INCDIRS += $$clean_path($$parameter)
take_next = false
} else: equals(parameter, "-isystem") {
take_next = true
}
}
} else: contains(line, "^[^ ]*-ld .*") {
for (parameter, $$list($$line)) {
contains(parameter, "^-L.*") {
parameter ~= s/^-L//
QMAKE_DEFAULT_LIBDIRS += $$clean_path($$parameter)
}
}
}
}
} else {
add_includes = false
add_libraries = false
for (line, output) {
line ~= s/^[ \\t]*// # remove leading spaces
contains(line, "LIBRARY_PATH=.*") {
line ~= s/^LIBRARY_PATH=// # remove leading LIBRARY_PATH=
equals(QMAKE_HOST.os, Windows): \
paths = $$split(line, ;)
else: \
paths = $$split(line, $$QMAKE_DIRLIST_SEP)
for (path, paths): \
QMAKE_DEFAULT_LIBDIRS += $$clean_path($$path)
} else: contains(line, "Library search paths:") {
add_libraries = true
} else: contains(line, "$${LITERAL_HASH}include <.*") { # #include <...> search starts here:
add_includes = true
} else: contains(line, "End of search.*") {
add_includes = false
} else: $$add_libraries {
# We assume all library search paths are absolute
!contains(line, "^/.*") {
add_libraries = false
next()
}
QMAKE_DEFAULT_LIBDIRS += $$clean_path($$line)
} else: $$add_includes {
!contains(line, ".* \\(framework directory\\)"): \
QMAKE_DEFAULT_INCDIRS += $$clean_path($$line)
}
}
}
if(!darwin:clang)|intel_icc {
# Clang on a non-Apple system (that is, a system without ld64 -- say, with GNU ld
# or gold under Linux) will not print any library search path. Need to use another
# invocation with different options (which in turn doesn't print include search
# paths, so it can't just be used in place of the above code).
# What's more, -print-search-dirs can't be used on clang on Apple because it
# won't print all the library paths (only the clang-internal ones).
output = $$system("$$cmd_prefix $$QMAKE_LINK $$QMAKE_LFLAGS -print-search-dirs", lines, ec)
!equals(ec, 0): qtCompilerError($$QMAKE_LINK, $$output)
for (line, output) {
contains(line, "^libraries: .*") {
line ~= s,^libraries: ,,
equals(QMAKE_HOST.os, Windows) {
# clang (7.x) on Windows uses the wrong path list separator ...
line ~= s,:(?![/\\\\]),;,
paths = $$split(line, ;)
} else {
paths = $$split(line, $$QMAKE_DIRLIST_SEP)
}
for (path, paths): \
QMAKE_DEFAULT_LIBDIRS += $$clean_path($$replace(path, ^=, $$[SYSROOT]))
}
}
}
isEmpty(QMAKE_DEFAULT_LIBDIRS)|isEmpty(QMAKE_DEFAULT_INCDIRS): \
!integrity: \
error("failed to parse default search paths from compiler output")
QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
} else: ghs {
cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp
output = $$system("$$cmd", blob, ec)
!equals(ec, 0): qtCompilerError($$QMAKE_CXX, $$output)
output ~= s/\\\\\\n {8}//g
output = $$split(output, $$escape_expand(\\n))
for (line, output) {
contains(line, "^[^ ]+/ecom[^ ]+ .* /tmp/fake_input\\.cpp") {
for (parameter, $$list($$line)) {
contains(parameter, "^(-I|--include_no_mmd=|--sys_include=).*") {
parameter ~= s/^(-I|--include_no_mmd=|--sys_include=)//
QMAKE_DEFAULT_INCDIRS += $$clean_path($$parameter)
}
}
} else: contains(line, "^[^ ]+/elxr .*") {
for (parameter, $$list($$line)) {
contains(parameter, "^-L.*") {
parameter ~= s/^-L//
QMAKE_DEFAULT_LIBDIRS += $$clean_path($$parameter)
}
}
}
}
} else: msvc_cross {
# Use a batch file, because %VAR% in the system() call expands to
# the pre-script-call value, and !VAR! cannot be enabled outside
# a batch file without invoking another shell instance.
cmd = $$system_quote($$system_path($$PWD/data/dumpvcvars.bat))
hostArch = $$QMAKE_HOST.arch
equals(hostArch, x86_64): \
hostArch = amd64
!equals(arch, $$hostArch): \
arch = $${hostArch}_$$arch
isEmpty(MSVC_VER): \
error("Mkspec does not specify MSVC_VER. Cannot continue.")
versionAtLeast(MSVC_VER, 15.0) {
dir = $$(VSINSTALLDIR)
isEmpty(dir) {
version_parts = $$split(MSVC_VER, .)
MSVC_NEXT_MAJOR = $$num_add($$first(version_parts), 1)
vswhere = "$$getenv(ProgramFiles\(x86\))/Microsoft Visual Studio/Installer/vswhere.exe"
!exists($$vswhere): \
error("Could not find $$vswhere")
vswhere = $$system_quote($$system_path($$vswhere))
# -version parameter: A version range for instances to find. 15.0 will get all versions >= 15.0
# Example: [15.0,16.0) will find versions 15.*.
dir = $$system("$$vswhere -latest -version [$$MSVC_VER,$${MSVC_NEXT_MAJOR}.0] -property installationPath")
}
isEmpty(dir): \
error("Failed to find the Visual Studio installation directory.")
cmd += $$system_quote($$dir\\VC\\Auxiliary\\Build\\vcvarsall.bat) $$arch
} else {
dir = $$(VCINSTALLDIR)
isEmpty(dir): \
dir = $$read_registry(HKLM, \
"Software\\Microsoft\\VisualStudio\\$$MSVC_VER\\Setup\\VC\\ProductDir", 32)
isEmpty(dir): \
error("Failed to find the Visual C installation directory.")
cmd += $$system_quote($$dir\\vcvarsall.bat) $$arch
}
isEmpty(WINSDK_VER): \
error("Mkspec does not specify WINSDK_VER. Cannot continue.")
# We prefer the environment variable, because that may work around
# a broken registry entry after uninstalling a newer SDK.
# However, we do that only if the major+minor SDK version matches
# the one requested by the mkspec, as we might be building for a
# newer target than the host.
winsdk_ver = $$(WindowsSDKVersion)
!isEmpty(winsdk_ver) {
winsdk_ver ~= s,\\\\$,, # Work around SDK breakage.
!equals(WINSDK_VER, $$replace(winsdk_ver, ^(\\d+\\.\\d+).*$, \\1)): \
winsdk_ver =
}
!isEmpty(winsdk_ver) {
cmd += $$winsdk_ver
} else {
winsdk_ver = $$read_registry(HKLM, \
"Software\\Microsoft\\Microsoft SDKs\\Windows\\v$$WINSDK_VER\\ProductVersion", 32)
isEmpty(winsdk_ver): \
error("Windows SDK $$WINSDK_VER requested by mkspec is not installed. Cannot continue.")
cmd += $${winsdk_ver}.0
}
output = $$system("$$cmd 2>&1", lines, ec)
!equals(ec, 0): \
qtToolchainError("SDK setup script failed. Output:", $$output, \
"Command was: $$cmd")
lines = $$output
for(ever) {
isEmpty(lines): \
break()
line = $$take_first(lines)
equals(line, "=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+="): \
break()
}
!count(lines, 3): \
qtToolchainError("SDK setup script returned unexpected output:", $$output, \
"Command was: $$cmd")
# These contain only paths for the target.
QMAKE_DEFAULT_INCDIRS = $$qtSplitPathList($$member(lines, 0))
QMAKE_DEFAULT_LIBDIRS = $$qtSplitPathList($$member(lines, 1))
# PATH is inherently for the host, and paths that are not shadowed
# by vcvarsall.bat are assumed to contain only tools that work for
# both host and target builds.
QMAKE_DEFAULT_PATH = $$qtSplitPathList($$member(lines, 2))
# We de-duplicate, because the script just prepends to the paths for
# the host, some of which are identical to the ones for the target.
QMAKE_DEFAULT_PATH = $$unique(QMAKE_DEFAULT_PATH)
} 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:if(!cross_compile|host_build) {
isEmpty(QMAKE_DEFAULT_INCDIRS): QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include
isEmpty(QMAKE_DEFAULT_LIBDIRS): QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib
}
# cache() complains about undefined variables and doesn't persist empty ones.
!isEmpty(QMAKE_DEFAULT_INCDIRS): \
cache($${target_prefix}.INCDIRS, set stash, QMAKE_DEFAULT_INCDIRS)
!isEmpty(QMAKE_DEFAULT_LIBDIRS): \
cache($${target_prefix}.LIBDIRS, set stash, QMAKE_DEFAULT_LIBDIRS)
!isEmpty(QMAKE_DEFAULT_PATH): \
cache($${target_prefix}.PATH, set stash, QMAKE_DEFAULT_PATH)
} else {
QMAKE_DEFAULT_INCDIRS = $$eval($${target_prefix}.INCDIRS)
QMAKE_DEFAULT_LIBDIRS = $$eval($${target_prefix}.LIBDIRS)
QMAKE_DEFAULT_PATH = $$eval($${target_prefix}.PATH)
}
msvc_cross {
qmake_inc_exp.name = INCLUDE
qmake_inc_exp.value = $$qtNmakePathList($$QMAKE_DEFAULT_INCDIRS)
qmake_lib_exp.name = LIB
qmake_lib_exp.value = $$qtNmakePathList($$QMAKE_DEFAULT_LIBDIRS)
qmake_path_exp.name = PATH
qmake_path_exp.value = $$qtNmakePathList($$QMAKE_DEFAULT_PATH)
QMAKE_EXPORTED_VARIABLES += qmake_inc_exp qmake_lib_exp qmake_path_exp
}
unset(target_prefix)