ab0cc3055d
we pull this feat off by booting configure with a dummy spec. the proper spec gets loaded subsequently. note that it was necessary to move the cache loading after processing the early checks (from which the spec handling is triggered). this is just fine, as the cache is needed only by tests, which are forbidden at this stage by definition. Change-Id: I5120e25a8bf05fb8cc5485fd93cf6387301089aa Reviewed-by: Jake Petroules <jake.petroules@qt.io>
1860 lines
58 KiB
Plaintext
1860 lines
58 KiB
Plaintext
|
|
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()
|
|
}
|
|
|
|
defineTest(qtConfCommandlineSetInput) {
|
|
arg = $${1}
|
|
val = $${2}
|
|
!isEmpty($${currentConfig}.commandline.options.$${arg}.name): \
|
|
arg = $$eval($${currentConfig}.commandline.options.$${arg}.name)
|
|
|
|
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}
|
|
isEmpty(val): 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}
|
|
isEmpty(val) {
|
|
v = $$qtConfPeekNextCommandlineArg()
|
|
contains(v, "^-.*|[A-Z_]+=.*")|isEmpty(v): \
|
|
val = "yes"
|
|
else: \
|
|
val = $$qtConfGetNextCommandlineArg()
|
|
}
|
|
|
|
!qtConfValidateValue($$opt, $$val): \
|
|
return()
|
|
|
|
qtConfCommandlineSetInput($$opt, $$val)
|
|
}
|
|
|
|
|
|
defineTest(qtConfCommandline_addString) {
|
|
opt = $${1}
|
|
val = $${2}
|
|
isEmpty(val): 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_ARGS = $$cat($$OUT_PWD/config.opt, lines) $$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-Z_]+)=(.*)") {
|
|
opt = $$replace(c, "^([A-Z_]+)=(.*)", "\\1")
|
|
val = $$replace(c, "^([A-Z_]+)=(.*)", "\\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
|
|
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 = yes
|
|
} else: contains(c, "^-(.*)") {
|
|
opt = $$replace(c, "^-(.*)", "\\1")
|
|
val =
|
|
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")
|
|
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
|
|
}
|
|
|
|
isEmpty(type) {
|
|
qtConfAddError("Unknown command line option '$$c'.")
|
|
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)
|
|
}
|
|
}
|
|
|
|
defineReplace(qtConfToolchainSupportsFlag) {
|
|
test_out_dir = $$shadowed($$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 $${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_gold_linker: \
|
|
LFLAGS = -fuse-ld=gold
|
|
|
|
return($$qtConfToolchainSupportsFlag($$LFLAGS "-Wl,$$flag"))
|
|
}
|
|
|
|
defineReplace(qtConfFindInPathList) {
|
|
for (dir, 2) {
|
|
exists("$$dir/$${1}"): \
|
|
return("$$dir/$${1}")
|
|
}
|
|
return()
|
|
}
|
|
|
|
defineReplace(qtConfFindInPath) {
|
|
ensurePathEnv()
|
|
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(qtConfPrepareArgs) {
|
|
arglist = $$split(1)
|
|
args =
|
|
for (a, arglist): \
|
|
args += $$system_quote($$a)
|
|
return($$args)
|
|
}
|
|
|
|
defineTest(qtConfSetupLibraries) {
|
|
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 = $$l
|
|
export($${lpfx}.export)
|
|
}
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
# reverse mapping for assignments on command line.
|
|
for (a, $${currentConfig}.commandline.assignments._KEYS_) {
|
|
apfx = $${currentConfig}.commandline.assignments.$${a}
|
|
ra = config.commandline.rev_assignments.$$eval($$apfx)
|
|
$$ra = $$a
|
|
export($$ra)
|
|
}
|
|
}
|
|
|
|
# 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): \
|
|
error("'inline' source in library '$$lib' does not specify 'libs'.")
|
|
|
|
# direct libs. overwrites inline libs.
|
|
defined(config.input.$${lib}.libs, var) {
|
|
$${1}.libs = $$eval(config.input.$${lib}.libs)
|
|
export($${1}.libs)
|
|
}
|
|
|
|
# build-specific direct libs. overwrites inline libs.
|
|
vars =
|
|
any = false
|
|
all = true
|
|
for (b, $${1}.builds._KEYS_) {
|
|
iv = $${lib}.libs.$${b}
|
|
vars += $$eval(config.commandline.rev_assignments.$${iv})
|
|
defined(config.input.$${iv}, var) {
|
|
$${1}.builds.$${b}.libs = $$eval(config.input.$${iv})
|
|
export($${1}.builds.$${b}.libs)
|
|
any = true
|
|
} else {
|
|
all = false
|
|
}
|
|
}
|
|
$$any:!$$all {
|
|
qtConfAddError("Either none or all of $$join(vars, ", ", [, ]) must be specified.")
|
|
return(false)
|
|
}
|
|
|
|
# prefix. prepends to (possibly overwritten) inline libs.
|
|
prefix = $$val_escape(config.input.$${lib}.prefix)
|
|
!isEmpty(prefix) {
|
|
$${1}.includedir = $$prefix/include
|
|
export($${1}.includedir)
|
|
$${1}.libs = "-L$$prefix/lib $$eval($${1}.libs)"
|
|
export($${1}.libs)
|
|
}
|
|
|
|
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'.")
|
|
|
|
$${1}.includedir = "$$val_escape(QMAKE_INCDIR_$$spec)"
|
|
export($${1}.includedir)
|
|
libs =
|
|
for (l, QMAKE_LIBDIR_$$spec): \
|
|
libs += -L$$l
|
|
libs += $$eval(QMAKE_LIBS_$$spec)
|
|
$${1}.libs = "$$val_escape(libs)"
|
|
export($${1}.libs)
|
|
|
|
# the library definition is always in scope, so no point in exporting it.
|
|
$${1}.export = false
|
|
export($${1}.export)
|
|
|
|
return(true)
|
|
}
|
|
|
|
# the library is found via pkg-config.
|
|
defineTest(qtConfLibrary_pkgConfig) {
|
|
pkg_config = $$qtConfPkgConfig($$eval($${1}.host))
|
|
isEmpty(pkg_config): \
|
|
return(false)
|
|
args = $$qtConfPrepareArgs($$eval($${1}.args))
|
|
|
|
!qtConfPkgConfigPackageExists($$pkg_config, $$args): \
|
|
return(false)
|
|
|
|
qtRunLoggedCommand("$$pkg_config --modversion $$args", version)|return(false)
|
|
qtRunLoggedCommand("$$pkg_config --libs-only-L --libs-only-l $$args", $${1}.libs)|return(false)
|
|
qtRunLoggedCommand("$$pkg_config --cflags $$args", $${1}.cflags)|return(false)
|
|
version ~= s/[^0-9.].*$//
|
|
$${1}.version = $$first(version)
|
|
export($${1}.version)
|
|
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) {
|
|
qmake_args =
|
|
libs = $$eval($${1}.libs)
|
|
!isEmpty(libs): \
|
|
qmake_args += $$system_quote(LIBS += $$libs)
|
|
for (b, $${1}.builds._KEYS_): \
|
|
qmake_args += $$system_quote(LIBS_$$upper($$b) += $$eval($${1}.builds.$${b}))
|
|
includedir = $$eval($${1}.includedir)
|
|
!isEmpty(includedir): \
|
|
qmake_args += $$system_quote(INCLUDEPATH *= $$includedir)
|
|
cflags = $$eval($${1}.cflags)
|
|
!isEmpty(cflags): \
|
|
qmake_args += $$system_quote(QMAKE_CFLAGS += $$cflags) $$system_quote(QMAKE_CXXFLAGS += $$cflags)
|
|
return($$qmake_args)
|
|
}
|
|
|
|
defineTest(qtConfExportLibrary) {
|
|
isEmpty(2): return()
|
|
!$$qtConfEvaluate($$eval($${1}.export)): return()
|
|
|
|
output = privatePro
|
|
|
|
eval(libs = $$eval($${1}.libs))
|
|
eval(cflags = $$eval($${1}.cflags))
|
|
eval(includes = $$eval($${1}.includedir))
|
|
|
|
# Split $$cflags into stuff that goes into DEFINES, INCLUDEPATH, and other stuff.
|
|
defines =
|
|
ignored =
|
|
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 or *-config scripts include other flags
|
|
# we really don't need and shouldn't add (pg_config is really bad).
|
|
ignored += $$i
|
|
}
|
|
}
|
|
!isEmpty(ignored): \
|
|
qtConfAddNote("Dropped compiler flags '$$ignored' when detecting library '$$2'.")
|
|
|
|
NAME = $$upper($$2)
|
|
!isEmpty(libs): qtConfOutputVar(assign, $$output, QMAKE_LIBS_$$NAME, $$libs)
|
|
for (b, $${1}.builds._KEYS_): \
|
|
qtConfOutputVar(assign, $$output, QMAKE_LIBS_$${NAME}_$$upper($$b), \
|
|
$$eval($${1}.builds.$${b}))
|
|
!isEmpty(defines): qtConfOutputVar(assign, $$output, QMAKE_DEFINES_$$NAME, $$defines)
|
|
!isEmpty(includes): qtConfOutputVar(assign, $$output, QMAKE_INCDIR_$$NAME, $$includes)
|
|
!isEmpty($${currentConfig}.module): \
|
|
qtConfExtendVar($$output, "QT.$${currentModule}_private.libraries", $$2)
|
|
}
|
|
|
|
defineTest(qtConfHandleLibrary) {
|
|
lpfx = $${currentConfig}.libraries.$$1
|
|
defined($${lpfx}.result, var): return()
|
|
|
|
qtConfEnsureTestTypeDeps("library")
|
|
qtConfTestPrepare_compile($$lpfx)
|
|
use_args = $$eval($${lpfx}.literal_args)
|
|
|
|
qtConfLoadResult($${lpfx}, $$1) {
|
|
$$eval($${lpfx}.result): \
|
|
qtConfExportLibrary($${lpfx}.sources.$$eval($${lpfx}.source), $$eval($${lpfx}.export))
|
|
return()
|
|
}
|
|
|
|
qtLogTestIntro($${lpfx}, "looking for library $${1}")
|
|
|
|
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} ...")
|
|
|
|
!$$qtConfEvaluate($$eval($${spfx}.condition)) {
|
|
qtLog(" => source failed condition.")
|
|
next()
|
|
}
|
|
|
|
!$${call}($$spfx) {
|
|
qtLog(" => source produced no result.")
|
|
next()
|
|
}
|
|
|
|
# if the library defines a test, use it to verify the source.
|
|
!isEmpty($${lpfx}.test) {
|
|
$${lpfx}.literal_args = $$use_args $$qtConfLibraryArgs($$spfx)
|
|
$${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($${spfx}, $$eval($${lpfx}.export))
|
|
|
|
$${lpfx}.source = $$s
|
|
export($${lpfx}.source)
|
|
result = true
|
|
break()
|
|
}
|
|
|
|
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) {
|
|
for (u, $$list($$eval($${1}.use))) {
|
|
libConfig =
|
|
contains($${currentConfig}.libraries._KEYS_, $$u) {
|
|
libConfig = $${currentConfig}
|
|
qtConfHandleLibrary($$u)
|
|
} else {
|
|
for (d, QMAKE_CONFIG_DEPS) {
|
|
contains($${d}.libraries._KEYS_, $$u) {
|
|
libConfig = $$d
|
|
break()
|
|
}
|
|
}
|
|
}
|
|
isEmpty(libConfig) {
|
|
nu = $$upper($$u)
|
|
libs = $$eval(QMAKE_LIBS_$$nu) $$eval(QMAKE_LIBS_$${nu}_DEBUG) $$eval(QMAKE_LIBS_$${nu}_RELEASE)
|
|
defines = $$eval(QMAKE_DEFINES_$${nu})
|
|
includes = $$eval(QMAKE_INCDIR_$${nu})
|
|
|
|
isEmpty(libs):isEmpty(defines):isEmpty(includes): \
|
|
error("Test $$1 tries to use undeclared library '$$u'")
|
|
$${1}.literal_args += $$system_quote(QMAKE_USE += $$u)
|
|
} else {
|
|
lpfx = $${libConfig}.libraries.$${u}
|
|
isEmpty($${lpfx}.source): \
|
|
return(false)
|
|
$${1}.literal_args += $$qtConfLibraryArgs($${lpfx}.sources.$$eval($${lpfx}.source))
|
|
}
|
|
}
|
|
export($${1}.literal_args)
|
|
return(true)
|
|
}
|
|
|
|
defineTest(qtConfTest_compile) {
|
|
test = $$eval($${1}.test)
|
|
host = $$eval($${1}.host)
|
|
isEmpty(host): host = false
|
|
|
|
test_dir = $$QMAKE_CONFIG_TESTS_DIR/$$test
|
|
test_out_dir = $$shadowed($$test_dir)
|
|
!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_gold_linker: \
|
|
qmake_configs += "use_gold_linker"
|
|
|
|
# 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"
|
|
|
|
qmake_args += "\"CONFIG += $$qmake_configs\""
|
|
|
|
!$$host {
|
|
# On WinRT we need to change the entry point as we cannot create windows
|
|
# applications
|
|
winrt: \
|
|
qmake_args += " \"QMAKE_LFLAGS += /ENTRY:main\""
|
|
|
|
# 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
|
|
}
|
|
|
|
# Clean up after previous run
|
|
exists($$test_out_dir/Makefile): \
|
|
QMAKE_MAKE = "$$QMAKE_MAKE clean && $$QMAKE_MAKE"
|
|
|
|
mkpath($$test_out_dir)|error()
|
|
write_file($$test_out_dir/.qmake.cache)|error()
|
|
|
|
# add possible command line args
|
|
qmake_args += $$qtConfPrepareArgs($$eval($${1}.args)) $$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_verifySpec) {
|
|
qtConfTest_compile($$1): return(true)
|
|
qtConfFatalError("Cannot compile a minimal program. The toolchain or QMakeSpec is broken.", log)
|
|
}
|
|
|
|
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()
|
|
|
|
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
|
|
logn("$$log_msg")
|
|
write_file($$QMAKE_CONFIG_LOG, msg, append)
|
|
}
|
|
|
|
defineTest(qtConfSaveResult) {
|
|
equals($${1}.cache, -): \
|
|
return()
|
|
keys = result $$eval($${1}.cache)
|
|
cont = "cache.$${2}._KEYS_ = $$keys"
|
|
for (k, keys): \
|
|
cont += "cache.$${2}.$${k} = $$val_escape($${1}.$${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})
|
|
}
|
|
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(qtConfEnsureTestTypeDeps) {
|
|
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): \
|
|
qtConfEnsureTestTypeDeps($$fwd)
|
|
$$fwdsn =
|
|
export($$fwdsn)
|
|
}
|
|
}
|
|
|
|
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): \
|
|
return()
|
|
|
|
qtLogTestIntro($${tpfx}, "executing config test $${1}")
|
|
|
|
result = false
|
|
$${call}($${tpfx}): result = true
|
|
|
|
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, "^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 {
|
|
condition = $$eval($${fpfx}.condition)
|
|
!isEmpty(condition) {
|
|
result = $$qtConfCheckSingleCondition($$1, $$condition, $$enabled)
|
|
} else {
|
|
result = true
|
|
# check whether we have an array of conditions
|
|
for (i, $${fpfx}.condition._KEYS_) {
|
|
condition = $$eval($${fpfx}.condition.$$i)
|
|
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
|
|
#
|
|
|
|
QT_CONF_REPORT_PADDING = "........................................"
|
|
|
|
defineTest(qtConfReportPadded) {
|
|
pad = $$num_add($$str_size($$QT_CONF_REPORT_PADDING), -$$str_size($${1}))
|
|
lessThan(pad, 0): pad = 0
|
|
str = "$$1 $$str_member($$QT_CONF_REPORT_PADDING, 0, $$pad)"
|
|
|
|
qtConfAddReport("$$str $${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) {
|
|
condition = $$eval($${entry}.condition)
|
|
r = $$qtConfEvaluate($$condition)
|
|
!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) {
|
|
for (n, QT_CONFIGURE_REPORT): \
|
|
logn($$n)
|
|
logn()
|
|
|
|
for (n, QT_CONFIGURE_NOTES) {
|
|
logn($$n)
|
|
logn()
|
|
}
|
|
|
|
for (w, QT_CONFIGURE_WARNINGS) {
|
|
logn($$w)
|
|
logn()
|
|
}
|
|
|
|
!isEmpty(QT_CONFIGURE_ERRORS) {
|
|
for (e, QT_CONFIGURE_ERRORS) {
|
|
logn($$e)
|
|
logn()
|
|
}
|
|
mention_config_log:!$$QMAKE_CONFIG_VERBOSE {
|
|
logn("Check config.log for details.")
|
|
logn()
|
|
}
|
|
|
|
!equals(config.input.continue, yes): \
|
|
error()
|
|
}
|
|
}
|
|
|
|
defineTest(qtConfCheckErrors) {
|
|
!isEmpty(QT_CONFIGURE_ERRORS):!equals(config.input.continue, yes): \
|
|
qtConfPrintReport()
|
|
}
|
|
|
|
#
|
|
# output generation
|
|
#
|
|
|
|
# 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)
|
|
}
|
|
}
|
|
|
|
# command line built-ins post-processing
|
|
defineTest(qtConfOutput_builtins) {
|
|
QMAKE_CONFIG_VERBOSE = $$eval(config.input.verbose)
|
|
isEmpty(QMAKE_CONFIG_VERBOSE): \
|
|
QMAKE_CONFIG_VERBOSE = false
|
|
export(QMAKE_CONFIG_VERBOSE)
|
|
|
|
QMAKE_CONFIG_CACHE_USE = $$eval(config.input.cache_use)
|
|
isEmpty(QMAKE_CONFIG_CACHE_USE): \
|
|
QMAKE_CONFIG_CACHE_USE = all
|
|
export(QMAKE_CONFIG_CACHE_USE)
|
|
}
|
|
|
|
defineTest(qtConfProcessOneOutput) {
|
|
feature = $${1}
|
|
fpfx = $${currentConfig}.features.$${feature}
|
|
opfx = $${fpfx}.output.$${2}
|
|
|
|
condition = $$eval($${opfx}.condition)
|
|
!isEmpty(condition):!$$qtConfEvaluate($$condition): \
|
|
return()
|
|
|
|
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'.")
|
|
|
|
condition = $$eval($${opfx}.condition)
|
|
!isEmpty(condition) {
|
|
!$$qtConfEvaluate($$condition): \
|
|
return(false)
|
|
}
|
|
|
|
$${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
|
|
#
|
|
|
|
cfgs =
|
|
isEmpty(_QMAKE_SUPER_CACHE_)|equals(OUT_PWD, $$dirname(_QMAKE_SUPER_CACHE_)) {
|
|
c = $$basename(_PRO_FILE_PWD_)
|
|
config.$${c}.dir = $$_PRO_FILE_PWD_
|
|
cfgs += $$c
|
|
!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): \
|
|
return()
|
|
|
|
load(configure_base)
|
|
|
|
QMAKE_POST_CONFIGURE =
|
|
config.builtins.dir = $$PWD/data
|
|
configsToProcess = builtins $$configsToProcess
|
|
allConfigs =
|
|
for(ever) {
|
|
isEmpty(configsToProcess): \
|
|
break()
|
|
|
|
currentConfig = config.$$take_first(configsToProcess)
|
|
thisDir = $$eval($${currentConfig}.dir)
|
|
jsonFile = $$thisDir/configure.json
|
|
priFile = $$thisDir/configure.pri
|
|
|
|
allConfigs += $$currentConfig
|
|
|
|
# load configuration data
|
|
configure_data = $$cat($$jsonFile, blob)
|
|
!parseJson(configure_data, $$currentConfig): \
|
|
error("Invalid or non-existent file $${jsonFile}.")
|
|
exists($$priFile): \
|
|
!include($$priFile): error()
|
|
|
|
# prepend all subconfigs to files to keep a depth first search order
|
|
subconfigs =
|
|
for(n, $${currentConfig}.subconfigs._KEYS_) {
|
|
subconfig = $$eval($${currentConfig}.subconfigs.$${n})
|
|
name = $$basename(subconfig)
|
|
config.$${name}.dir = $$thisDir/$$subconfig
|
|
subconfigs += $$name
|
|
}
|
|
configsToProcess = $$subconfigs $$configsToProcess
|
|
}
|
|
|
|
for (currentConfig, allConfigs): \
|
|
qtConfSetupLibraries()
|
|
|
|
QMAKE_SAVED_ARGS = $$QMAKE_EXTRA_ARGS
|
|
QMAKE_REDO_CONFIG = false
|
|
qtConfParseCommandLine()
|
|
|
|
for (currentConfig, allConfigs) {
|
|
qtConfSetModuleName()
|
|
qtConfSetupModuleOutputs()
|
|
# do early checks, mainly to validate the command line
|
|
qtConfProcessEarlyChecks()
|
|
}
|
|
qtConfCheckErrors()
|
|
|
|
!isEmpty(_QMAKE_SUPER_CACHE_): \
|
|
QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_SUPER_CACHE_)/config.cache
|
|
else: \
|
|
QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_CACHE_)/config.cache
|
|
!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
|
|
}
|
|
equals(QMAKE_CONFIG_CACHE_USE, none) {
|
|
cont = \
|
|
"cache.platform = $$[QMAKE_SPEC]" \
|
|
"cache.xplatform = $$[QMAKE_XSPEC]"
|
|
write_file($$QMAKE_CONFIG_CACHE, cont)
|
|
}
|
|
|
|
QMAKE_CONFIG_LOG = $$OUT_PWD/config.log
|
|
!equals(QMAKE_CONFIG_CACHE_USE, all): \
|
|
write_file($$QMAKE_CONFIG_LOG, "")
|
|
|
|
CONFIG += qt_conf_tests_allowed
|
|
logn()
|
|
logn("Running configuration tests...")
|
|
|
|
for (currentConfig, allConfigs) {
|
|
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
|
|
!isEmpty($${currentConfig}.module) {
|
|
for (d, $${currentConfig}.depends._KEYS_) {
|
|
dep = $$replace($${currentConfig}.depends.$$d, -private$, _private)
|
|
dep *= $$replace(dep, _private$, )
|
|
QMAKE_CONFIG_DEPS += $$dep
|
|
}
|
|
}
|
|
|
|
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()
|