Modularize the new configure system (infrastructure part)

This change implements the required infrastructure to modularize the new
configuration system.

This requires a hierarchy of configuration files, both for handling
multiple repositories and for individual modules inside the same
repository.

When configuring, they all need to get loaded first, as command line
processing needs to know about all possible command line options.

When the command line has been processed, the individual configuration
files need to get processed one after the other and independently from
each other.

Configure is now automatically invoked when building the a project
tree's "root" project; this works with both modular and top-level builds
of Qt (the latter with an according change in the super repo). As an
immediate consequence, the -skip option moves to the super repo with a
different implementation, as configuration is now done after the repo
list is determined. The option belongs there anyway.

This commit also adds an optional testDir entry to the json file. Like
this, we can still have all configure tests in qtbase/config.tests and
the configuration file in, e.g., corelib can reference those.

The files section can now be left out as long as a 'module' entry is
present, specifying the module name. The names of the files to generate
can then be deduced from that name. We still need to be able to specify
names directly for the global configuration files.

qtConfig() now also queries features which are module-specific. As it is
sometimes necessary to query the configuration of modules which should
not be actually linked (and cannot in the case of subdirs projects), the
new variable QT_FOR_CONFIG which allows specifying configuration-only
dependencies is introduced.

Done-with: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Change-Id: Id1b518a3aa34044748b87fb8fac14d79653f6b18
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Lars Knoll 2016-08-25 15:45:44 +02:00
parent 137e690ac7
commit 60e5a1c8ef
16 changed files with 486 additions and 276 deletions

View File

