diff options
Diffstat (limited to 'mkspecs/features/qt_configure.prf')
-rw-r--r-- | mkspecs/features/qt_configure.prf | 2471 |
1 files changed, 0 insertions, 2471 deletions
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf deleted file mode 100644 index 4c18dbf953..0000000000 --- a/mkspecs/features/qt_configure.prf +++ /dev/null @@ -1,2471 +0,0 @@ -# -# W A R N I N G -# ------------- -# -# This file is not part of the Qt API. It exists purely as an -# implementation detail. It may change from version to version -# without notice, or even be removed. -# -# We mean it. -# - -QT_CONFIGURE_REPORT = -QT_CONFIGURE_NOTES = -QT_CONFIGURE_WARNINGS = -QT_CONFIGURE_ERRORS = - -defineTest(qtConfAddReport) { - QT_CONFIGURE_REPORT += "$$join(1, $$escape_expand(\\n))" - export(QT_CONFIGURE_REPORT) -} - -defineTest(qtConfAddNote) { - QT_CONFIGURE_NOTES += "Note: $$join(1, $$escape_expand(\\n))" - export(QT_CONFIGURE_NOTES) -} - -defineTest(qtConfAddWarning) { - QT_CONFIGURE_WARNINGS += "WARNING: $$join(1, $$escape_expand(\\n))" - export(QT_CONFIGURE_WARNINGS) -} - -defineTest(qtConfAddError) { - QT_CONFIGURE_ERRORS += "ERROR: $$join(1, $$escape_expand(\\n))" - export(QT_CONFIGURE_ERRORS) - equals(2, log):qt_conf_tests_allowed { - CONFIG += mention_config_log - export(CONFIG) - } -} - -defineTest(qtConfFatalError) { - qtConfAddError($$1, $$2) - qtConfPrintReport() - error() -} - -# Return a string list for the specified JSON path, which may be either a -# single string or an array of strings. -# Note that this returns a variable name, so it can be directly iterated over. -defineReplace(qtConfScalarOrList) { - defined($$1, var): return($$1) - vals = $$list() - for (i, $${1}._KEYS_): \ - $$vals += $$eval($${1}.$$i) - export($$vals) - return($$vals) -} - -defineTest(qtConfCommandlineSetInput) { - arg = $${1} - val = $${2} - !isEmpty($${currentConfig}.commandline.options.$${arg}.name): \ - arg = $$eval($${currentConfig}.commandline.options.$${arg}.name) - !isEmpty(config.input.$$arg) { - oldval = $$eval(config.input.$$arg) - equals(oldval, $$val): \ - qtConfAddNote("Option '$$arg' with value '$$val' was specified twice") - else: \ - qtConfAddNote("Overriding option '$$arg' with '$$val' (was: '$$oldval')") - } - - config.input.$$arg = $$val - export(config.input.$$arg) -} - -defineReplace(qtConfGetNextCommandlineArg) { - c = $$take_first(QMAKE_EXTRA_ARGS) - export(QMAKE_EXTRA_ARGS) - return($$c) -} - -defineReplace(qtConfPeekNextCommandlineArg) { - return($$first(QMAKE_EXTRA_ARGS)) -} - -defineTest(qtConfCommandline_boolean) { - opt = $${1} - val = $${2} - isEmpty(val): val = yes - - !equals(val, yes):!equals(val, no) { - qtConfAddError("Invalid value given for boolean command line option '$$opt'.") - return() - } - - qtConfCommandlineSetInput($$opt, $$val) -} - -defineTest(qtConfCommandline_void) { - opt = $${1} - val = $${2} - !isEmpty(val) { - qtConfAddError("Command line option '$$opt' expects no argument ('$$val' given).") - return() - } - - val = $$eval($${currentConfig}.commandline.options.$${opt}.value) - isEmpty(val): val = yes - - qtConfCommandlineSetInput($$opt, $$val) -} - -defineTest(qtConfCommandline_enum) { - opt = $${1} - val = $${2} - isEmpty(val): val = yes - - # validate and map value - mapped = $$eval($${currentConfig}.commandline.options.$${opt}.values.$${val}) - isEmpty(mapped) { - # just a list of allowed values - for (i, $${currentConfig}.commandline.options.$${opt}.values._KEYS_) { - equals($${currentConfig}.commandline.options.$${opt}.values.$${i}, $$val) { - mapped = $$val - break() - } - } - } - isEmpty(mapped) { - qtConfAddError("Invalid value '$$val' supplied to command line option '$$opt'.") - return() - } - - qtConfCommandlineSetInput($$opt, $$mapped) -} - -defineTest(qtConfValidateValue) { - opt = $${1} - val = $${2} - - validValues = $$eval($${currentConfig}.commandline.options.$${opt}.values._KEYS_) - isEmpty(validValues): \ - return(true) - - for (i, validValues) { - equals($${currentConfig}.commandline.options.$${opt}.values.$${i}, $$val): \ - return(true) - } - - qtConfAddError("Invalid value '$$val' supplied to command line option '$$opt'.") - return(false) -} - -defineTest(qtConfCommandline_string) { - opt = $${1} - val = $${2} - nextok = $${3} - isEmpty(val):$$nextok: val = $$qtConfGetNextCommandlineArg() - - # Note: Arguments which are variable assignments are legit here. - contains(val, "^-.*")|isEmpty(val) { - qtConfAddError("No value supplied to command line option '$$opt'.") - return() - } - - !qtConfValidateValue($$opt, $$val): \ - return() - - qtConfCommandlineSetInput($$opt, $$val) -} - -defineTest(qtConfCommandline_optionalString) { - opt = $${1} - val = $${2} - nextok = $${3} - isEmpty(val) { - $$nextok: val = $$qtConfPeekNextCommandlineArg() - contains(val, "^-.*|[A-Z0-9_]+=.*")|isEmpty(val): \ - val = "yes" - else: \ - val = $$qtConfGetNextCommandlineArg() - } - - !qtConfValidateValue($$opt, $$val): \ - return() - - qtConfCommandlineSetInput($$opt, $$val) -} - - -defineTest(qtConfCommandline_addString) { - opt = $${1} - val = $${2} - nextok = $${3} - isEmpty(val):$$nextok: val = $$qtConfGetNextCommandlineArg() - - # Note: Arguments which are variable assignments are legit here. - contains(val, "^-.*")|isEmpty(val) { - qtConfAddError("No value supplied to command line option '$$opt'.") - return() - } - - !qtConfValidateValue($$opt, $$val): \ - return() - - !isEmpty($${currentConfig}.commandline.options.$${opt}.name): \ - opt = $$eval($${currentConfig}.commandline.options.$${opt}.name) - - config.input.$$opt += $$val - export(config.input.$$opt) -} - -defineTest(qtConfCommandline_redo) { - !exists($$OUT_PWD/config.opt) { - qtConfAddError("No config.opt present - cannot redo configuration.") - return() - } - QMAKE_EXTRA_REDO_ARGS = $$cat($$OUT_PWD/config.opt, lines) - export(QMAKE_EXTRA_REDO_ARGS) # just for config.log - QMAKE_EXTRA_ARGS = $$QMAKE_EXTRA_REDO_ARGS $$QMAKE_EXTRA_ARGS - export(QMAKE_EXTRA_ARGS) - QMAKE_REDO_CONFIG = true - export(QMAKE_REDO_CONFIG) -} - -defineTest(qtConfParseCommandLine) { - customCalls = - for (cc, allConfigs) { - custom = $$eval($${cc}.commandline.custom) - - !isEmpty(custom) { - customCall = qtConfCommandline_$$custom - !defined($$customCall, test): \ - error("Custom command line callback '$$custom' is undefined.") - customCalls += $$customCall - } - } - - for (ever) { - c = $$qtConfGetNextCommandlineArg() - isEmpty(c): break() - - didCustomCall = false - for (customCall, customCalls) { - $${customCall}($$c) { - didCustomCall = true - break() - } - } - $$didCustomCall: \ - next() - - contains(c, "([A-Z0-9_]+)=(.*)") { - opt = $$replace(c, "^([A-Z0-9_]+)=(.*)", "\\1") - val = $$replace(c, "^([A-Z0-9_]+)=(.*)", "\\2") - for (cc, allConfigs) { - var = $$eval($${cc}.commandline.assignments.$${opt}) - !isEmpty(var): \ - break() - } - isEmpty(var) { - qtConfAddError("Assigning unknown variable '$$opt' on command line.") - return() - } - config.input.$$var = $$val - export(config.input.$$var) - next() - } - - # parse out opt and val - nextok = false - contains(c, "^--?enable-(.*)") { - opt = $$replace(c, "^--?enable-(.*)", "\\1") - val = yes - } else: contains(c, "^--?(disable|no)-(.*)") { - opt = $$replace(c, "^--?(disable|no)-(.*)", "\\2") - val = no - } else: contains(c, "^--([^=]+)=(.*)") { - opt = $$replace(c, "^--([^=]+)=(.*)", "\\1") - val = $$replace(c, "^--([^=]+)=(.*)", "\\2") - } else: contains(c, "^--(.*)") { - opt = $$replace(c, "^--(.*)", "\\1") - val = - } else: contains(c, "^-(.*)") { - opt = $$replace(c, "^-(.*)", "\\1") - val = - nextok = true - for (cc, allConfigs) { - type = $$eval($${cc}.commandline.options.$${opt}) - !isEmpty(type): break() - type = $$eval($${cc}.commandline.options.$${opt}.type) - !isEmpty(type): break() - } - isEmpty(type):contains(opt, "(qt|system)-.*") { - val = $$replace(opt, "(qt|system)-(.*)", "\\1") - opt = $$replace(opt, "(qt|system)-(.*)", "\\2") - } - } else { - qtConfAddError("Invalid command line parameter '$$c'.") - return() - } - - for (cc, allConfigs) { - type = $$eval($${cc}.commandline.options.$${opt}) - isEmpty(type): \ - type = $$eval($${cc}.commandline.options.$${opt}.type) - isEmpty(type) { - # no match in the regular options, try matching the prefixes - for (p, $${cc}.commandline.prefix._KEYS_) { - e = "^-$${p}(.*)" - contains(c, $$e) { - opt = $$eval($${cc}.commandline.prefix.$${p}) - val = $$replace(c, $$e, "\\1") - nextok = true - type = "addString" - break() - } - } - } - !isEmpty(type) { - currentConfig = $$cc - break() - } - } - # handle builtin [-no]-feature-xxx - isEmpty(type):contains(opt, "feature-(.*)") { - opt ~= s,^feature-,, - found = false - for (cc, allConfigs) { - contains($${cc}.features._KEYS_, $$opt) { - found = true - break() - } - } - !$$found { - qtConfAddError("Enabling/Disabling unknown feature '$$opt'.") - return() - } - # this is a boolean enabling/disabling the corresponding feature - type = boolean - } - - # Skip the -qmake option. - isEmpty(type):contains(opt, "qmake") { - next() - } - - isEmpty(type):contains(opt, "skip") { - isEmpty(skipOptionWarningAdded) { - qtConfAddWarning("Command line option -skip is only effective in top-level builds.") - skipOptionWarningAdded = 1 - } - val = $$qtConfGetNextCommandlineArg() - next() - } - - isEmpty(type) { - qtConfAddError("Unknown command line option '$$c'.") - equals(config.input.continue, yes): \ - next() - else: \ - return() - } - - call = "qtConfCommandline_$${type}" - !defined($$call, test): \ - error("Command line option '$$c' has unknown type '$$type'.") - - # now that we have opt and value, process it - $${call}($$opt, $$val, $$nextok) - } -} - -defineReplace(qtConfToolchainSupportsFlag) { - test_out_dir = $$OUT_PWD/$$basename(QMAKE_CONFIG_TESTS_DIR) - test_cmd_base = "$$QMAKE_CD $$system_quote($$system_path($$test_out_dir)) &&" - - conftest = "int main() { return 0; }" - write_file("$$test_out_dir/conftest.cpp", conftest)|error() - - qtRunLoggedCommand("$$test_cmd_base $$QMAKE_CXX $$QMAKE_CXXFLAGS $${1} -o conftest-out conftest.cpp"): \ - return(true) - return(false) -} - -defineTest(qtConfTest_compilerSupportsFlag) { - flag = $$eval($${1}.flag) - - return($$qtConfToolchainSupportsFlag($$flag)) -} - -defineTest(qtConfTest_linkerSupportsFlag) { - flag = $$eval($${1}.flag) - - use_bfd_linker: \ - LFLAGS = -fuse-ld=bfd - use_gold_linker: \ - LFLAGS = -fuse-ld=gold - use_lld_linker: \ - LFLAGS = -fuse-ld=lld - - return($$qtConfToolchainSupportsFlag($$LFLAGS "-Wl,$$flag")) -} - -defineReplace(qtConfFindInPathList) { - # This nesting is consistent with Apple ld -search_paths_first, - # and presumably with GNU ld (no actual documentation found). - for (dir, 2) { - for (file, 1) { - exists("$$dir/$$file"): \ - return("$$dir/$$file") - } - } - return() -} - -defineReplace(qtConfFindInPath) { - ensurePathEnv() - equals(QMAKE_HOST.os, Windows):!contains(1, .*\\.exe): 1 = $${1}.exe - return($$qtConfFindInPathList($$1, $$2 $$QMAKE_PATH_ENV)) -} - -defineReplace(qtConfPkgConfigEnv) { - env = - !isEmpty(PKG_CONFIG_SYSROOT_DIR): env = "$${SETENV_PFX}PKG_CONFIG_SYSROOT_DIR=$${PKG_CONFIG_SYSROOT_DIR}$${SETENV_SFX} " - !isEmpty(PKG_CONFIG_LIBDIR): env = "$$env$${SETENV_PFX}PKG_CONFIG_LIBDIR=$${PKG_CONFIG_LIBDIR}$${SETENV_SFX} " - return($$env) -} - -defineReplace(qtConfPkgConfig) { - host = $$1 - isEmpty(host): host = false - - $$host { - pkg_config = $$qtConfFindInPath("pkg-config") - } else { - pkg_config = "$$qtConfPkgConfigEnv()$$PKG_CONFIG_EXECUTABLE" - } - - return($$pkg_config) -} - -defineTest(qtConfPkgConfigPackageExists) { - isEmpty(1)|isEmpty(2): \ - return(false) - - !qtRunLoggedCommand("$${1} --exists --silence-errors $${2}"): \ - return(false) - - return(true) -} - -defineReplace(qtSystemQuote) { - args = - for (a, 1): \ - args += $$system_quote($$a) - return($$args) -} - -defineReplace(qtConfPrepareArgs) { - return($$qtSystemQuote($$split(1))) -} - -defineTest(qtConfSetupLibraries) { - asspfx = $${currentConfig}.commandline.assignments - for (l, $${currentConfig}.libraries._KEYS_) { - lpfx = $${currentConfig}.libraries.$${l} - # 'export' may be omitted, in which case it falls back to the library's name - !defined($${lpfx}.export, var) { - $${lpfx}.export = $$replace(l, -, _) - export($${lpfx}.export) - } - # 'export' may also be empty, but we need a derived identifier - alias = $$eval($${lpfx}.export) - isEmpty(alias): alias = $$replace(l, -, _) - $${lpfx}.alias = $$alias - export($${lpfx}.alias) - # make it easy to refer to the library by its export name. - $${currentConfig}.exports._KEYS_ += $$alias - $${currentConfig}.exports.$$alias += $$l - export($${currentConfig}.exports.$$alias) - isEmpty($${lpfx}.sources._KEYS_): \ - error("Library $$l defines no sources") - for (s, $${lpfx}.sources._KEYS_) { - spfx = $${lpfx}.sources.$${s} - # link back to parent object - $${spfx}.library = $$l - export($${spfx}.library) - # a plain string is transformed into a structure - isEmpty($${spfx}._KEYS_) { - $${spfx}.libs = $$eval($${spfx}) - export($${spfx}.libs) - } - # if the type is missing (implicitly in the case of plain strings), assume 'inline' - isEmpty($${spfx}.type) { - $${spfx}.type = inline - export($${spfx}.type) - } - } - } - $${currentConfig}.exports._KEYS_ = $$unique($${currentConfig}.exports._KEYS_) - export($${currentConfig}.exports._KEYS_) - - for (alias, $${currentConfig}.exports._KEYS_) { - ua = $$upper($$alias) - $${asspfx}._KEYS_ += \ - $${ua}_PREFIX $${ua}_INCDIR $${ua}_LIBDIR \ - $${ua}_LIBS $${ua}_LIBS_DEBUG $${ua}_LIBS_RELEASE - uapfx = $${asspfx}.$${ua} - $${uapfx}_PREFIX = $${alias}.prefix - $${uapfx}_INCDIR = $${alias}.incdir - $${uapfx}_LIBDIR = $${alias}.libdir - $${uapfx}_LIBS = $${alias}.libs - $${uapfx}_LIBS_DEBUG = $${alias}.libs.debug - $${uapfx}_LIBS_RELEASE = $${alias}.libs.release - export($${uapfx}_PREFIX) - export($${uapfx}_INCDIR) - export($${uapfx}_LIBDIR) - export($${uapfx}_LIBS) - export($${uapfx}_LIBS_DEBUG) - export($${uapfx}_LIBS_RELEASE) - } - export($${asspfx}._KEYS_) - - # reverse mapping for assignments on command line. - for (a, $${asspfx}._KEYS_) { - apfx = $${asspfx}.$${a} - ra = config.commandline.rev_assignments.$$eval($$apfx) - $$ra = $$a - export($$ra) - } -} - -defineReplace(qtGccSysrootifiedPath) { - return($$replace(1, ^=, $$[QT_SYSROOT])) -} - -defineReplace(qtGccSysrootifiedPaths) { - sysrootified = - for (path, 1): \ - sysrootified += $$qtGccSysrootifiedPath($$path) - return($$sysrootified) -} - -# libs-var, libs, in-paths -defineTest(qtConfResolveLibs) { - for (path, 3): \ - pre_lflags += -L$$path - $$1 = $$pre_lflags $$2 - export($$1) - return(true) -} - -# libs-var, in-paths, libs -defineTest(qtConfResolvePathLibs) { - ret = true - gcc: \ - local_paths = $$qtGccSysrootifiedPaths($$2) - else: \ - local_paths = $$2 - for (libdir, local_paths) { - !exists($$libdir/.) { - qtLog("Library path $$val_escape(libdir) is invalid.") - ret = false - } - } - !qtConfResolveLibs($$1, $$3, $$2): \ - ret = false - return($$ret) -} - -defineReplace(qtConfGetTestSourceList) { - result = - !isEmpty($${1}.test.inherit) { - base = $$section(1, ., 0, -2) - for (i, $${1}.test.inherit): \ - result += $$qtConfGetTestSourceList($${base}.$$i) - } - return($$result $$1) -} - -defineReplace(qtConfGetTestIncludes) { - defined($${1}._KEYS_, var) { - 1st = $$first($${1}._KEYS_) - equals(1st, 0) { - # array; recurse for every element - ret = - for (k, $${1}._KEYS_): \ - ret += $$qtConfGetTestIncludes($${1}.$$k) - return($$ret) - } - # object; try condition and recurse - !defined($${1}.headers, var):!defined($${1}.headers._KEYS_, var): \ # just plain broken without it - error("headers object '$$1' has no nested headers entry") - cond = $$eval($${1}.condition) - isEmpty(cond): \ # would be pointless otherwise - error("headers object '$$1' has no condition") - !$$qtConfEvaluate($$cond) { - qtLog("header entry '$$1' failed condition '$$cond'.") - return() - } - qtLog("header entry '$$1' passed condition.") - return($$qtConfGetTestIncludes($${1}.headers)) - } - return($$eval($$1)) # plain string - or nothing (can happen for top-level call only) -} - -# includes-var, in-paths, test-object-var -defineTest(qtConfResolvePathIncs) { - ret = true - gcc: \ - local_paths = $$qtGccSysrootifiedPaths($$2) - else: \ - local_paths = $$2 - for (incdir, local_paths) { - !exists($$incdir/.) { - qtLog("Include path $$val_escape(incdir) is invalid.") - ret = false - } - } - 2 -= $$QMAKE_DEFAULT_INCDIRS - $$1 = $$2 - export($$1) - wasm { - # FIXME: emcc downloads pre-built libraries and adds their include - # path to the clang call dynamically. it would be possible to parse - # the emcc -s USE_xyz=1 --cflags output to populate xzy_INCDIR and - # thus make the code below work. - return($$ret) - } - tests = $$qtConfGetTestSourceList($$3) - hdrs = - for (test, tests): \ - hdrs += $$qtConfGetTestIncludes($${test}.headers) - for (hdr, hdrs) { - h = $$qtConfFindInPathList($$hdr, $$2 $$EXTRA_INCLUDEPATH $$QMAKE_DEFAULT_INCDIRS) - isEmpty(h) { - qtLog("$$hdr not found in [$$val_escape(2)] and global paths.") - ret = false - } - } - return($$ret) -} - -# the library is specified inline in a 'libs' field. -# overrides from the command line are accepted. -defineTest(qtConfLibrary_inline) { - lib = $$eval($${1}.library) - !defined($${1}.libs, var):isEmpty($${1}.builds._KEYS_): \ - error("'inline' source in library '$$lib' specifies neither 'libs' nor 'builds'.") - - # library lists are specified as strings in the json sources for - # readability, but it's a pain to work with that, so expand it now. - eval($${1}.libs = $$eval($${1}.libs)) - export($${1}.libs) - for (b, $${1}.builds._KEYS_) { - eval($${1}.builds.$${b} = $$eval($${1}.builds.$${b})) - export($${1}.builds.$${b}) - } - - # if multiple libraries provide the same export, it makes sense - # to make them recognize the same input variables. - input = $$eval($${2}.alias) - - # build-specific direct libs. overwrites inline libs. - vars = - any = false - all = true - for (b, $$list(debug release)) { - iv = $${input}.libs.$${b} - vars += $$eval(config.commandline.rev_assignments.$${iv}) - defined(config.input.$${iv}, var) { - eval($${1}.builds.$${b} = $$eval(config.input.$${iv})) - export($${1}.builds.$${b}) - $${1}.builds._KEYS_ *= $${b} - any = true - } else { - all = false - } - } - $$any { - !$$all { - qtConfAddError("Either none or all of $$join(vars, ", ", [, ]) must be specified.") - return(false) - } - export($${1}.builds._KEYS_) - # we also reset the generic libs, to avoid surprises. - $${1}.libs = - export($${1}.libs) - } - - # direct libs. overwrites inline libs. - defined(config.input.$${input}.libs, var) { - eval($${1}.libs = $$eval(config.input.$${input}.libs)) - export($${1}.libs) - } - - includes = $$eval(config.input.$${input}.incdir) - - # prefix. prepends to (possibly overwritten) inline libs. - prefix = $$eval(config.input.$${input}.prefix) - !isEmpty(prefix) { - includes += $$prefix/include - $${1}.libs = -L$$prefix/lib $$eval($${1}.libs) - export($${1}.libs) - } - - libdir = $$eval(config.input.$${input}.libdir) - !isEmpty(libdir) { - libs = - for (ld, libdir): \ - libs += -L$$ld - $${1}.libs = $$libs $$eval($${1}.libs) - export($${1}.libs) - } - - !qtConfResolvePathIncs($${1}.includedir, $$includes, $$2): \ - return(false) - - return(true) -} - -# the library is provided by the qmake spec. -# this source type cannot fail. -defineTest(qtConfLibrary_makeSpec) { - spec = $$eval($${1}.spec) - isEmpty(spec): \ - error("makeSpec source in library '$$eval($${1}.library)' does not specify 'spec'.") - - !qtConfResolvePathLibs($${1}.libs, $$eval(QMAKE_LIBDIR_$$spec), $$eval(QMAKE_LIBS_$$spec)): \ - return(false) - - !qtConfResolvePathIncs($${1}.includedir, $$eval(QMAKE_INCDIR_$$spec), $$2): \ - return(false) - - !isEmpty(QMAKE_EXPORT_INCDIR_$$spec) { - $${1}.exportincludedir = $$eval(QMAKE_EXPORT_INCDIR_$$spec) - export($${1}.exportincludedir) - } - - # note that the object is re-exported, because we resolve the libraries. - - return(true) -} - -# the library is found via pkg-config. -defineTest(qtConfLibrary_pkgConfig) { - pkg_config = $$qtConfPkgConfig($$eval($${1}.host)) - isEmpty(pkg_config) { - qtLog("pkg-config use disabled globally.") - return(false) - } - args = $$qtConfPrepareArgs($$eval($${1}.args)) - - !qtConfPkgConfigPackageExists($$pkg_config, $$args) { - qtLog("pkg-config did not find package.") - return(false) - } - - qtRunLoggedCommand("$$pkg_config --modversion $$args", version)|return(false) - version ~= s/[^0-9.].*$// - $${1}.version = $$first(version) - export($${1}.version) - - qtRunLoggedCommand("$$pkg_config --libs-only-L $$args", libpaths)|return(false) - qtRunLoggedCommand("$$pkg_config --libs-only-l $$args", libs)|return(false) - eval(libs = $$libpaths $$libs) - !qtConfResolveLibs($${1}.libs, $$libs): \ - return(false) - contains($${1}.libs, ".*\\.$${QMAKE_EXTENSION_STATICLIB}$") { - qtRunLoggedCommand("$$pkg_config --static --libs $$args", libs)|return(false) - # Split by space - eval(libs = $$libs) - !qtConfResolveLibs($${1}.libs, $$libs): \ - return(false) - } - - qtRunLoggedCommand("$$pkg_config --cflags $$args", $${1}.cflags)|return(false) - # Split CFLAGS into stuff that goes into DEFINES, INCLUDEPATH, and other stuff. - # The compound variable is still set in case something wants to use it outside - # regular library exports. - defines = - includes = - ignored = - eval(cflags = $$eval($${1}.cflags)) - for (i, cflags) { - contains(i, "-I.*") { - i ~= s/^-I// - includes += $$i - } else: contains(i, "-D.*") { - i ~= s/^-D// - defines += $$i - } else { - # Sometimes, pkg-config files include other flags - # we really don't need and shouldn't add. - ignored += $$i - } - } - !isEmpty(ignored): \ - qtLog("Note: Dropped compiler flags '$$ignored'.") - !qtConfResolvePathIncs($${1}.includedir, $$includes, $$2): \ - return(false) - $${1}.defines = $$defines - - # now remove the content of the transitive deps we know about. - largs = $$qtConfAllLibraryArgs($$eval($${2}.dependencies)) - for (la, largs): \ - eval("$$la") - USES = $$eval($$list($$upper($$replace(QMAKE_USE, -, _)))) - # _CC == _LD for configure's library sources, so pick first arbitrarily. - DEPS = $$resolve_depends(USES, QMAKE_DEPENDS_, _CC) - for (DEP, DEPS) { - $${1}.libs -= $$eval(QMAKE_LIBS_$${DEP}) - $${1}.includedir -= $$eval(QMAKE_INCDIR_$${DEP}) - $${1}.defines -= $$eval(QMAKE_DEFINES_$${DEP}) - } - export($${1}.libs) - export($${1}.includedir) - export($${1}.defines) - - return(true) -} - -defineTest(qtConfTest_getPkgConfigVariable) { - pkg_config = $$qtConfPkgConfig($$eval($${1}.host)) - isEmpty(pkg_config): \ - return(false) - args = $$qtConfPrepareArgs($$eval($${1}.pkg-config-args)) - - !qtConfPkgConfigPackageExists($$pkg_config, $$args): \ - return(false) - - variable = $$eval($${1}.pkg-config-variable) - qtRunLoggedCommand("$$pkg_config --variable=$$variable $$args", $${1}.value)|return(false) - export($${1}.value) - $${1}.cache += value - export($${1}.cache) - return(true) -} - -defineReplace(qtConfLibraryArgs) { - NAME = $$upper($$replace($${1}.library, -, _)) - qmake_args = "QMAKE_LIBS_$${NAME} = $$val_escape($${1}.libs)" - for (b, $${1}.builds._KEYS_): \ - qmake_args += "QMAKE_LIBS_$${NAME}_$$upper($$b) = $$val_escape($${1}.builds.$${b})" - includedir = $$eval($${1}.includedir) - !isEmpty(includedir): \ - qmake_args += "QMAKE_INCDIR_$${NAME} = $$val_escape(includedir)" - defines = $$eval($${1}.defines) - !isEmpty(defines): \ - qmake_args += "QMAKE_DEFINES_$${NAME} = $$val_escape(defines)" - depends = $$eval($${2}.dependencies) - !isEmpty(depends) { - dep_uses = - for (use, depends): \ - dep_uses += $$section(use, :, 1, 1) - qmake_args += \ - "QMAKE_DEPENDS_$${NAME}_CC = $$upper($$replace(dep_uses, -, _))" \ - "QMAKE_DEPENDS_$${NAME}_LD = $$upper($$replace(dep_uses, -, _))" - } - return($$qmake_args) -} - -defineReplace(qtConfAllLibraryArgs) { - isEmpty(1): return() - dep_uses = - for (use, 1): \ - dep_uses += $$section(use, :, 1, 1) - dep_args = - seen = - for(ever) { - isEmpty(1): break() - use = $$take_last(1) - contains(seen, $$use): next() - seen += $$use - use_cfg = $$section(use, :, 0, 0) - !isEmpty(use_cfg) { - use_lib = $$section(use, :, 1, 1) - lpfx = $${use_cfg}.libraries.$$use_lib - dep_args += $$qtConfLibraryArgs($${lpfx}.sources.$$eval($${lpfx}.source), $$lpfx) - 1 += $$eval($${lpfx}.dependencies) - } - } - return("QMAKE_USE += $$dep_uses" $$dep_args) -} - -defineTest(qtConfExportLibrary) { - lpfx = $${currentConfig}.libraries.$$1 - alias = $$eval($${lpfx}.alias) - $${currentConfig}.found.$$alias = $$1 - export($${currentConfig}.found.$$alias) - name = $$eval($${lpfx}.export) - isEmpty(name): return() - spfx = $${lpfx}.sources.$$eval($${lpfx}.source) - !$$qtConfEvaluate($$eval($${spfx}.export)): return() - - output = privatePro - NAME = $$upper($$name) - # LIBS is emitted even if empty, as this allows the library to be "seen". - libs = $$eval($${spfx}.libs) - qtConfOutputVar(assign, $$output, QMAKE_LIBS_$$NAME, $$libs) - for (b, $${spfx}.builds._KEYS_) { - blibs = $$eval($${spfx}.builds.$${b}) - qtConfOutputVar(assign, $$output, QMAKE_LIBS_$${NAME}_$$upper($$b), $$blibs) - } - defines = $$eval($${spfx}.defines) - !isEmpty(defines): qtConfOutputVar(assign, $$output, QMAKE_DEFINES_$$NAME, $$defines) - includes = $$eval($${spfx}.exportincludedir) - !equals(includes, -) { - isEmpty(includes): includes = $$eval($${spfx}.includedir) - !isEmpty(includes): qtConfOutputVar(assign, $$output, QMAKE_INCDIR_$$NAME, $$includes) - } - uses = $$eval($${lpfx}.dependencies) - !isEmpty(uses) { - # FIXME: ideally, we would export transitive deps only for static - # libs, to not extend the link interface unduly. however, the system - # does currently not differentiate between public and private deps. - depends = - for (use, uses) { - use_cfg = $$section(use, :, 0, 0) - use_lib = $$section(use, :, 1, 1) - !isEmpty(use_cfg): \ - depends += $$upper($$eval($${use_cfg}.libraries.$${use_lib}.export)) - else: \ - depends += $$upper($$replace(use_lib, -, _)) - } - # we use suffixes instead of infixes, because $$resolve_depends() demands it. - qtConfOutputVar(assign, $$output, QMAKE_DEPENDS_$${NAME}_CC, $$depends) - qtConfOutputVar(assign, $$output, QMAKE_DEPENDS_$${NAME}_LD, $$depends) - } - !isEmpty($${currentConfig}.module): \ - qtConfExtendVar($$output, "QT.$${currentModule}_private.libraries", $$name) -} - -defineTest(qtConfHandleLibrary) { - lpfx = $${currentConfig}.libraries.$$1 - defined($${lpfx}.result, var): return() - - alias = $$eval($${lpfx}.alias) - !isEmpty($${currentConfig}.found.$$alias) { - # this happening indicates a logic error in the conditions - # of the feature(s) referring to this library. - # note that this does not look across module boundaries, as - # multiple modules may know the same libraries; de-duplication - # happens via the cache (obviously, this assumes identical - # definitions and logic). - error("A library exporting '$$alias' was already found.") - } - - qtConfEnsureTestTypeDeps("library") - !qtConfTestPrepare_compile($$lpfx) { - $${lpfx}.result = false - export($${lpfx}.result) - return() - } - $${lpfx}.dependencies = $$eval($${lpfx}.resolved_uses) - export($${lpfx}.dependencies) - - qtConfLoadResult($${lpfx}, $$1, "library") { - $$eval($${lpfx}.result): \ - qtConfExportLibrary($$1) - return() - } - - qtLogTestIntro($${lpfx}, "looking for library $${1}") - qtPersistLog() - - result = false - for (s, $${lpfx}.sources._KEYS_) { - spfx = $${lpfx}.sources.$${s} - - t = $$eval($${spfx}.type) - call = qtConfLibrary_$$t - !defined($$call, test): \ - error("Library $${1} source $${s} has unknown type '$$t'") - - qtLog("Trying source $$s (type $$t) of library $${1} ...") - - cond = $$eval($${spfx}.condition) - !$$qtConfEvaluate($$cond) { - qtLog(" => source failed condition '$$cond'.") - next() - } - - !$${call}($$spfx, $$lpfx) { - qtLog(" => source produced no result.") - next() - } - - $${lpfx}.source = $$s - export($${lpfx}.source) - - # if the library defines a test, use it to verify the source. - defined($${lpfx}.test, var)|defined($${lpfx}.test._KEYS_, var) { - $${lpfx}.resolved_uses = $$currentConfig:$$1 - $${lpfx}.host = $$eval($${spfx}.host) - !qtConfTest_compile($$lpfx) { - qtLog(" => source failed verification.") - next() - } - } - - qtLog(" => source accepted.") - - $${lpfx}.cache += source - for (v, $$list(libs includedir cflags version export)): \ - $${lpfx}.cache += sources.$${s}.$${v} - for (b, $${spfx}.builds._KEYS_): \ - $${lpfx}.cache += sources.$${s}.builds.$${b} - - # immediately output the library as well. - qtConfExportLibrary($$1) - - result = true - break() - } - - $${lpfx}.msgs = $$qtPersistedLog() - export($${lpfx}.msgs) - - qtLogTestResult($${lpfx}, $$result) - - $${lpfx}.result = $$result - export($${lpfx}.result) - qtConfSaveResult($${lpfx}, $$1) -} - -# This is a fake test type for the test dependency system. -defineTest(qtConfTest_library) { - error("The test type 'library' may not be instantiated.") -} - -defineTest(qtConfTestPrepare_compile) { - !isEmpty($${1}.use._KEYS_) { - uses = - for (k, $${1}.use._KEYS_) { - use = $$eval($${1}.use.$${k}.lib) - isEmpty(use): \ - error("'use' entry $$k in test $$1 lacks 'lib' field.") - !$$qtConfEvaluate($$eval($${1}.use.$${k}.condition)): \ - next() - uses += $$use - } - } else { - uses = $$split($${1}.use) - } - for (u, uses) { - libConfig = - exports = $$eval($${currentConfig}.exports.$$u) - !isEmpty(exports) { - # using a local library by exported name. - ru = $$eval($${currentConfig}.found.$$u) - !isEmpty(ru) { - # if it was already found, all is good. - u = $$ru - } else: count(exports, 1) { - # otherwise, if there is only one option, ensure it's resolved. - u = $$exports - qtConfHandleLibrary($$u) - } else { - # otherwise, verify that all options were resolved. - for (x, exports) { - isEmpty($${currentConfig}.libraries.$${x}.result) { - # the higher-level logic is in the features, which we cannot - # infer from here. so the only option is failing. - error("Test $$1 refers to yet unresolved library export '$$u'") - } - } - return(false) - } - libConfig = $$currentConfig - } else: contains($${currentConfig}.libraries._KEYS_, $$u) { - # using a local library by real name. this should be the exception. - qtConfHandleLibrary($$u) - libConfig = $$currentConfig - } else { - for (d, QMAKE_LIBRARY_DEPS) { - exports = $$eval($${d}.exports.$$u) - !isEmpty(exports) { - # using a foreign library by exported name. - # foreign libraries may be external (if they are from a different - # repository and the build is modular), and using these by real - # name is impossible. so for consistency, uses by real name are - # limited to local libraries. - ru = $$eval($${d}.found.$$u) - !isEmpty(ru) { - u = $$ru - libConfig = $$d - break() - } - for (x, exports) { - isEmpty($${d}.libraries.$${x}.result): \ - error("Test $$1 refers to unresolved library export '$$u' in '$$d'") - } - return(false) - } - } - } - isEmpty(libConfig) { - nu = $$upper($$replace(u, -, _)) - !defined(QMAKE_LIBS_$$nu, var): \ - error("Test $$1 tries to use undeclared library '$$u'") - # using an external library by exported name. - $${1}.resolved_uses += :$$u - } else { - lpfx = $${libConfig}.libraries.$${u} - !equals($${lpfx}.result, true): \ - return(false) - $${1}.resolved_uses += $$libConfig:$$u - } - } - export($${1}.resolved_uses) - return(true) -} - -defineTest(qtConfPrepareCompileTestSource) { - test_dir = $$2 - - tests = $$qtConfGetTestSourceList($$1) - - test_lang = "c++" - for (test, tests): \ - test_lang += $$eval($${test}.test.lang) - test_lang = $$last(test_lang) # Last non-empty, that is. - - equals(test_lang, "c++"): suffix = "cpp" - else: equals(test_lang, "c"): suffix = "c" - else: equals(test_lang, "objc"): suffix = "m" - else: equals(test_lang, "objc++"): suffix = "mm" - else: error("Unknown language '$$test_lang' in compile test $$1") - - # Create source code - contents = "/* Generated by configure */" - # Custom code before includes - for (test, tests): \ - for (ent, $$qtConfScalarOrList($${test}.test.head)): \ - contents += $$ent - # Includes - for (test, tests) { - hdrs = $$qtConfGetTestIncludes($${test}.test.include) - isEmpty(hdrs): \ - hdrs = $$qtConfGetTestIncludes($${test}.headers) - for (ent, hdrs): \ - contents += "$${LITERAL_HASH}include <$$ent>" - } - # Custom code after includes - for (test, tests): \ - for (ent, $$qtConfScalarOrList($${test}.test.tail)): \ - contents += $$ent - # And finally the custom code inside main() - contents += \ - "int main(int argc, char **argv)" \ - "{" \ - " (void)argc; (void)argv;" \ - " /* BEGIN TEST: */" - for (test, tests): \ - for (ent, $$qtConfScalarOrList($${test}.test.main)): \ - contents += " $$ent" - contents += \ - " /* END TEST */" \ - " return 0;" \ - "}" - write_file($$test_dir/main.$$suffix, contents)|error() - - for (test, tests) { - for (file, $$qtConfScalarOrList($${test}.test.files._KEYS_)): \ - write_file($$test_dir/$$file, $$qtConfScalarOrList($${test}.test.files.$${file}))|error() - } - - # Create stub .pro file - contents = "SOURCES = main.$$suffix" - # Custom project code - pwd = $$val_escape($${currentConfig}.dir) - for (test, tests): \ - for (ent, $$qtConfScalarOrList($${test}.test.qmake)): \ - contents += $$replace(ent, "@PWD@", $$pwd) - write_file($$test_dir/$$basename(test_dir).pro, contents)|error() -} - -defineTest(qtConfTest_compile) { - test = $$eval($${1}.test) - host = $$eval($${1}.host) - isEmpty(host): host = false - - test_base_out_dir = $$OUT_PWD/$$basename(QMAKE_CONFIG_TESTS_DIR) - isEmpty(test) { - test_dir = $$test_base_out_dir/$$section(1, ".", -1) - test_out_dir = $$test_dir - qtConfPrepareCompileTestSource($$1, $$test_dir) - } else { - test_dir = $$QMAKE_CONFIG_TESTS_DIR/$$test - test_out_dir = $$test_base_out_dir/$$test - !isEmpty($${1}.pro): \ - test_dir = $$test_dir/$$eval($${1}.pro) - } - test_cmd_base = "$$QMAKE_CD $$system_quote($$system_path($$test_out_dir)) &&" - - qmake_args = $$qtConfPkgConfigEnv()$$system_quote($$system_path($$QMAKE_QMAKE)) - !isEmpty(QMAKE_QTCONF): \ - qmake_args += -qtconf $$system_quote($$QMAKE_QTCONF) - - # Disable qmake features which are typically counterproductive for tests - qmake_args += "\"CONFIG -= qt debug_and_release app_bundle lib_bundle\"" - - # allow tests to behave differently depending on the type of library - # being built (shared/static). e.g. see config.tests/unix/icu - shared: \ - qmake_configs = "shared" - else: \ - qmake_configs = "static" - - use_bfd_linker: \ - qmake_configs += "use_bfd_linker" - use_gold_linker: \ - qmake_configs += "use_gold_linker" - use_lld_linker: \ - qmake_configs += "use_lld_linker" - - # disable warnings from the builds, since they're just noise at this point. - qmake_configs += "warn_off" - - # add console to the CONFIG variable when running the tests, so that they - # can work with a regular main() entry point on Windows. - qmake_configs += "console" - - # for platforms with multiple architectures (macOS, iOS, tvOS, watchOS), - # make sure tests are only built for a single architecture - qmake_configs += "single_arch" - - qmake_args += "\"CONFIG += $$qmake_configs\"" - - !$$host|!cross_compile { - # add compiler flags, these are set for the target and should not be applied to host tests - !isEmpty(EXTRA_DEFINES): \ - qmake_args += $$system_quote(DEFINES += $$val_escape(EXTRA_DEFINES)) - !isEmpty(EXTRA_LIBDIR): \ - qmake_args += $$system_quote(QMAKE_LIBDIR += $$val_escape(EXTRA_LIBDIR)) - !isEmpty(EXTRA_FRAMEWORKPATH): \ - qmake_args += $$system_quote(QMAKE_FRAMEWORKPATH += $$val_escape(EXTRA_FRAMEWORKPATH)) - !isEmpty(EXTRA_INCLUDEPATH): \ - qmake_args += $$system_quote(INCLUDEPATH += $$val_escape(EXTRA_INCLUDEPATH)) - qmake_args += $$EXTRA_QMAKE_ARGS - } - - # make sure to make this the last override (because of -early) - cross_compile { - # must be done before loading default_pre.prf. - qmake_args += -early "\"CONFIG += cross_compile\"" - } - - # Clean up after previous run - exists($$test_out_dir/Makefile): \ - QMAKE_MAKE = "$$QMAKE_MAKE clean && $$QMAKE_MAKE" - - mkpath($$test_out_dir)|error() - cont = "CONFIG += QTDIR_build" - write_file($$test_base_out_dir/.qmake.cache, cont)|error() - - $${1}.literal_args += $$qtConfAllLibraryArgs($$eval($${1}.resolved_uses)) - - # add possible command line args - qmake_args += \ - $$qtConfPrepareArgs($$eval($${1}.args)) \ - $$qtSystemQuote($$eval($${1}.literal_args)) - - qtRunLoggedCommand("$$test_cmd_base $$qmake_args $$system_quote($$test_dir)") { - qtRunLoggedCommand("$$test_cmd_base $$QMAKE_MAKE"): \ - return(true) - } - - return(false) -} - -defineTest(qtConfTest_files) { - for(i, $${1}.files._KEYS_) { - f = $$eval($${1}.files.$${i}) - qtLog("Searching for file $${f}.") - contains(f, ".*\\.h") { - file = $$qtConfFindInPathList($$f, $$EXTRA_INCLUDEPATH $$QMAKE_DEFAULT_INCDIRS) - } else: contains(f, ".*\\.(lib|so|a)") { - file = $$qtConfFindInPathList($$f, $$EXTRA_LIBDIR $$QMAKE_DEFAULT_LIBDIRS) - } else { - # assume we're looking for an executable - file = $$qtConfFindInPath($$f, $$EXTRA_PATH) - } - isEmpty(file) { - qtLog(" Not found."); - return(false) - } - qtLog(" Found at $${file}.") - } - return(true) -} - -defineTest(logn) { - log("$${1}$$escape_expand(\\n)") -} - -defineTest(qtLogTestIntro) { - label = $$eval($${1}.label) - isEmpty(label): return() - - isEmpty(3): log("Checking for $${label}... ") - $$QMAKE_CONFIG_VERBOSE: log("$$escape_expand(\\n)") - write_file($$QMAKE_CONFIG_LOG, 2, append) -} - -defineTest(qtLogTestResult) { - isEmpty($${1}.label): return() - - !isEmpty($${1}.log) { - field = $$eval($${1}.log) - log_msg = $$eval($${1}.$$field) - msg = "test $$1 gave result $$log_msg" - } else: $${2} { - log_msg = yes - msg = "test $$1 succeeded" - } else { - log_msg = no - msg = "test $$1 FAILED" - } - $$QMAKE_CONFIG_VERBOSE: log_msg = $$msg - isEmpty(3): logn("$$log_msg") - write_file($$QMAKE_CONFIG_LOG, msg, append) -} - -defineTest(qtConfSaveResult) { - equals($${1}.cache, -): \ - return() - keys = result msgs $$eval($${1}.cache) - cont = "cache.$${2}._KEYS_ = $$keys" - cache.$${2}._KEYS_ = $$keys - export(cache.$${2}._KEYS_) - for (k, keys) { - cont += "cache.$${2}.$${k} = $$val_escape($${1}.$${k})" - cache.$${2}.$${k} = $$eval($${1}.$${k}) - export(cache.$${2}.$${k}) - } - write_file($$QMAKE_CONFIG_CACHE, cont, append)|error() -} - -defineTest(qtConfLoadResult) { - equals(QMAKE_CONFIG_CACHE_USE, none): \ - return(false) - isEmpty(cache.$${2}._KEYS_): \ - return(false) - equals(QMAKE_CONFIG_CACHE_USE, positive):!$$eval(cache.$${2}.result): \ - return(false) - for (k, cache.$${2}._KEYS_) { - $${1}.$${k} = $$eval(cache.$${2}.$${k}) - export($${1}.$${k}) - } - # we could print the cached result, but that's basically just noise - - # the explicitly generated summary is supposed to contain all relevant - # information. - qtLogTestIntro($$1, "loaded result for $$3 $$1", false) - qtLog($$eval($${1}.msgs)) - qtLogTestResult($$1, $$eval($${1}.result), false) - return(true) -} - -defineTest(qtConfIsBoolean) { - equals(1, "true")|equals(1, "false"): \ - return(true) - return(false) -} - -defineTest(qtConfSetupTestTypeDeps) { - for (tt, $${currentConfig}.testTypeDependencies._KEYS_) { - !defined(qtConfTest_$${tt}, test): \ - error("Declaring dependency for undefined test type '$$tt'.") - for (f, $${currentConfig}.testTypeDependencies.$${tt}._KEYS_) { - feature = $$eval($${currentConfig}.testTypeDependencies.$${tt}.$${f}) - isEmpty($${currentConfig}.features.$${feature}._KEYS_): \ - error("Test type '$$tt' depends on undefined feature '$$feature'.") - } - } - # Test type aliasing means that one test type's callback is called by - # another test type's callback. Put differently, one callback forwards - # the call to another one. The former representation is more natural - # (and concise) to write, while the latter is more efficient to process. - # Hence, this function inverts the mapping. - for (tt, $${currentConfig}.testTypeAliases._KEYS_) { - !defined(qtConfTest_$${tt}, test): \ - error("Aliasing undefined test type '$$tt'.") - for (tta, $${currentConfig}.testTypeAliases.$${tt}._KEYS_) { - type = $$eval($${currentConfig}.testTypeAliases.$${tt}.$${tta}) - !defined(qtConfTest_$${type}, test): \ - error("Aliasing '$$tt' to undefined test type '$$type'.") - $${currentConfig}.testTypeForwards.$${type} += $$tt - export($${currentConfig}.testTypeForwards.$${type}) - } - } -} - -defineTest(qtConfEnsureTestTypeDepsOne) { - depsn = $${currentConfig}.testTypeDependencies.$${1}._KEYS_ - !isEmpty($$depsn) { - for (dep, $$depsn) { - feature = $$eval($${currentConfig}.testTypeDependencies.$${1}.$${dep}) - !qtConfCheckFeature($$feature): \ - error("Test type '$$1' depends on non-emitted feature $${feature}.") - } - $$depsn = - export($$depsn) - } - fwdsn = $${currentConfig}.testTypeForwards.$${1} - !isEmpty($$fwdsn) { - for (fwd, $$fwdsn): \ - qtConfEnsureTestTypeDepsOne($$fwd) - $$fwdsn = - export($$fwdsn) - } -} - -defineTest(qtConfEnsureTestTypeDeps) { - qtConfEnsureTestTypeDepsOne($$1) - currentConfig = config.builtins - qtConfEnsureTestTypeDepsOne($$1) -} - -defineTest(qtRunSingleTest) { - tpfx = $${currentConfig}.tests.$${1} - defined($${tpfx}.result, var): \ - return() - - type = $$eval($${tpfx}.type) - call = "qtConfTest_$$type" - !defined($$call, test): \ - error("Configure test $${1} refers to nonexistent type $$type") - - qtConfEnsureTestTypeDeps($$type) - - preCall = "qtConfTestPrepare_$$type" - defined($$preCall, test):!$${preCall}($${tpfx}) { - $${tpfx}.result = false - export($${tpfx}.result) - # don't cache the result; the pre-deps have their own caches. - return() - } - - # note: we do this only after resolving the dependencies and the - # preparation (which may resolve libraries), so that caching does - # not alter the execution order (and thus the output). - qtConfLoadResult($${tpfx}, $$1, "config test"): \ - return() - - qtLogTestIntro($${tpfx}, "executing config test $${1}") - qtPersistLog() - - result = false - $${call}($${tpfx}): result = true - - $${tpfx}.msgs = $$qtPersistedLog() - export($${tpfx}.msgs) - - qtLogTestResult($${tpfx}, $$result) - - $${tpfx}.result = $$result - export($${tpfx}.result) - qtConfSaveResult($${tpfx}, $$1) -} - -defineTest(qtConfHaveModule) { - module = $$replace(1, -, _) - !isEmpty(QT.$${module}.skip):$$eval(QT.$${module}.skip): \ - return(false) - !isEmpty(QT.$${module}.name): \ - return(true) - return(false) -} - -defineReplace(qtConfEvaluate) { - isEmpty(1): return(true) - - 1 ~= s/$$escape_expand(\\t)/ /g - 1 ~= s/$$escape_expand(\\r)//g - 1 ~= s/$$escape_expand(\\n) */ /g - expr = $${1} - expr ~= s/&&/ && /g - expr ~= s/\\|\\|/ || /g - expr ~= s/!/ ! /g - expr ~= s/\\(/ ( /g - expr ~= s/\\)/ ) /g - expr ~= s/ *== */==/g - expr ~= s/ *! = */!=/g - expr_list = $$eval($$list($$expr)) - return($$qtConfEvaluateSubExpression($${1}, $$expr_list, 0)) -} - -defineReplace(qtConfEvaluateSingleExpression) { - e = $${2} - - equals(e, true) { - result = true - } else: equals(e, false) { - result = false - } else: contains(e, "^[0-9]+$") { - # numbers - result = $$e - } else: contains(e, "^'.*'$") { - # quoted literals - result = $$replace(e, "^'(.*)'$", "\\1") - } else: contains(e, "^tests\\..*") { - !qt_conf_tests_allowed: \ - error("Expression '$${1}' refers to a test, which is not allowed at this stage of configuring.") - test = $$section(e, ".", 1, 1) - var = $$section(e, ".", 2, -1) - isEmpty(var): \ - var = result - !contains($${currentConfig}.tests._KEYS_, $$test): \ - error("Unknown test object $${test} in expression '$${1}'.") - qtRunSingleTest($$test) - result = $$eval($${currentConfig}.tests.$${test}.$${var}) - } else: contains(e, "^libs\\..*") { - !qt_conf_tests_allowed: \ - error("Expression '$${1}' refers to a library, which is not allowed at this stage of configuring.") - lib = $$section(e, ".", 1, 1) - var = $$section(e, ".", 2, -1) - isEmpty(var): \ - var = result - !contains($${currentConfig}.libraries._KEYS_, $$lib): \ - error("Unknown library object $${lib} in expression '$${1}'.") - qtConfHandleLibrary($$lib) - !defined($${currentConfig}.libraries.$${lib}.$${var}, var): \ - var = sources.$$eval($${currentConfig}.libraries.$${lib}.source).$$var - result = $$eval($${currentConfig}.libraries.$${lib}.$${var}) - } else: contains(e, "^features\\..*") { - feature = $$section(e, ".", 1, 1) - var = $$section(e, ".", 2, -1) - isEmpty(var): \ - var = available - !contains($${currentConfig}.features._KEYS_, $$feature) { - # this is basically a copy of what qtConfig() in qt_build_config.prf - # does, but we produce a nicer error message. - for (module, QMAKE_CONFIG_DEPS) { - contains(QT.$${module}.enabled_features, $$feature): \ - result = true - else: contains(QT.$${module}.disabled_features, $$feature): \ - result = false - else: \ - next() - !equals(var, available): \ - error("Expression '$$1' is accessing field '$$var' of non-local feature $${feature}.") - return($$result) - } - error("Unknown feature object $${feature} in expression '$${1}'.") - } - !qtConfCheckFeature($$feature): \ - error("Expression '$$1' is accessing non-emitted feature $${feature}.") - result = $$eval($${currentConfig}.features.$${feature}.$${var}) - } else: contains(e, "^config\\..*") { - var = $$replace(e, "^config\\.", "") - result = false - contains(CONFIG, $$var): result = true - } else: contains(e, "^module\\..*") { - var = $$replace(e, "^module\\.", "") - result = false - qtConfHaveModule($$var): result = true - } else: contains(e, "^arch\\..*") { - var = $$replace(e, "^arch\\.", "") - result = false - isEmpty(QT_ARCH): \ - qtConfCheckFeature(architecture) - contains(QT_ARCH, $$var): result = true - } else: contains(e, "^subarch\\..*") { - var = $$replace(e, "^subarch\\.", "") - result = false - isEmpty(QT_ARCH): \ - qtConfCheckFeature(architecture) - contains(QT_CPU_FEATURES.$$QT_ARCH, $$var): result = true - } else: contains(e, "^input\\..*") { - result = $$eval(config.$$e) - } else: contains(e, "^var\\..*") { - var = $$replace(e, "^var\\.", "") - result = $$eval($$var) - } else: contains(e, "^call\\..*") { - call = $$replace(e, "^call\\.", "qtConfFunc_") - !defined($$call, replace): \ - error("Call $$call referenced in expression '$${1}' does not exist") - eval(result = \$\$"$$call"()) - } else { - error("Unrecognized token $$e in expression '$${1}'") - } - return($$result) -} - -defineReplace(qtConfEvaluateSubExpression) { - expr_list = $${2} - result = true - negate = false - runSubExpression = false - nesting_level = 0 - for (n, $${3}..$$num_add($$size(expr_list), -1)) { - e = $$member(expr_list, $$n) - $$runSubExpression { - runSubExpression = false - result = $$qtConfEvaluateSubExpression($${1}, $$expr_list, $$n) - } else: isEqual(e, "(") { - isEqual(nesting_level, 0): runSubExpression = true - nesting_level = $$num_add($$nesting_level, 1) - next() - } else: isEqual(e, ")") { - nesting_level = $$num_add($$nesting_level, -1) - lessThan(nesting_level, 0): break() - next() - } else: greaterThan(nesting_level, 0) { - next() - } else: isEqual(e, "!") { - negate = true - next() - } else: isEqual(e, "&&") { - !qtConfIsBoolean($$result): \ - error("Left hand side of && is non-boolean value '$$result' in expression '$${1}'") - !$$result: return(false) - } else: isEqual(e, "||") { - !qtConfIsBoolean($$result): \ - error("Left hand side of || is non-boolean value '$$result' in expression '$${1}'") - $$result: return(true) - } else { - contains(e, ".*==.*") { - lhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, "==.*", "")) - rhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, ".*==", "")) - result = false - equals(lhs, $$rhs): result = true - } else: contains(e, ".*!=.*") { - lhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, "!=.*", "")) - rhs = $$qtConfEvaluateSingleExpression($${1}, $$replace(e, ".*!=", "")) - result = false - !equals(lhs, $$rhs): result = true - } else { - result = $$qtConfEvaluateSingleExpression($${1}, $$e) - } - } - $$negate { - !qtConfIsBoolean($$result): \ - error("Attempting to negate a non-boolean value '$$result' in expression '$${1}'") - $$result: \ - result = false - else: \ - result = true - negate = false - } - } - return($$result) -} - -defineReplace(qtIsFeatureEnabled) { - enable = $$eval($${currentConfig}.features.$${1}.enable) - !isEmpty(enable) { - $$qtConfEvaluate($$enable): \ - return(true) - } else { - equals(config.input.$${1}, "yes"): \ - return(true) - } - - return(false) -} - -defineReplace(qtIsFeatureDisabled) { - disable = $$eval($${currentConfig}.features.$${1}.disable) - !isEmpty(disable) { - $$qtConfEvaluate($$disable): \ - return(true) - } else { - equals(config.input.$${1}, "no"): \ - return(true) - } - - return(false) -} - -defineReplace(qtConfCheckSingleCondition) { - result = $$qtConfEvaluate($$2) - - !qtConfIsBoolean($$result): \ - error("Evaluation of condition '$$2' yielded non-boolean value '$$result' in feature '$${1}'.") - - !$$result { - $${3} { - qtConfAddError("Feature '$${1}' was enabled, but the pre-condition '$$2' failed.", log) - $$result = true - } - } - return($$result) -} - -defineTest(qtConfCheckFeature) { - fpfx = $${currentConfig}.features.$${1} - - available = $$eval($${fpfx}.available) - !isEmpty(available): return(true) - - # skip features that will not get emitted anyway - emitIf = $$qtConfEvaluate($$eval($${fpfx}.emitIf)) - enabled = $$qtIsFeatureEnabled($$1) - disabled = $$qtIsFeatureDisabled($$1) - - !$$emitIf { - $$enabled|$$disabled: \ - qtConfAddWarning("Feature $${1} is insignificant in this configuration, ignoring related command line option(s).") - return(false) - } - - $$disabled { - result = false - } else: !$$enabled:!$$qtConfEvaluate($$eval($${fpfx}.autoDetect)) { - # feature not auto-detected and not explicitly enabled - result = false - } else { - result = true - for (condition, $$qtConfScalarOrList($${fpfx}.condition)) { - result = $$qtConfCheckSingleCondition($$1, $$condition, $$enabled) - !$$result: break() - } - } - $${fpfx}.available = $$result - export($${fpfx}.available) - - for (i, $${fpfx}.output._KEYS_): \ - qtConfProcessOneOutput($${1}, $$i) - - return(true) -} - -defineTest(qtConfCheckModuleCondition) { - QT.$${currentModule}.skip = false - !$$qtConfEvaluate($$eval($${currentConfig}.condition)): \ - QT.$${currentModule}.skip = true - export(QT.$${currentModule}.skip) - - # ensure qtConfHaveModule() works - QT.$${currentModule}.name = - - export(QT.$${currentModule}.name) -} - - -defineTest(qtConfProcessFeatures) { - for (feature, $${currentConfig}.features._KEYS_): \ - qtConfCheckFeature($$feature) -} - -# -# reporting -# - -defineReplace(qtConfPadCols) { - pad = $$num_add($$str_size($$2), -$$str_size($${1})) - lessThan(pad, 0): pad = 0 - return("$$1 $$str_member($$2, 0, $$pad) $$3") -} - -defineTest(qtConfReportPadded) { - qtConfAddReport($$qtConfPadCols($$1, "........................................", $$2)) -} - -defineReplace(qtConfCollectFeatures) { - l = - for (feature, $$list($${1})) { - $$eval($${currentConfig}.features.$${feature}.available): \ - l += $$eval($${currentConfig}.features.$${feature}.label) - } - - isEmpty(l): return("<none>") - return($$join(l, ' ')) -} - -defineTest(qtConfReport_featureList) { - qtConfReportPadded($${1}, $$qtConfCollectFeatures($${2})) -} - -defineReplace(qtConfFindFirstAvailableFeature) { - for (feature, $$list($${1})) { - isEmpty($${currentConfig}.features.$${feature}._KEYS_): \ - error("Asking for a report on undefined feature $${2}.") - $$eval($${currentConfig}.features.$${feature}.available): \ - return($$eval($${currentConfig}.features.$${feature}.label)) - } - - return("<none>") -} - -defineTest(qtConfReport_firstAvailableFeature) { - qtConfReportPadded($${1}, $$qtConfFindFirstAvailableFeature($${2})) -} - -defineTest(qtConfReport_feature) { - !contains($${currentConfig}.features._KEYS_, $$2): \ - error("Asking for a report on undefined feature $${2}.") - - # hide report for not emitted features - isEmpty($${currentConfig}.features.$${2}.available): \ - return() - - $$eval($${currentConfig}.features.$${2}.available) { - result = "yes" - !isEmpty(3): result = "$${3}" - } else { - result = "no" - !isEmpty(4): result = "$${4}" - } - - text = $$eval($${currentConfig}.features.$${2}.label) - - qtConfReportPadded($${1}$$text, $$result) -} - -defineTest(qtConfReport_note) { - qtConfAddNote($${1}) -} - -defineTest(qtConfReport_warning) { - qtConfAddWarning($${1}) -} - -defineTest(qtConfReport_error) { - qtConfAddError($${1}, log) -} - -defineTest(qtConfReport_fatal) { - qtConfFatalError($${1}) -} - -defineTest(qtConfCreateReportRecurse) { - equals(2, false) { - indent = "" - recurse = false - } else { - indent = $${2} - recurse = true - } - - keys = $$eval($${1}._KEYS_) - for (n, keys) { - entry = $${1}.$$n - subKeys = $$eval($${entry}._KEYS_) - contains(subKeys, condition) { - r = true - for (condition, $$qtConfScalarOrList($${entry}.condition)) { - r = $$qtConfEvaluate($$condition) - !$$r: break() - } - !qtConfIsBoolean($$r): \ - error("Evaluation of condition '$$condition' in report entry $${entry} yielded non-boolean value '$$r'.") - !$$r: next() - } - contains(subKeys, "section") { - !$$recurse: \ - error("Report type 'section' is not allowed in '$$1'.") - section = $$eval($${entry}.section) - qtConfAddReport("$$indent$$section:") - qtConfCreateReportRecurse("$${entry}.entries", "$$indent ") - } else: !isEmpty($${entry}) { - feature = $$eval($${entry}) - qtConfReport_feature($$indent, $$feature) - } else { - text = $$eval($${entry}.message) - isEmpty($${entry}.type): \ - error("Report entry $${entry} doesn't define a type.") - r = "qtConfReport_$$eval($${entry}.type)" - !defined($$r, test): \ - error("Undefined report type $$eval($${entry}.type) used in report entry $${entry}.") - args = $$eval($${entry}.args) - $${r}($$indent$${text}, $$args) - } - } -} - -defineTest(qtConfProcessEarlyChecks) { - qtConfCreateReportRecurse($${currentConfig}.earlyReport, false) -} - -defineTest(qtConfCreateReport) { - qtConfCreateReportRecurse($${currentConfig}.report, false) -} - -defineTest(qtConfCreateSummary) { - qtConfCreateReportRecurse($${currentConfig}.summary, "") -} - -defineTest(qtConfPrintReport) { - blocks = \ - "$$join(QT_CONFIGURE_REPORT, $$escape_expand(\\n))" \ - "$$join(QT_CONFIGURE_NOTES, $$escape_expand(\\n\\n))" \ - "$$join(QT_CONFIGURE_WARNINGS, $$escape_expand(\\n\\n))" - - !isEmpty(QT_CONFIGURE_ERRORS) { - blocks += "$$join(QT_CONFIGURE_ERRORS, $$escape_expand(\\n\\n))" - mention_config_log:!$$QMAKE_CONFIG_VERBOSE: \ - blocks += "Check config.log for details." - } - blocks = "$$join(blocks, $$escape_expand(\\n\\n))" - logn($$blocks) - !isEmpty(QT_CONFIGURE_ERRORS):!equals(config.input.continue, yes): \ - error() - write_file($$OUT_PWD/config.summary, blocks)|error() -} - -defineTest(qtConfCheckErrors) { - !isEmpty(QT_CONFIGURE_ERRORS):!equals(config.input.continue, yes): \ - qtConfPrintReport() -} - -# -# output generation -# - -defineTest(qtConfOutput_libraryPaths) { - qtLog("Global lib dirs: [$$val_escape(EXTRA_LIBDIR)] [$$val_escape(QMAKE_DEFAULT_LIBDIRS)]") - qtLog("Global inc dirs: [$$val_escape(EXTRA_INCLUDEPATH)] [$$val_escape(QMAKE_DEFAULT_INCDIRS)]") -} - -# qtConfOutputVar(modifier, output, name, value) -defineTest(qtConfOutputVar) { - modifier = $$1 - output = $$2 - name = $$3 - value = $$val_escape(4) - - defined($${currentConfig}.output.$${output}.assign.$${name}, var): \ - error("Trying to overwrite assigned variable '$$name' in '$$output' using modifier '$$modifier'.") - - equals(modifier, assign) { - !isEmpty($${currentConfig}.output.$${output}.append.$${name})|!isEmpty($${currentConfig}.output.$${output}.remove.$${name}): \ - error("Trying to assign variable '$$name' in '$$output', which has already appended or removed parts.") - $${currentConfig}.output.$${output}.assign.$${name} = $$value - } else: equals(modifier, append) { - contains($${currentConfig}.output.$${output}.remove.$${name}, $$value): \ - error("Trying to append removed '$$value' to variable '$$name' in '$$output'.") - $${currentConfig}.output.$${output}.append.$${name} += $$value - } else: equals(modifier, remove) { - contains($${currentConfig}.output.$${output}.append.$${name}, $$value): \ - error("Trying to remove appended '$$value' to variable '$$name' in '$$output'.") - $${currentConfig}.output.$${output}.remove.$${name} += $$value - } else { - error("Invalid modifier '$$modifier' passed to qtConfOutputVar.") - } - $${currentConfig}.output.$${output}.$${modifier}._KEYS_ *= $${name} - export($${currentConfig}.output.$${output}.$${modifier}.$${name}) - export($${currentConfig}.output.$${output}.$${modifier}._KEYS_) -} - -# qtConfExtendVar(output, name, value) -defineTest(qtConfExtendVar) { - output = $$1 - name = $$2 - value = $$val_escape(3) - - !defined($${currentConfig}.output.$${output}.assign.$${name}, var): \ - error("Trying to extend undefined variable '$$name' in '$$output'.") - - $${currentConfig}.output.$${output}.assign.$${name} += $$value - export($${currentConfig}.output.$${output}.assign.$${name}) -} - -defineTest(qtConfOutputVarHelper) { - !isEmpty($${2}.public):$$eval($${2}.public) { - output = "publicPro" - } else { - output = "privatePro" - } - - negative = $$eval($${2}.negative) - isEmpty(negative): negative = false - equals(3, $$negative): return() - - name = $$eval($${2}.name) - isEmpty(name): \ - error("Output type 'var$$title($$1)' used in feature '$$eval($${2}.feature)' without a 'name' entry.") - - value = $$qtConfEvaluate($$eval($${2}.value)) - !isEmpty($${2}.eval):$$qtConfEvaluate($$eval($${2}.eval)): \ - eval(value = $$value) - qtConfOutputVar($$1, $$output, $$name, $$value) - equals(output, "publicPro"):!isEmpty($${currentConfig}.module): \ - qtConfExtendVar($$output, "QT.$${currentModule}.exports", $$name) -} - -defineTest(qtConfOutput_varAssign) { - qtConfOutputVarHelper(assign, $$1, $$2) -} - -defineTest(qtConfOutput_varAppend) { - qtConfOutputVarHelper(append, $$1, $$2) -} - -defineTest(qtConfOutput_varRemove) { - qtConfOutputVarHelper(remove, $$1, $$2) -} - -defineTest(qtConfOutputConfigVar) { - pro = $$3 - var = $$4 - modular = $$5 - - negative = $$eval($${1}.negative) - isEmpty(negative): negative = false - equals(2, $$negative): return() - - val = $$eval($${1}.name) - isEmpty(val) { - val = $$eval($${1}.feature) - $$negative: val = no-$$val - } - - isEmpty($${currentConfig}.module)|!$$modular: \ - qtConfOutputVar(append, $$pro, $$var, $$val) - else: \ - qtConfExtendVar($$pro, "QT.$${currentModule}.$$var", $$val) -} - -defineTest(qtConfOutput_publicQtConfig) { - qtConfOutputConfigVar($$1, $$2, "publicPro", "QT_CONFIG", true) -} - -defineTest(qtConfOutput_publicConfig) { - !isEmpty($${currentConfig}.module): \ - error("Cannot use output type 'publicConfig' in module-local feature '$$eval($${1}.feature)'.") - qtConfOutputConfigVar($$1, $$2, "publicPro", "CONFIG", false) -} - -defineTest(qtConfOutput_privateConfig) { - qtConfOutputConfigVar($$1, $$2, "privatePro", "CONFIG", false) -} - -defineTest(qtConfOutputSetDefine) { - $${currentConfig}.output.$${1}.$${2} = $${3} - $${currentConfig}.output.$${1}._KEYS_ *= $${2} - export($${currentConfig}.output.$${1}.$${2}) - export($${currentConfig}.output.$${1}._KEYS_) -} - -defineTest(qtConfOutput_define) { - output = publicHeader - define = $$eval($${1}.name) - value = $$qtConfEvaluate($$eval($${1}.value)) - isEmpty(define): \ - error("Output type 'define' used in feature '$$eval($${1}.feature)' without a 'name' entry.") - - negative = $$eval($${1}.negative) - isEmpty(negative): negative = false - equals(2, $$negative): return() - - qtConfOutputSetDefine($$output, $$define, $$value) -} - -defineTest(qtConfOutput_feature) { - name = "$$eval($${1}.name)" - isEmpty(name): \ - name = $$eval($${1}.feature) - - $${2} { - isEmpty($${currentConfig}.module): \ - qtConfOutputVar(append, "publicPro", "QT_CONFIG", $$name) - else: \ - qtConfExtendVar("publicPro", "QT.$${currentModule}.QT_CONFIG", $$name) - } else { - f = $$upper($$replace(name, -, _)) - qtConfOutputSetDefine("publicHeader", "QT_NO_$$f") - } -} - -defineTest(qtConfSetModuleName) { - currentModule = $$eval($${currentConfig}.module) - isEmpty(currentModule): \ - currentModule = global - export(currentModule) -} - -defineTest(qtConfSetupModuleOutputs) { - qtConfOutputVar(assign, "publicPro", "QT.$${currentModule}.enabled_features", ) - qtConfOutputVar(assign, "publicPro", "QT.$${currentModule}.disabled_features", ) - qtConfOutputVar(assign, "privatePro", "QT.$${currentModule}_private.enabled_features", ) - qtConfOutputVar(assign, "privatePro", "QT.$${currentModule}_private.disabled_features", ) - !isEmpty($${currentConfig}.module) { - qtConfOutputVar(assign, "publicPro", "QT.$${currentModule}.QT_CONFIG", ) - qtConfOutputVar(assign, "publicPro", "QT.$${currentModule}.exports", ) - qtConfOutputVar(assign, "privatePro", "QT.$${currentModule}_private.libraries", ) - } -} - -defineTest(qtConfOutput_publicFeature) { - name = "$$eval($${1}.name)" - isEmpty(name): \ - name = $$eval($${1}.feature) - feature = $$replace(name, [-+.], _) - - $${2} { - qtConfExtendVar("publicPro", "QT.$${currentModule}.enabled_features", $$name) - QT.$${currentModule}.enabled_features += $$name - export(QT.$${currentModule}.enabled_features) - qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", 1) - } else { - qtConfExtendVar("publicPro", "QT.$${currentModule}.disabled_features", $$name) - QT.$${currentModule}.disabled_features += $$name - export(QT.$${currentModule}.disabled_features) - qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", -1) - } -} - -defineTest(qtConfOutput_privateFeature) { - name = "$$eval($${1}.name)" - isEmpty(name): \ - name = $$eval($${1}.feature) - feature = $$replace(name, [-+.], _) - - $${2} { - qtConfExtendVar("privatePro", "QT.$${currentModule}_private.enabled_features", $$name) - QT.$${currentModule}_private.enabled_features += $$name - export(QT.$${currentModule}_private.enabled_features) - qtConfOutputSetDefine("privateHeader", "QT_FEATURE_$$feature", 1) - } else { - qtConfExtendVar("privatePro", "QT.$${currentModule}_private.disabled_features", $$name) - QT.$${currentModule}_private.disabled_features += $$name - export(QT.$${currentModule}_private.disabled_features) - qtConfOutputSetDefine("privateHeader", "QT_FEATURE_$$feature", -1) - } -} - -defineTest(qtConfProcessOneOutput) { - feature = $${1} - fpfx = $${currentConfig}.features.$${feature} - opfx = $${fpfx}.output.$${2} - - call = $$eval($${opfx}.type) - isEmpty(call) { - # output is just a string, not an object - call = $$eval($$opfx) - } - !defined("qtConfOutput_$$call", test): \ - error("Undefined type '$$call' in output '$$2' of feature '$$feature'.") - - !$$qtConfEvaluate($$eval($${opfx}.condition)): \ - return() - - $${opfx}.feature = $$feature - qtConfOutput_$${call}($$opfx, $$eval($${fpfx}.available)) -} - -defineTest(qtConfProcessOutput) { - !contains($${currentConfig}._KEYS_, "features"): \ - return() - - basedir = $$shadowed($$eval($${currentConfig}.dir)) - module = $$eval($${currentConfig}.module) - - # write it to the output files - !defined($${currentConfig}.files._KEYS_, var) { - # set defaults that should work for most Qt modules - isEmpty(module): \ - error("Neither module nor files section specified in configuration file.") - - $${currentConfig}.files._KEYS_ = publicPro privatePro publicHeader privateHeader - $${currentConfig}.files.publicPro = qt$${module}-config.pri - $${currentConfig}.files.privatePro = qt$${module}-config.pri # sic! - $${currentConfig}.files.publicHeader = qt$${module}-config.h - $${currentConfig}.files.privateHeader = qt$${module}-config_p.h - } - - for (type, $${currentConfig}.files._KEYS_) { - contains(type, ".*Pro") { - for (k, $${currentConfig}.output.$${type}.assign._KEYS_): \ - $${currentConfig}.output.$$type += "$$k = $$eval($${currentConfig}.output.$${type}.assign.$$k)" - for (k, $${currentConfig}.output.$${type}.remove._KEYS_): \ - $${currentConfig}.output.$$type += "$$k -= $$eval($${currentConfig}.output.$${type}.remove.$$k)" - for (k, $${currentConfig}.output.$${type}.append._KEYS_): \ - $${currentConfig}.output.$$type += "$$k += $$eval($${currentConfig}.output.$${type}.append.$$k)" - } else: contains(type, ".*Header") { - for (define, $${currentConfig}.output.$${type}._KEYS_) { - value = $$eval($${currentConfig}.output.$${type}.$${define}) - $${currentConfig}.output.$$type += "$${LITERAL_HASH}define $$define $$value" - } - } - - content = $$eval($${currentConfig}.output.$${type}) - - !isEmpty(module): \ - call = qtConfOutputPostProcess_$${module}_$${type} - else: \ - call = qtConfOutputPostProcess_$${type} - defined($$call, replace): \ - eval(content = \$\$"$$call"(\$\$content)) - - file = $$eval($${currentConfig}.files.$${type}) - fileCont.$$file += $$content - fileCont._KEYS_ *= $$file - } - - for (file, fileCont._KEYS_): \ - write_file($$basedir/$$file, fileCont.$$file)|error() -} - -# -# tie it all together -# - -!isEmpty(_QMAKE_SUPER_CACHE_):!equals(OUT_PWD, $$dirname(_QMAKE_SUPER_CACHE_)) { - # sub-repo within a top-level build; no need to configure anything. - !isEmpty(QMAKE_EXTRA_ARGS) { - # sub-projects don't get the extra args passed down automatically, - # so we can use their presence to detect misguided attempts to - # configure the repositories separately. - # caveat: a plain qmake call is indistinguishable from a recursion - # (by design), so we cannot detect this case. - error("You cannot configure $$TARGET separately within a top-level build.") - } - return() -} - -config.$${TARGET}.dir = $$_PRO_FILE_PWD_ -cfgs = $$TARGET -!isEmpty(_QMAKE_SUPER_CACHE_) { - for (s, SUBDIRS) { - config.$${s}.dir = $$_PRO_FILE_PWD_/$${s} - cfgs += $$s - } -} -configsToProcess = -for (c, cfgs) { - s = $$eval(config.$${c}.dir) - exists($$s/configure.json): \ - configsToProcess += $$c -} -isEmpty(configsToProcess) { - !isEmpty(QMAKE_EXTRA_ARGS): \ - error("This module does not accept configure command line arguments.") - return() -} - -load(configure_base) - -QMAKE_POST_CONFIGURE = -config.builtins.dir = $$PWD/data -configsToProcess = builtins $$configsToProcess -allConfigs = -for(ever) { - isEmpty(configsToProcess): \ - break() - - thisConfig = $$take_first(configsToProcess) - currentConfig = config.$$thisConfig - thisDir = $$eval($${currentConfig}.dir) - jsonFile = $$thisDir/configure.json - priFile = $$thisDir/configure.pri - - # load configuration data - configure_data = $$cat($$jsonFile, blob) - !parseJson(configure_data, $$currentConfig): \ - error("Invalid or non-existent file $${jsonFile}.") - exists($$priFile): \ - !include($$priFile): error() - - # only configs which contain more than just subconfigs are saved for later. - $${currentConfig}._KEYS_ -= subconfigs - !isEmpty($${currentConfig}._KEYS_) { - allConfigs += $$currentConfig - contains($${currentConfig}._KEYS_, libraries) { - qtConfSetupLibraries() - # this ensures that references in QMAKE_LIBRARY_DEPS are unique. - qtConfSetModuleName() - ex = $$eval(config.modules.$${currentModule}) - !isEmpty(ex): \ - error("Module $$currentModule is claimed by both $$currentConfig and $${ex}.") - config.modules.$${currentModule} = $$currentConfig - } - } - - # prepend all subconfigs to files to keep a depth first search order - subconfigs = - for(n, $${currentConfig}.subconfigs._KEYS_) { - subconfig = $$eval($${currentConfig}.subconfigs.$${n}) - name = $${thisConfig}_$$basename(subconfig) - ex = $$eval(config.$${name}.dir) - !isEmpty(ex): \ - error("Basename clash between $$thisDir/$$subconfig and $${ex}.") - config.$${name}.dir = $$thisDir/$$subconfig - subconfigs += $$name - } - configsToProcess = $$subconfigs $$configsToProcess -} -# 'builtins' is used for command line parsing and test type dependency -# injection, but its features must not be processed regularly. -allModuleConfigs = $$member(allConfigs, 1, -1) - -QMAKE_SAVED_ARGS = $$QMAKE_EXTRA_ARGS -QMAKE_REDO_CONFIG = false -qtConfParseCommandLine() -qtConfCheckErrors() - -!isEmpty(config.input.list-features) { - all_ft = - for (currentConfig, allModuleConfigs) { - for (k, $${currentConfig}.features._KEYS_) { - pp = $$eval($${currentConfig}.features.$${k}.purpose) - !isEmpty(pp) { - pfx = $$eval($${currentConfig}.features.$${k}.section) - !isEmpty(pfx): pfx = "$$pfx: " - all_ft += $$qtConfPadCols($$k, ".......................", \ - $$pfx$$section(pp, $$escape_expand(\\n), 0, 0)) - } - } - } - all_ft = $$sorted(all_ft) - logn() - for (ft, all_ft): \ - logn($$ft) - error() -} - -!isEmpty(config.input.list-libraries) { - logn() - for (currentConfig, allModuleConfigs) { - !isEmpty($${currentConfig}.exports._KEYS_) { - !isEmpty($${currentConfig}.module): \ - logn($$eval($${currentConfig}.module):) - else: \ - logn($$section(currentConfig, ., -1):) - all_xp = - for (xport, $${currentConfig}.exports._KEYS_) { - libs = $$eval($${currentConfig}.exports.$$xport) - isEqual($${currentConfig}.libraries.$$first(libs).export, "") { # not isEmpty()! - !isEmpty(config.input.verbose): \ - all_xp += "$$xport!" - } else { - out = "$$xport" - !isEmpty(config.input.verbose):!isEqual(xport, $$libs): \ - out += "($$libs)" - all_xp += "$$out" - } - } - all_xp = $$sorted(all_xp) - all_xp ~= s,^([^!]*)!$,(\\1),g - for (xp, all_xp): \ - logn(" $$xp") - } - } - error() -} - -QMAKE_CONFIG_VERBOSE = $$eval(config.input.verbose) -isEmpty(QMAKE_CONFIG_VERBOSE): \ - QMAKE_CONFIG_VERBOSE = false -QMAKE_CONFIG_LOG = $$OUT_PWD/config.log -write_file($$QMAKE_CONFIG_LOG, "") -qtLog("Command line: $$qtSystemQuote($$QMAKE_SAVED_ARGS)") -$$QMAKE_REDO_CONFIG: \ - qtLog("config.opt: $$qtSystemQuote($$QMAKE_EXTRA_REDO_ARGS)") - -for (currentConfig, allModuleConfigs) { - qtConfSetModuleName() - qtConfSetupModuleOutputs() - # do early checks, mainly to validate the command line - qtConfProcessEarlyChecks() -} -qtConfCheckErrors() - -QMAKE_CONFIG_CACHE = $$OUT_PWD/config.cache -QMAKE_CONFIG_CACHE_USE = $$eval(config.input.cache_use) -cache_recheck = $$eval(config.input.cache_recheck) -equals(cache_recheck, yes) { - QMAKE_CONFIG_CACHE_USE = positive - cache_recheck = -} -isEmpty(QMAKE_CONFIG_CACHE_USE): \ - QMAKE_CONFIG_CACHE_USE = all -!equals(QMAKE_CONFIG_CACHE_USE, none) { - include($$QMAKE_CONFIG_CACHE, , true) - # this crudely determines when to discard the cache. this also catches the case - # of no cache being there in the first place. - !equals(cache.platform, $$[QMAKE_SPEC])|!equals(cache.xplatform, $$[QMAKE_XSPEC]) { - QMAKE_CONFIG_CACHE_USE = none - } else: !isEmpty(cache_recheck) { - for (cr, $$list($$split(cache_recheck, ","))) { - !isEmpty(cache.$${cr}._KEYS_) { - cache.$${cr}._KEYS_ = - } else { - qtConfAddWarning("Attempting to discard non-cached result '$$cr'.") - } - } - } -} -equals(QMAKE_CONFIG_CACHE_USE, none) { - cont = \ - "cache.platform = $$[QMAKE_SPEC]" \ - "cache.xplatform = $$[QMAKE_XSPEC]" - write_file($$QMAKE_CONFIG_CACHE, cont) -} - -CONFIG += qt_conf_tests_allowed -logn() -logn("Running configuration tests...") - -for (currentConfig, allModuleConfigs) { - tdir = $$eval($${currentConfig}.testDir) - isEmpty(tdir): tdir = config.tests - QMAKE_CONFIG_TESTS_DIR = $$absolute_path($$tdir, $$eval($${currentConfig}.dir)) - - qtConfSetModuleName() - - qtConfSetupTestTypeDeps() - - # correctly setup dependencies - QMAKE_CONFIG_DEPS = global global_private - QMAKE_LIBRARY_DEPS = $$eval(config.modules.global) - !isEmpty($${currentConfig}.module) { - for (d, $${currentConfig}.depends._KEYS_) { - dep = $$replace($${currentConfig}.depends.$$d, -private$, _private) - gdep = $$replace(dep, _private$, ) - dep *= $$gdep - QMAKE_CONFIG_DEPS += $$dep - !isEqual(gdep, $$dep): \ # libraries are in the private module. - QMAKE_LIBRARY_DEPS += $$eval(config.modules.$$gdep) - } - } - - qtConfCheckModuleCondition() - - qtConfHaveModule($$currentModule) { - # process all features - qtConfProcessFeatures() - } else { - qtConfOutputVar(assign, "privatePro", "QT.$${currentModule}.skip", "true") - } - - # generate files and reports - qtConfProcessOutput() - qtConfHaveModule($$currentModule) { - qtConfCreateReport() - qtConfCreateSummary() - } else { - QT_CONFIGURE_SKIPPED_MODULES += " $$currentModule" - } -} - -!isEmpty(QT_CONFIGURE_SKIPPED_MODULES): \ - qtConfAddNote("The following modules are not being compiled in this configuration:" $$QT_CONFIGURE_SKIPPED_MODULES) - -logn("Done running configuration tests.") -logn() - -!$$QMAKE_REDO_CONFIG { - write_file($$OUT_PWD/config.opt, QMAKE_SAVED_ARGS)|error() -} - -# these come from the pri files loaded above. -for (p, QMAKE_POST_CONFIGURE): \ - eval($$p) - -logn("Configure summary:") -logn() -qtConfPrintReport() - -load(qt_prefix_build_check) - -# final notes for the user -logn() -logn("Qt is now configured for building. Just run '$$QMAKE_MAKE_NAME'.") -pfx = $$[QT_INSTALL_PREFIX] -qtIsPrefixBuild($$pfx) { - logn("Once everything is built, you must run '$$QMAKE_MAKE_NAME install'.") - logn("Qt will be installed into '$$system_path($$pfx)'.") -} else { - logn("Once everything is built, Qt is installed.") - logn("You should NOT run '$$QMAKE_MAKE_NAME install'.") - logn("Note that this build cannot be deployed to other machines or devices.") -} -logn() -logn("Prior to reconfiguration, make sure you remove any leftovers from") -logn("the previous build.") -logn() |