| 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 WinRT and 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). |
| winrt|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: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): \ |
| dir = $$read_registry(HKLM, \ |
| "Software\\Microsoft\\VisualStudio\\SxS\\VS7\\$$MSVC_VER", 32) |
| 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 |
| } |
| winrt: cmd += store |
| |
| 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) |