@ -935,6 +935,7 @@ foreach my $lib (@modules_to_sync) {
if (opendir DIR, $subdir) {
foreach my $t (sort { $b cmp $a } readdir(DIR)) {
next if ($t =~ /\.pri$/);
next if ($t =~ /^qt[a-z0-9]+-config(_p)?\.h$/);
my $file = "$subdir/$t";
if(-d $file) {
push @subdirs, $file unless($t eq "." || $t eq "..");
@ -985,6 +986,7 @@ foreach my $lib (@modules_to_sync) {
#calc files and "copy" them
foreach my $subdir (@subdirs) {
my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$" , 0);
@headers = grep(!/^qt[a-z0-9]+-config(_p)?\.h$/, @headers);
if (defined $inject_headers{$subdir}) {
foreach my $if (@{$inject_headers{$subdir}}) {
@headers = grep(!/^\Q$if\E$/, @headers); #in case we configure'd previously

32
configure vendored
View File

@ -1911,31 +1911,15 @@ done
set +f
IFS=$SAVED_IFS
# redirect qmake's output to a dummy Makefile
$CFG_QMAKE_PATH -o Makefile.cfg -qtconf "$QTCONFFILE" $relpath/configure.pri -- "$@" || exit 101
rm Makefile.cfg
#-------------------------------------------------------------------------------
# give feedback on configuration
#-------------------------------------------------------------------------------
if [ -n "$PLATFORM_NOTES" ]; then
echo
echo "Platform notes:"
echo "$PLATFORM_NOTES"
else
echo
fi
#-------------------------------------------------------------------------------
# build makefiles based on the configuration
# configure and build top-level makefile
#-------------------------------------------------------------------------------
if [ -n "$CFG_TOPLEVEL" ]; then
cd ..
fi
"$CFG_QMAKE_PATH" -qtconf "$QTCONFFILE" "$relpathMangled" || exit
"$CFG_QMAKE_PATH" -qtconf "$QTCONFFILE" "$relpathMangled" -- "$@" || exit
#-------------------------------------------------------------------------------
# finally save the executed command to another script
@ -1955,6 +1939,18 @@ if [ $CFG_REDO = no ]; then
chmod +x config.status
fi
#-------------------------------------------------------------------------------
# final notes for the user
#-------------------------------------------------------------------------------
if [ -n "$PLATFORM_NOTES" ]; then
echo
echo "Platform notes:"
echo "$PLATFORM_NOTES"
else
echo
fi
if [ -n "$PREFIX_COMPLAINTS" ]; then
echo
echo "$PREFIX_COMPLAINTS"

View File

@ -162,7 +162,6 @@
"separate-debug-info": { "type": "boolean", "name": "separate_debug_info" },
"shared": "boolean",
"silent": "void",
"skip": "addString",
"slog2": "boolean",
"sm": { "type": "boolean", "name": "sessionmanager" },
"sql-db2": "boolean",
@ -857,9 +856,6 @@
"type": "compile",
"test": "unix/reduce_relocs"
},
"skip_modules": {
"type": "skipModules"
},
"build_parts": {
"type": "buildParts"
},
@ -2096,9 +2092,6 @@
"condition": "libs.host_dbus",
"output": [ { "type": "varAppend", "name": "QT_HOST_CFLAGS_DBUS", "value": "libs.host_dbus.cflags", "eval": "true" } ]
},
"skip_modules": {
"output": [ { "type": "varAssign", "name": "QT_SKIP_MODULES", "value": "tests.skip_modules.value" } ]
},
"build_parts": {
"output": [ { "type": "varAppend", "name": "QT_BUILD_PARTS", "value": "tests.build_parts.value" } ]
},

View File

@ -195,34 +195,10 @@ defineTest(qtConfTest_detectPkgConfig) {
}
defineTest(qtConfTest_neon) {
contains(config.tests.architecture.subarch, "neon"): return(true)
contains($${currentConfig}.tests.architecture.subarch, "neon"): return(true)
return(false)
}
defineTest(qtConfTest_skipModules) {
$${1}.cache = -
export($${1}.cache)
skip =
uikit {
skip += qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples
!ios: skip += qtscript
}
for (m, config.input.skip) {
# normalize the command line input
m ~= s/^(qt)?/qt/
!exists($$_PRO_FILE_PWD_/../$$m) {
qtConfAddError("-skip command line argument called with non-existent module '$$m'.")
return(false)
}
skip += $$m
}
$${1}.value = $$unique(skip)
export($${1}.value)
return(true)
}
defineTest(qtConfTest_buildParts) {
parts = $$config.input.make
isEmpty(parts) {
@ -491,10 +467,10 @@ defineTest(qtConfOutput_architecture) {
"QT_ARCH = $$arch"
}
config.output.publicPro += $$publicPro
export(config.output.publicPro)
config.output.privatePro += $$privatePro
export(config.output.privatePro)
$${currentConfig}.output.publicPro += $$publicPro
export($${currentConfig}.output.publicPro)
$${currentConfig}.output.privatePro += $$privatePro
export($${currentConfig}.output.privatePro)
# setup QT_ARCH variable used by qtConfEvaluate
QT_ARCH = $$arch
@ -522,15 +498,15 @@ defineTest(qtConfOutput_qreal) {
defineTest(qtConfOutput_pkgConfig) {
!$${2}: return()
PKG_CONFIG = $$eval(config.tests.pkg-config.pkgConfig)
PKG_CONFIG = $$eval($${currentConfig}.tests.pkg-config.pkgConfig)
export(PKG_CONFIG)
# this method also exports PKG_CONFIG_(LIB|SYSROOT)DIR, so that tests using pkgConfig will work correctly
PKG_CONFIG_SYSROOT_DIR = $$eval(config.tests.pkg-config.pkgConfigSysrootDir)
PKG_CONFIG_SYSROOT_DIR = $$eval($${currentConfig}.tests.pkg-config.pkgConfigSysrootDir)
!isEmpty(PKG_CONFIG_SYSROOT_DIR) {
qtConfOutputVar(assign, "publicPro", "PKG_CONFIG_SYSROOT_DIR", $$PKG_CONFIG_SYSROOT_DIR)
export(PKG_CONFIG_SYSROOT_DIR)
}
PKG_CONFIG_LIBDIR = $$eval(config.tests.pkg-config.pkgConfigLibdir)
PKG_CONFIG_LIBDIR = $$eval($${currentConfig}.tests.pkg-config.pkgConfigLibdir)
!isEmpty(PKG_CONFIG_LIBDIR) {
qtConfOutputVar(assign, "publicPro", "PKG_CONFIG_LIBDIR", $$PKG_CONFIG_LIBDIR)
export(PKG_CONFIG_LIBDIR)
@ -560,20 +536,20 @@ defineTest(qtConfOutput_debugAndRelease) {
defineTest(qtConfOutput_compilerVersion) {
!$${2}: return()
name = $$upper($$config.tests.compiler.compilerId)
version = $$config.tests.compiler.compilerVersion
name = $$upper($$eval($${currentConfig}.tests.compiler.compilerId))
version = $$eval($${currentConfig}.tests.compiler.compilerVersion)
major = $$section(version, '.', 0, 0)
minor = $$section(version, '.', 1, 1)
patch = $$section(version, '.', 2, 2)
isEmpty(minor): minor = 0
isEmpty(patch): patch = 0
config.output.publicPro += \
$${currentConfig}.output.publicPro += \
"QT_$${name}_MAJOR_VERSION = $$major" \
"QT_$${name}_MINOR_VERSION = $$minor" \
"QT_$${name}_PATCH_VERSION = $$patch"
export(config.output.publicPro)
export($${currentConfig}.output.publicPro)
}
# should go away when qfeatures.txt is ported
@ -581,17 +557,17 @@ defineTest(qtConfOutput_extraFeatures) {
isEmpty(config.input.extra_features): return()
# write to qconfig.pri
config.output.publicPro += "$${LITERAL_HASH}ifndef QT_BOOTSTRAPPED"
$${currentConfig}.output.publicPro += "$${LITERAL_HASH}ifndef QT_BOOTSTRAPPED"
for (f, config.input.extra_features) {
feature = $$replace(f, "^no-", "")
FEATURE = $$upper($$replace(feature, -, _))
contains(f, "^no-.*") {
config.output.publicPro += \
$${currentConfig}.output.publicPro += \
"$${LITERAL_HASH}ifndef QT_NO_$$FEATURE" \
"$${LITERAL_HASH}define QT_NO_$$FEATURE" \
"$${LITERAL_HASH}endif"
} else {
config.output.publicPro += \
$${currentConfig}.output.publicPro += \
"$${LITERAL_HASH}if defined(QT_$$FEATURE) && defined(QT_NO_$$FEATURE)" \
"$${LITERAL_HASH}undef QT_$$FEATURE" \
"$${LITERAL_HASH}elif !defined(QT_$$FEATURE) && !defined(QT_NO_$$FEATURE)" \
@ -599,8 +575,8 @@ defineTest(qtConfOutput_extraFeatures) {
"$${LITERAL_HASH}endif"
}
}
config.output.publicPro += "$${LITERAL_HASH}endif"
export(config.output.publicPro)
$${currentConfig}.output.publicPro += "$${LITERAL_HASH}endif"
export($${currentConfig}.output.publicPro)
# write to qmodule.pri
disabled_features =
@ -649,8 +625,8 @@ defineTest(qtConfOutput_compilerFlags) {
output += "EXTRA_FRAMEWORKPATH += $$val_escape(config.input.fpaths)"
}
config.output.privatePro += $$output
export(config.output.privatePro)
$${currentConfig}.output.privatePro += $$output
export($${currentConfig}.output.privatePro)
}
defineTest(qtConfOutput_gccSysroot) {
@ -670,21 +646,21 @@ defineTest(qtConfOutput_gccSysroot) {
" QMAKE_CXXFLAGS += --sysroot=\$\$[QT_SYSROOT]" \
" QMAKE_LFLAGS += --sysroot=\$\$[QT_SYSROOT]" \
"}"
config.output.publicPro += $$output
export(config.output.publicPro)
$${currentConfig}.output.publicPro += $$output
export($${currentConfig}.output.publicPro)
}
defineTest(qtConfOutput_qmakeArgs) {
!$${2}: return()
config.output.privatePro = "!host_build {"
$${currentConfig}.output.privatePro = "!host_build {"
for (a, config.input.qmakeArgs) {
config.output.privatePro += " $$a"
$${currentConfig}.output.privatePro += " $$a"
EXTRA_QMAKE_ARGS += $$system_quote($$a)
}
config.output.privatePro += "}"
$${currentConfig}.output.privatePro += "}"
export(EXTRA_QMAKE_ARGS)
export(config.output.privatePro)
export($${currentConfig}.output.privatePro)
}
defineTest(qtConfOutputPostProcess_publicPro) {
@ -706,8 +682,8 @@ defineTest(qtConfOutputPostProcess_publicPro) {
"QT_RELEASE_DATE = $$config.input.qt_release_date"
}
config.output.publicPro += $$output
export(config.output.publicPro)
$${currentConfig}.output.publicPro += $$output
export($${currentConfig}.output.publicPro)
}
defineTest(qtConfOutputPostProcess_publicHeader) {
@ -729,8 +705,8 @@ defineTest(qtConfOutputPostProcess_publicHeader) {
!isEmpty(config.input.qt_libinfix): \
output += "$${LITERAL_HASH}define QT_LIBINFIX \"$$eval(config.input.qt_libinfix)\""
config.output.publicHeader += $$output
export(config.output.publicHeader)
$${currentConfig}.output.publicHeader += $$output
export($${currentConfig}.output.publicHeader)
}
@ -748,7 +724,7 @@ defineTest(qtConfReport_buildTypeAndConfig) {
qtConfAddReport("Building for: $$qtConfEvaluate('tests.architecture.arch')")
}
qtConfAddReport()
qtConfAddReport("Configuration: $$config.output.privatePro.append.CONFIG $$config.output.publicPro.append.QT_CONFIG")
qtConfAddReport("Configuration: $$eval($${currentConfig}.output.privatePro.append.CONFIG) $$eval($${currentConfig}.output.publicPro.append.QT_CONFIG)")
qtConfAddReport()
}
@ -775,10 +751,10 @@ defineTest(qtConfReport_buildMode) {
# ensure pristine environment for configuration
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)
# ... and cause them to be reloaded afterwards
QMAKE_POST_CONFIGURE += \
"include(\$\$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)" \
"include(\$\$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)"
# load and process input from configure
exists("$$OUT_PWD/config.tests/configure.cfg") {
include("$$OUT_PWD/config.tests/configure.cfg")
}
load(qt_configure)
# load and process input from configure.sh/.exe
include($$shadowed($$PWD)/config.tests/configure.cfg)

View File

@ -1,5 +1,7 @@
load(configure_base)
isEmpty(QMAKE_CONFIG_TESTS_DIR): QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests
# Try to build the test project in $$QMAKE_CONFIG_TESTS_DIR/$$1
# ($$_PRO_FILE_PWD_/config.tests/$$1 by default).
#

View File

@ -43,8 +43,6 @@ defineTest(qtRunLoggedCommand) {
return(true)
}
isEmpty(QMAKE_CONFIG_TESTS_DIR): QMAKE_CONFIG_TESTS_DIR = $$_PRO_FILE_PWD_/config.tests
# Ensure that a cache is present. If none was found on startup, this will create
# one in the build directory of the project which loads this feature.
cache()

View File

@ -95,3 +95,26 @@ defineTest(qtNomakeTools) {
export($${d}.CONFIG)
}
}
# This overloads the same function from qt_functions.prf.
# This is not in qt_module.prf, as that gets loaded too late.
defineTest(qtConfig) {
modules = $$QT $$QT_PRIVATE $$QT_FOR_PRIVATE $$QT_FOR_CONFIG
modules ~= s,-private$,_private,g
modules = $$resolve_depends(modules, "QT.", ".depends")
isEmpty(MODULE): \
MODULE = $$section($$list($$basename(_PRO_FILE_)), ., 0, 0)
exists($$OUT_PWD/qt$${MODULE}-config.pri) {
include($$OUT_PWD/qt$${MODULE}-config.pri)
modules += $${MODULE} $${MODULE}_private
}
modules += global global_private
modules = $$reverse(modules)
for (module, modules) {
contains(QT.$${module}.enabled_features, $$1): \
return(true)
contains(QT.$${module}.disabled_features, $$1): \
return(false)
}
error("Could not find feature $${1}.")
}

View File

@ -1,8 +1,3 @@
CONFIG -= qt debug_and_release
load(configure_base)
QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_CACHE_)/config.cache
QMAKE_CONFIG_CACHE_USE = all
QT_CONFIGURE_REPORT =
QT_CONFIGURE_NOTES =
@ -36,8 +31,8 @@ defineTest(qtConfAddError) {
defineTest(qtConfCommandlineSetInput) {
arg = $${1}
val = $${2}
!isEmpty(config.commandline.options.$${arg}.name): \
arg = $$eval(config.commandline.options.$${arg}.name)
!isEmpty($${currentConfig}.commandline.options.$${arg}.name): \
arg = $$eval($${currentConfig}.commandline.options.$${arg}.name)
config.input.$$arg = $$val
export(config.input.$$arg)
@ -74,7 +69,7 @@ defineTest(qtConfCommandline_void) {
return()
}
val = $$eval(config.commandline.options.$${opt}.value)
val = $$eval($${currentConfig}.commandline.options.$${opt}.value)
isEmpty(val): val = yes
qtConfCommandlineSetInput($$opt, $$val)
@ -86,11 +81,11 @@ defineTest(qtConfCommandline_enum) {
isEmpty(val): val = yes
# validate and map value
mapped = $$eval(config.commandline.options.$${opt}.values.$${val})
mapped = $$eval($${currentConfig}.commandline.options.$${opt}.values.$${val})
isEmpty(mapped) {
# just a list of allowed values
for (i, config.commandline.options.$${opt}.values._KEYS_) {
equals(config.commandline.options.$${opt}.values.$${i}, $$val) {
for (i, $${currentConfig}.commandline.options.$${opt}.values._KEYS_) {
equals($${currentConfig}.commandline.options.$${opt}.values.$${i}, $$val) {
mapped = $$val
break()
}
@ -108,12 +103,12 @@ defineTest(qtConfValidateValue) {
opt = $${1}
val = $${2}
validValues = $$eval(config.commandline.options.$${opt}.values._KEYS_)
validValues = $$eval($${currentConfig}.commandline.options.$${opt}.values._KEYS_)
isEmpty(validValues): \
return(true)
for (i, validValues) {
equals(config.commandline.options.$${opt}.values.$${i}, $$val): \
equals($${currentConfig}.commandline.options.$${opt}.values.$${i}, $$val): \
return(true)
}
@ -169,20 +164,24 @@ defineTest(qtConfCommandline_addString) {
!qtConfValidateValue($$opt, $$val): \
return()
!isEmpty(config.commandline.options.$${opt}.name): \
opt = $$eval(config.commandline.options.$${opt}.name)
!isEmpty($${currentConfig}.commandline.options.$${opt}.name): \
opt = $$eval($${currentConfig}.commandline.options.$${opt}.name)
config.input.$$opt += $$val
export(config.input.$$opt)
}
defineTest(qtConfParseCommandLine) {
custom = $$config.commandline.custom
customCall =
!isEmpty(custom) {
customCall = qtConfCommandline_$$custom
!defined($$customCall, test): \
error("Custom command line callback '$$custom' is undefined.")
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) {
@ -212,15 +211,24 @@ defineTest(qtConfParseCommandLine) {
next()
}
!isEmpty(customCall) {
$${customCall}($$c): \
next()
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")
var = $$eval(config.commandline.assignments.$${opt})
for (cc, allConfigs) {
var = $$eval($${cc}.commandline.assignments.$${opt})
!isEmpty(var): \
break()
}
isEmpty(var) {
qtConfAddError("Assigning unknown variable '$$opt' on command line.")
return()
@ -254,20 +262,26 @@ defineTest(qtConfParseCommandLine) {
return()
}
type = $$eval(config.commandline.options.$${opt})
isEmpty(type): \
type = $$eval(config.commandline.options.$${opt}.type)
isEmpty(type) {
# no match in the regular options, try matching the prefixes
for (p, config.commandline.prefix._KEYS_) {
e = "^-$${p}(.*)"
contains(c, $$e) {
opt = $$eval(config.commandline.prefix.$${p})
val = $$replace(c, $$e, "\\1")
type = "addString"
break()
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-(.*)") {
@ -368,8 +382,8 @@ defineReplace(qtConfPrepareArgs) {
}
defineTest(qtConfSetupLibraries) {
for (l, config.libraries._KEYS_) {
lpfx = config.libraries.$${l}
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
@ -396,8 +410,8 @@ defineTest(qtConfSetupLibraries) {
}
# reverse mapping for assignments on command line.
for (a, config.commandline.assignments._KEYS_) {
apfx = config.commandline.assignments.$${a}
for (a, $${currentConfig}.commandline.assignments._KEYS_) {
apfx = $${currentConfig}.commandline.assignments.$${a}
ra = config.commandline.rev_assignments.$$eval($$apfx)
$$ra = $$a
export($$ra)
@ -570,10 +584,12 @@ defineTest(qtConfExportLibrary) {
qtConfOutputVar(assign, $$output, QMAKE_$${NAME}_VERSION_MINOR, $$member(version, 1))
qtConfOutputVar(assign, $$output, QMAKE_$${NAME}_VERSION_PATCH, $$member(version, 2))
}
!isEmpty($${currentConfig}.module): \
qtConfExtendVar($$output, "QT.$${currentModule}_private.libraries", $$2)
}
defineTest(qtConfHandleLibrary) {
lpfx = config.libraries.$$1
lpfx = $${currentConfig}.libraries.$$1
defined($${lpfx}.result, var): return()
qtConfEnsureTestTypeDeps("library")
@ -647,10 +663,10 @@ defineTest(qtConfTest_library) {
defineTest(qtConfTestPrepare_compile) {
for (u, $$list($$eval($${1}.use))) {
!contains(config.libraries._KEYS_, $$u): \
!contains($${currentConfig}.libraries._KEYS_, $$u): \
error("Test $$1 tries to use undeclared library '$$u'")
qtConfHandleLibrary($$u)
lpfx = config.libraries.$${u}
lpfx = $${currentConfig}.libraries.$${u}
isEmpty($${lpfx}.source): \
return(false)
$${1}.literal_args += $$qtConfLibraryArgs($${lpfx}.sources.$$eval($${lpfx}.source))
@ -820,12 +836,12 @@ defineTest(qtConfIsBoolean) {
}
defineTest(qtConfSetupTestTypeDeps) {
for (tt, config.testTypeDependencies._KEYS_) {
for (tt, $${currentConfig}.testTypeDependencies._KEYS_) {
!defined(qtConfTest_$${tt}, test): \
error("Declaring dependency for undefined test type '$$tt'.")
for (f, config.testTypeDependencies.$${tt}._KEYS_) {
feature = $$eval(config.testTypeDependencies.$${tt}.$${f})
isEmpty(config.features.$${feature}._KEYS_): \
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'.")
}
}
@ -834,31 +850,31 @@ defineTest(qtConfSetupTestTypeDeps) {
# 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, config.testTypeAliases._KEYS_) {
for (tt, $${currentConfig}.testTypeAliases._KEYS_) {
!defined(qtConfTest_$${tt}, test): \
error("Aliasing undefined test type '$$tt'.")
for (tta, config.testTypeAliases.$${tt}._KEYS_) {
type = $$eval(config.testTypeAliases.$${tt}.$${tta})
for (tta, $${currentConfig}.testTypeAliases.$${tt}._KEYS_) {
type = $$eval($${currentConfig}.testTypeAliases.$${tt}.$${tta})
!defined(qtConfTest_$${type}, test): \
error("Aliasing '$$tt' to undefined test type '$$type'.")
config.testTypeForwards.$${type} += $$tt
export(config.testTypeForwards.$${type})
$${currentConfig}.testTypeForwards.$${type} += $$tt
export($${currentConfig}.testTypeForwards.$${type})
}
}
}
defineTest(qtConfEnsureTestTypeDeps) {
depsn = config.testTypeDependencies.$${1}._KEYS_
depsn = $${currentConfig}.testTypeDependencies.$${1}._KEYS_
!isEmpty($$depsn) {
for (dep, $$depsn) {
feature = $$eval(config.testTypeDependencies.$${1}.$${dep})
feature = $$eval($${currentConfig}.testTypeDependencies.$${1}.$${dep})
!qtConfCheckFeature($$feature): \
error("Test type '$$1' depends on non-emitted feature $${feature}.")
}
$$depsn =
export($$depsn)
}
fwdsn = config.testTypeForwards.$${1}
fwdsn = $${currentConfig}.testTypeForwards.$${1}
!isEmpty($$fwdsn) {
for (fwd, $$fwdsn): \
qtConfEnsureTestTypeDeps($$fwd)
@ -868,7 +884,7 @@ defineTest(qtConfEnsureTestTypeDeps) {
}
defineTest(qtRunSingleTest) {
tpfx = config.tests.$${1}
tpfx = $${currentConfig}.tests.$${1}
defined($${tpfx}.result, var): \
return()
@ -945,10 +961,10 @@ defineReplace(qtConfEvaluateSingleExpression) {
var = $$section(e, ".", 2, -1)
isEmpty(var): \
var = result
!contains(config.tests._KEYS_, $$test): \
!contains($${currentConfig}.tests._KEYS_, $$test): \
error("Unknown test object $${test} in expression '$${1}'.")
qtRunSingleTest($$test)
result = $$eval(config.tests.$${test}.$${var})
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.")
@ -956,22 +972,36 @@ defineReplace(qtConfEvaluateSingleExpression) {
var = $$section(e, ".", 2, -1)
isEmpty(var): \
var = result
!contains(config.libraries._KEYS_, $$lib): \
!contains($${currentConfig}.libraries._KEYS_, $$lib): \
error("Unknown library object $${lib} in expression '$${1}'.")
qtConfHandleLibrary($$lib)
!defined(config.libraries.$${lib}.$${var}, var): \
var = sources.$$eval(config.libraries.$${lib}.$${source}).$$var
result = $$eval(config.libraries.$${lib}.$${var})
!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(config.features._KEYS_, $$feature): \
!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(config.features.$${feature}.$${var})
result = $$eval($${currentConfig}.features.$${feature}.$${var})
} else: contains(e, "^config\..*") {
var = $$replace(e, "^config\.", "")
result = false
@ -1059,7 +1089,7 @@ defineReplace(qtConfEvaluateSubExpression) {
}
defineReplace(qtIsFeatureEnabled) {
enable = $$eval(config.features.$${1}.enable)
enable = $$eval($${currentConfig}.features.$${1}.enable)
!isEmpty(enable) {
$$qtConfEvaluate($$enable): \
return(true)
@ -1072,7 +1102,7 @@ defineReplace(qtIsFeatureEnabled) {
}
defineReplace(qtIsFeatureDisabled) {
disable = $$eval(config.features.$${1}.disable)
disable = $$eval($${currentConfig}.features.$${1}.disable)
!isEmpty(disable) {
$$qtConfEvaluate($$disable): \
return(true)
@ -1100,7 +1130,7 @@ defineReplace(qtConfCheckSingleCondition) {
}
defineTest(qtConfCheckFeature) {
fpfx = config.features.$${1}
fpfx = $${currentConfig}.features.$${1}
available = $$eval($${fpfx}.available)
!isEmpty(available): return(true)
@ -1138,7 +1168,7 @@ defineTest(qtConfCheckFeature) {
$${fpfx}.available = $$result
export($${fpfx}.available)
for (i, config.features.$${feature}.output._KEYS_): \
for (i, $${currentConfig}.features.$${feature}.output._KEYS_): \
qtConfProcessOneOutput($$feature, $$i)
return(true)
@ -1146,7 +1176,7 @@ defineTest(qtConfCheckFeature) {
defineTest(qtConfProcessFeatures) {
for (feature, config.features._KEYS_): \
for (feature, $${currentConfig}.features._KEYS_): \
qtConfCheckFeature($$feature)
}
@ -1167,8 +1197,8 @@ defineTest(qtConfReportPadded) {
defineReplace(qtConfCollectFeatures) {
l =
for (feature, $$list($${1})) {
$$eval(config.features.$${feature}.available): \
l += $$eval(config.features.$${feature}.description)
$$eval($${currentConfig}.features.$${feature}.available): \
l += $$eval($${currentConfig}.features.$${feature}.description)
}
isEmpty(l): return("<none>")
@ -1181,10 +1211,10 @@ defineTest(qtConfReport_featureList) {
defineReplace(qtConfFindFirstAvailableFeature) {
for (feature, $$list($${1})) {
isEmpty(config.features.$${feature}._KEYS_): \
isEmpty($${currentConfig}.features.$${feature}._KEYS_): \
error("Asking for a report on undefined feature $${2}.")
$$eval(config.features.$${feature}.available): \
return($$eval(config.features.$${feature}.description))
$$eval($${currentConfig}.features.$${feature}.available): \
return($$eval($${currentConfig}.features.$${feature}.description))
}
return("<none>")
@ -1195,14 +1225,14 @@ defineTest(qtConfReport_firstAvailableFeature) {
}
defineTest(qtConfReport_feature) {
!contains(config.features._KEYS_, $$2): \
!contains($${currentConfig}.features._KEYS_, $$2): \
error("Asking for a report on undefined feature $${2}.")
# hide report for not emitted features
isEmpty(config.features.$${2}.available): \
isEmpty($${currentConfig}.features.$${2}.available): \
return()
$$eval(config.features.$${2}.available) {
$$eval($${currentConfig}.features.$${2}.available) {
result = "yes"
!isEmpty(3): result = "$${3}"
} else {
@ -1210,7 +1240,7 @@ defineTest(qtConfReport_feature) {
!isEmpty(4): result = "$${4}"
}
text = $$eval(config.features.$${2}.description)
text = $$eval($${currentConfig}.features.$${2}.description)
qtConfReportPadded($${1}$$text, $$result)
}
@ -1270,17 +1300,15 @@ defineTest(qtConfCreateReportRecurse) {
}
defineTest(qtConfProcessEarlyChecks) {
qtConfCreateReportRecurse(config.earlyReport, false)
qtConfCheckErrors()
qtConfCreateReportRecurse($${currentConfig}.earlyReport, false)
}
defineTest(qtConfCreateReport) {
qtConfCreateReportRecurse(config.report, false)
qtConfCreateReportRecurse($${currentConfig}.report, false)
}
defineTest(qtConfCreateSummary) {
qtConfCreateReportRecurse(config.summary, "")
qtConfCreateReportRecurse($${currentConfig}.summary, "")
}
defineTest(qtConfPrintReport) {
@ -1322,15 +1350,6 @@ defineTest(qtConfCheckErrors) {
# output generation
#
defineReplace(qtConfOutputSelectProFile) {
!isEmpty($${1}.public) {
$$eval($${1}.public): \
return(publicPro)
}
return(privatePro)
}
# qtConfOutputVar(modifier, output, name, value)
defineTest(qtConfOutputVar) {
modifier = $$1
@ -1338,35 +1357,53 @@ defineTest(qtConfOutputVar) {
name = $$3
value = $$val_escape(4)
!isEmpty(config.output.$${output}.assign.$${name}): \
defined($${currentConfig}.output.$${output}.assign.$${name}, var): \
error("Trying to overwrite assigned variable '$$name' in '$$output' using modifier '$$modifier'.")
equals(modifier, assign) {
!isEmpty(config.output.$${output}.append.$${name})|!isEmpty(config.output.$${output}.remove.$${name}): \
!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.")
config.output.$${output}.assign.$${name} = $$value
$${currentConfig}.output.$${output}.assign.$${name} = $$value
} else: equals(modifier, append) {
contains(config.output.$${output}.remove.$${name}, $$value): \
contains($${currentConfig}.output.$${output}.remove.$${name}, $$value): \
error("Trying to append removed '$$value' to variable '$$name' in '$$output'.")
config.output.$${output}.append.$${name} += $$value
$${currentConfig}.output.$${output}.append.$${name} += $$value
} else: equals(modifier, remove) {
contains(config.output.$${output}.append.$${name}, $$value): \
contains($${currentConfig}.output.$${output}.append.$${name}, $$value): \
error("Trying to remove appended '$$value' to variable '$$name' in '$$output'.")
config.output.$${output}.remove.$${name} += $$value
$${currentConfig}.output.$${output}.remove.$${name} += $$value
} else {
error("Invalid modifier '$$modifier' passed to qtConfOutputVar.")
}
config.output.$${output}.$${modifier}._KEYS_ *= $${name}
export(config.output.$${output}.$${modifier}.$${name})
export(config.output.$${output}.$${modifier}._KEYS_)
$${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()
output = $$qtConfOutputSelectProFile($${2})
name = $$eval($${2}.name)
isEmpty(name): \
error("Output type 'var$$title($$1)' used in feature '$$eval($${2}.feature)' without a 'name' entry.")
@ -1375,6 +1412,8 @@ defineTest(qtConfOutputVarHelper) {
!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) {
@ -1392,6 +1431,8 @@ defineTest(qtConfOutput_varRemove) {
defineTest(qtConfOutputConfigVar) {
pro = $$3
var = $$4
modular = $$5
negative = $$eval($${1}.negative)
isEmpty(negative): negative = false
equals(2, $$negative): return()
@ -1402,26 +1443,31 @@ defineTest(qtConfOutputConfigVar) {
$$negative: val = no-$$val
}
qtConfOutputVar(append, $$pro, $$var, $$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")
qtConfOutputConfigVar($$1, $$2, "publicPro", "QT_CONFIG", true)
}
defineTest(qtConfOutput_publicConfig) {
qtConfOutputConfigVar($$1, $$2, "publicPro", "CONFIG")
!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")
qtConfOutputConfigVar($$1, $$2, "privatePro", "CONFIG", false)
}
defineTest(qtConfOutputSetDefine) {
config.output.$${1}.$${2} = $${3}
config.output.$${1}._KEYS_ *= $${2}
export(config.output.$${1}.$${2})
export(config.output.$${1}._KEYS_)
$${currentConfig}.output.$${1}.$${2} = $${3}
$${currentConfig}.output.$${1}._KEYS_ *= $${2}
export($${currentConfig}.output.$${1}.$${2})
export($${currentConfig}.output.$${1}._KEYS_)
}
defineTest(qtConfOutput_define) {
@ -1444,13 +1490,35 @@ defineTest(qtConfOutput_feature) {
name = $$eval($${1}.feature)
$${2} {
qtConfOutputVar(append, "publicPro", "QT_CONFIG", $$name)
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): \
@ -1458,10 +1526,14 @@ defineTest(qtConfOutput_publicFeature) {
feature = $$replace(name, [-+.], _)
$${2} {
qtConfOutputVar(append, "publicPro", "QT.global.enabled_features", $$name)
qtConfExtendVar("publicPro", "QT.$${currentModule}.enabled_features", $$name)
QT.$${currentModule}.enabled_features += $$name
export(QT.$${currentModule}.enabled_features)
qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", 1)
} else {
qtConfOutputVar(append, "publicPro", "QT.global.disabled_features", $$name)
qtConfExtendVar("publicPro", "QT.$${currentModule}.disabled_features", $$name)
QT.$${currentModule}.disabled_features += $$name
export(QT.$${currentModule}.disabled_features)
qtConfOutputSetDefine("publicHeader", "QT_FEATURE_$$feature", -1)
}
}
@ -1476,17 +1548,21 @@ defineTest(qtConfOutput_privateFeature) {
feature = $$replace(name, [-+.], _)
$${2} {
qtConfOutputVar(append, "privatePro", "QT.global.enabled_features", $$name)
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 {
qtConfOutputVar(append, "privatePro", "QT.global.disabled_features", $$name)
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 = config.features.$${feature}
fpfx = $${currentConfig}.features.$${feature}
opfx = $${fpfx}.output.$${2}
condition = $$eval($${opfx}.condition)
@ -1512,64 +1588,167 @@ defineTest(qtConfProcessOneOutput) {
}
defineTest(qtConfProcessOutput) {
!contains($${currentConfig}._KEYS_, "features"): \
return()
basedir = $$shadowed($$eval($${currentConfig}.dir))
module = $$eval($${currentConfig}.module)
# write it to the output files
for (type, config.files._KEYS_) {
file = $$OUT_PWD/$$eval(config.files.$${type})
isEmpty($${currentConfig}.files._KEYS_) {
# 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, config.output.$${type}.assign._KEYS_): \
config.output.$$type += "$$k = $$eval(config.output.$${type}.assign.$$k)"
for (k, config.output.$${type}.remove._KEYS_): \
config.output.$$type += "$$k -= $$eval(config.output.$${type}.remove.$$k)"
for (k, config.output.$${type}.append._KEYS_): \
config.output.$$type += "$$k += $$eval(config.output.$${type}.append.$$k)"
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 {
for (define, config.output.$${type}._KEYS_) {
value = $$eval(config.output.$${type}.$${define})
config.output.$$type += "$${LITERAL_HASH}define $$define $$value"
for (define, $${currentConfig}.output.$${type}._KEYS_) {
value = $$eval($${currentConfig}.output.$${type}.$${define})
$${currentConfig}.output.$$type += "$${LITERAL_HASH}define $$define $$value"
}
}
defined(qtConfOutputPostProcess_$${type}, test): \
qtConfOutputPostProcess_$${type}()
write_file($$file, config.output.$${type})|error()
ppScope =
!isEmpty(module): ppScope = $${module}_
defined(qtConfOutputPostProcess_$${ppScope}$${type}, test): \
qtConfOutputPostProcess_$${ppScope}$${type}()
file = $$eval($${currentConfig}.files.$${type})
fileCont.$$file += $$eval($${currentConfig}.output.$${type})
fileCont._KEYS_ *= $$file
}
for (file, fileCont._KEYS_): \
write_file($$basedir/$$file, fileCont.$$file)|error()
}
#
# tie it all together
#
defineTest(qtConfigure) {
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 =
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($${1}, blob)
!parseJson(configure_data, config): \
error("Invalid or non-existent file $${1}.")
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()
qtConfSetupTestTypeDeps()
qtConfParseCommandLine()
!isEmpty(_QMAKE_SUPER_CACHE_): \
QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_SUPER_CACHE_)/config.cache
else: \
QMAKE_CONFIG_CACHE = $$dirname(_QMAKE_CACHE_)/config.cache
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
}
equals(QMAKE_CONFIG_CACHE_USE, none) {
cont = \
"cache.platform = $$[QMAKE_SPEC]" \
"cache.xplatform = $$[QMAKE_XSPEC]"
write_file($$QMAKE_CONFIG_CACHE, cont)
}
qtConfParseCommandLine()
!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)
}
for (currentConfig, allConfigs) {
qtConfSetModuleName()
qtConfSetupModuleOutputs()
# do early checks, mainly to validate the command line
qtConfProcessEarlyChecks()
}
qtConfCheckErrors()
CONFIG += qt_conf_tests_allowed
logn()
logn("Running configuration tests...")
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
}
}
# process all features
qtConfProcessFeatures()
@ -1578,14 +1757,15 @@ defineTest(qtConfigure) {
qtConfProcessOutput()
qtConfCreateReport()
qtConfCreateSummary()
logn("Done running configuration tests.")
logn()
}
qtConfigure($$_PRO_FILE_PWD_/configure.json)
# these come from the pri files loaded above.
for (p, QMAKE_POST_CONFIGURE): \
eval($$p)
logn("Done running configuration tests.")
logn()
logn("Configure summary:")
logn()
qtConfPrintReport()

View File

@ -300,10 +300,16 @@ defineTest(prepareRecursiveTarget) {
}
defineTest(qtConfig) {
contains(QT.global.enabled_features, $$1): \
return(true)
contains(QT.global.disabled_features, $$1): \
return(false)
modules = $$QT $$QT_PRIVATE $$QT_FOR_CONFIG
modules ~= s,-private$,_private,g
modules = $$resolve_depends(modules, "QT.", ".depends")
modules += global global_private
modules = $$reverse(modules)
for (module, modules) {
contains(QT.$${module}.enabled_features, $$1): \
return(true)
contains(QT.$${module}.disabled_features, $$1): \
return(false)
}
error("Could not find feature $${1}.")
}

View File

@ -106,6 +106,16 @@ alien_syncqt: return()
MODULE_INC_OUTDIR = $$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME
exists($$OUT_PWD/qt$${MODULE}-config.h) {
fwd_rel = $$relative_path($$OUT_PWD, $$MODULE_INC_OUTDIR)
SYNCQT.INJECTIONS += \
$$fwd_rel/qt$${MODULE}-config.h:qt$${MODULE}-config.h \
$$fwd_rel/qt$${MODULE}-config_p.h:$$MODULE_VERSION/$$MODULE_INCNAME/private/qt$${MODULE}-config_p.h
inst_rel = $$relative_path($$OUT_PWD, $$_PRO_FILE_PWD_)
SYNCQT.HEADER_FILES += $$inst_rel/qt$${MODULE}-config.h
SYNCQT.PRIVATE_HEADER_FILES += $$inst_rel/qt$${MODULE}-config_p.h
}
for (injection, SYNCQT.INJECTIONS) {
injects = $$split(injection, :)
dst_hdr = $$absolute_path($$member(injects, 0), $$MODULE_INC_OUTDIR)

View File

@ -35,6 +35,41 @@ else: \
MODULE_PRI = $$mod_inst_pfx/qt_lib_$${MODULE_ID}.pri
MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
exists($$OUT_PWD/qt$${MODULE}-config.pri): \
include($$OUT_PWD/qt$${MODULE}-config.pri)
defineReplace(qtGetFeaturesForModule) {
enabled = $$unique(QT.$${1}.enabled_features)
disabled = $$unique(QT.$${1}.disabled_features)
result = \
"QT.$${1}.enabled_features =$$join(enabled, " ", " ")" \
"QT.$${1}.disabled_features =$$join(disabled, " ", " ")"
return($$result)
}
defineReplace(qtGetExportsForModule) {
result =
for (var, QT.$${1}.exports): \
result += "$$var = $$val_escape($$var)"
return($$result)
}
defineReplace(qtExportLibsForModule) {
result =
for (lib, QT.$${1}.libraries) {
NAME = $$upper($$lib)
vars = \
QMAKE_LIBS_$$NAME QMAKE_LIBS_$${NAME}_DEBUG QMAKE_LIBS_$${NAME}_RELEASE \
QMAKE_CFLAGS_$$NAME QMAKE_INCDIR_$$NAME QMAKE_$${NAME}_VERSION \
QMAKE_$${NAME}_VERSION_MAJOR QMAKE_$${NAME}_VERSION_MINOR QMAKE_$${NAME}_VERSION_PATCH
for (var, vars) {
!isEmpty($$var): \
result += "$$var = $$val_escape($$var)"
}
}
return($$result)
}
!build_pass {
# Create a module .pri file
@ -102,6 +137,9 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
"QT.$${MODULE_ID}.module_config =$$join(module_build_type, " ", " ")" \
$$module_config \
"QT.$${MODULE_ID}.DEFINES = $$val_escape(MODULE_DEFINES)" \
$$qtGetFeaturesForModule($$MODULE_ID) \
$$qtGetExportsForModule($$MODULE_ID) \
"QT_CONFIG +=$$join(QT.$${MODULE_ID}.QT_CONFIG, " ", " ")" \
"" \
"QT_MODULES += $$MODULE"
winrt: MODULE_PRI_CONT += \
@ -126,7 +164,10 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
"QT.$${MODULE}_private.includes = $$MODULE_PRIVATE_INCLUDES" \
"QT.$${MODULE}_private.frameworks =" \
"QT.$${MODULE}_private.depends = $$private_deps" \
"QT.$${MODULE}_private.module_config =$$join(module_build_type, " ", " ")"
"QT.$${MODULE}_private.module_config =$$join(module_build_type, " ", " ")" \
$$qtGetFeaturesForModule($${MODULE}_private) \
"" \
$$qtExportLibsForModule($${MODULE}_private)
write_file($$MODULE_PRIVATE_PRI, MODULE_PRIVATE_PRI_CONT)|error()
}
MODULE_PRI_FILES = $$MODULE_PRI $$MODULE_PRIVATE_PRI

View File

@ -12,6 +12,8 @@
# Ensure that each module has a .qmake.cache when properly qmake'd.
cache()
load(qt_configure)
load(qt_build_config)
TEMPLATE = subdirs
@ -74,6 +76,7 @@ QT_BUILD_PARTS -= libs tools examples tests
QMAKE_DISTCLEAN += \
.qmake.cache \
config.cache \
config.log \
mkspecs/modules/*.pri \
mkspecs/modules-inst/*.pri

View File

@ -24,7 +24,6 @@ DISTCLEAN_DEPS += qmake-clean
# config.status (and configure.cache, which is the same for Windows)
# are omitted for convenience of rebuilds.
QMAKE_DISTCLEAN += \
config.cache \
config.summary \
config.tests/.qmake.cache \
mkspecs/qconfig.pri \

View File

@ -1015,35 +1015,21 @@ void Configure::configure()
QStringList args;
args << buildPath + "/bin/qmake"
<< "-o" << "Makefile.cfg"
<< sourcePath + "/configure.pri"
<< sourcePathMangled
<< "--" << configCmdLine;
QString pwd = QDir::currentPath();
QDir::setCurrent(buildPathMangled);
if (int exitCode = Environment::execute(args, QStringList(), QStringList())) {
cout << "Qmake failed, return code " << exitCode << endl << endl;
dictionary[ "DONE" ] = "error";
}
QDir::setCurrent(pwd);
if ((dictionary["REDO"] != "yes") && (dictionary["DONE"] != "error"))
saveCmdLine();
}
void Configure::generateMakefiles()
{
QString pwd = QDir::currentPath();
{
QStringList args;
args << buildPath + "/bin/qmake" << sourcePathMangled;
QDir::setCurrent(buildPathMangled);
if (int exitCode = Environment::execute(args, QStringList(), QStringList())) {
cout << "Qmake failed, return code " << exitCode << endl << endl;
dictionary[ "DONE" ] = "error";
}
}
QDir::setCurrent(pwd);
}
bool Configure::showLicense(QString orgLicenseFile)
{
if (dictionary["LICENSE_CONFIRMED"] == "yes") {

View File

@ -51,7 +51,6 @@ public:
void configure();
void generateHeaders();
void generateMakefiles();
void generateQDevicePri();
void prepareConfigTests();

View File

@ -80,10 +80,6 @@ int runConfigure( int argc, char** argv )
if (!app.isOk())
return 3;
app.generateMakefiles();
if( !app.isOk() )
return 2;
return 0;
}