Qt5 Build System
Qt5’s configure system
This is a description of the Qt5 qmake-based build system.
For Qt6, see Qt6 Build System.
For a description of terms used here, please see the Qt Build System Glossary.
configure.json
There are several instances of this file
top-level - SOURCE_ROOT/configure.json
For the whole of Qt. Only defines the “skip” command line option at the moment.
repo level - SOURCE_ROOT/qtbase/configure.json
Valid for all module within this repository.
module level - SOURCE_ROOT/qtbase/src/network/configure.json
Valid for this particular module.
repo level keys
- files
- subconfigs
- commandline
- libraries
- testTypeDependencies
- testTypeAliases
- tests
- features
- earlyReport
- report
- summary
module level keys
- module: The current module’s name. E.g. “network”
- depends: list of module this module depends on
- testDir: path to the config.tests directory, relative to this file
- commandline: specification of command line arguments for configure
- libraries: definitions of libraries that can be used with QMAKE_USE
- tests: definition of configure tests
- features: Qt features that can be enabled/disabled
- condition: The module will be skipped if the condition is not met
- report: Notes and warnings that are displayed if certain conditions are met.
- summary: Defines what is displayed in configure’s summary output for this module.
commandline
This object defines the commandline options for the configure script.
custom
Here, we can register a custom commandline handler for configure arguments that do not fit into the rest of the declarative concept of configure.json. As of Qt 5.15, there can be exactly one custom commandline handler per
configure.json
. The custom handler is run before the actual command line processing. Example:
“commandline”: { “custom”: “qmakeArgs”, … }
will trigger the callback
defineTest(qtConfCommandline_qmakeArgs) { contains(1, QMAKE_[A-Z0-9_]+ *[-+]?=.*) { config.input.qmakeArgs += $$1 export(config.input.qmakeArgs) return(true) } return(false) }
which filters out command line arguments that assign to QMAKE_* variables and puts them into an internal variable.
options
The keys in the
options
objects are the arguments that can be passed to configure. With
“bindir”: “string”,
we can do
configure -bindir bin
. The values of the
options
object are strings or objects. If they are strings, the string specifies the
type
of the argument:
“bindir”: “string”,
is equivalent to
“bindir”: {“type”: “string”},
The value of this configure argument lands in
config.input.bindir
.
name
name
For command-line options that do not form a valid variable name, one can define the internal variable name like this:
"static-runtime": { "name": "static_runtime" },
The result ends up in
config.input.static_runtime
in this example.
type
type
An option of type
foo
triggers a callback
qtConfCommandline_foo
in
qt_configure.prf
or
configure.pri
. There are the following pre-defined types:
Type | Valid Values |
---|---|
boolean | yes, no |
enum | one of multiple defined values |
see below | |
string | non-empty string |
optionalString | “yes”, if empty string |
the string, otherwise | |
addString | non-empty string |
The argument can be passed multiple times. | |
The values is then a list of strings. | |
void | does not accept a value |
The type can be some arbitray string as illustrated by the type
redo
which is triggered by the
-redo
configure argument and calls
qtCommandline_redo
. That’s as customizable as it can get but is not to be confused with the
custom
command line option object above. The Gods of Naming Things Well just cried a bit. Enums have another key, named
values
, that can be a list of valid values:
“pcre”: { “type”: “enum”, “values”: [ “no”, “qt”, “system” ] },
But behold! We can also use a map as demonstrated by this little brain teaser:
“release”: { “type”: “enum”, “debug”, “values”: { “yes”: “no”, “no”: “yes” } },
values
values
Command-line options can specify a list of valid values.
“linker”: { “type”: “optionalString”, “values”: [ “bfd”, “gold”, “lld” ] },
If any other value is passed, an configure exits with an error.
prefix
prefix
This fantastically named commandline key is best described by an example:
"prefix": { "D": "defines", }
What this does is: enable the user to to
configure -DFOO -DBAR
and stores the list
FOO BAR
in
config.input.defines
. Internally, this creates a command-line option of type
addString
.
assignments
assignments
Here we can define variables assignments the user can pass to configure.
With
“assignments”: { “MYSQL_PATH”: “mysql.prefix” },
we can do
configure MYSQL_PATH=/some/where
. The result is stored in
config.input.mysql.prefix
.
Every assignment that is not registered in this way will fail:
./configure NO=WAY ... ERROR: Assigning unknown variable 'NO' on command line.
Note that variables beginning with
QMAKE_
are handled by
qtConfCommandline_qmakeArgs
as described above.
libraries
Is an object. Its keys are strings that can be passed to QMAKE_USE. Its values are objects again.
Example:
“libraries”: { “corewlan”: { “label”: “CoreWLan”, “export”: "“,”test“: {”lang“:”objc++“,”include“: [ "CoreWLAN/CoreWLAN.h", "CoreWLAN/CWInterface.h" ],”main“:”[CWInterface interfaceWithName:@"en2"];" }, “sources”: [ “-framework CoreWLAN -framework Foundation” ] }, … }
- label: The display name for configure’s user output. - export: - test: the name of a test or an object defining a configure test for this library. Details below. - sources: Array of several “sources” where the library might be found. - headers: Array of string, containing relative paths to header files (as they would appear in #include directives). Configure tries to locate those headers using heuristics. If the headers cannot be located, the test fails. The generated test source code will contain include directives for these headers on success. Note that header files within frameworks cannot be located as of now. Use test.include instead.
test
Configure test for the library this object is located in.
If
test
is a string, then it’s the name of a subdirectory below config.tests containing a test project that is configured with qmake and then built. If
test
is an object, then the following keys are used:
- lang: The programming language to be used. Valid values are [“c++”, “c”, “objc”, “objc++”]. Default is “c++”.
- head: array of strings with custom code before includes
- include: array of strings for which include directives are generated. E.g. produces
["vector"]
.#include <foo.h>
- tail: array of strings with custom code after includes
- main: Array of strings that form the body of the main function of the test. The main function’s signature for C++ is the usual .
int main(int argc, char **argv)
- qmake: Array of strings with custom code for the test’s .pro file. Added after SOURCES. The special string is replaced by the current config dir.
@PWD@
sources
A source is a generalized location of a library. Configure probes the sources sequentially. The first successful wins.
There are different types of sources: - inline: the library is specified inline in a ‘libs’ field. Overrides from the command line are accepted. Where “inline” means “this is just a string”. But hey, this can also be an object. - makeSpec: The library is provided by the qmake spec. This source type cannot fail. - pkgConfig: The library is found via pkg-config.
Sources are dispatched by type to
qtConfLibrary_$${type}
. The handlers for the types above are defined in qt_configure.prf. Modules can add their own type “foo” by adding
defineTest(qtConfLibrary_foo)
to their local configure.pri. The common keys of a source object are: - type: The type as described above. - condition: If the condition is false, the source fails. Usually some platform or toolchain check like
"config.msvc"
.
inline sources
Can be specified “inline” as string
“sources”: [“-lz -lproxy”]
or as object if you need to set additional properties
“sources”: [ { “comment”: “longwinded rambling”, “libs”: “-lz -lproxy” }]
With
builds
you can specify different libraries per build:
{ "libs": "", "builds": { "debug": "-ldbus-1d", "release": "-ldbus-1" }, "condition": "config.win32" },
makeSpec sources
"sources": [ { "type": "makeSpec", "spec": "NETWORK" } ]
Reads the variables QMAKE_LIBDIR_NETWORK, QMAKE_LIBS_NETWORK and QMAKE_INCDIR_NETWORK from the mkspec. This source is always successful.
pkgConfig sources
{ "type": "pkgConfig", "host": true, "args": "dbus-1 >= 1.2" },
- host: boolean, run pkgConfig for host or target?
- args: Arguments for pkgConfig.
tests
TO BE DONE
features
- Options from highest to lowest significance
- emitIf:
- Defaults to true
- Early check (checked before anything else)
- Overrules every other option and will make the feature non-existent, if false. Note: this means that before using such a feature, you must replicate the condition of emitIf to avoid “feature X does not exist” errors.
- If used in connection with enable or disable and evaluates to false: Will cause a warning, feature will be disabled
- Commonly used to turn off features, that are not supported on certain platforms (Direct… on Linux)
- enable/disable:
- Default to false
- Operate on input variables (corresponds to command line options : -feature-foo, -no-feature-foo, and command line options defined in configure.json)
- Override autoDetect
- If both are set to true, “disable” wins
- If enable is true and “condition” is not met, will trigger an error
- Used to explicitly enable/disable a feature from the command line
- autoDetect:
- Defaults to true
- Only relevant if the feature is not enabled/disabled on the command line
- If true: feature is enabled by default. But the condition decides about feature’s status. It’s not an error if the condition is false.
- If false: feature is disabled by default. It can only be turned on manually with the -feature-foo configure switch.
- condition:
- Defaults to true
- Requirements that have to be met in order to use this feature
testTypeDependencies
From the introducing commit c8b46d3989ded1368d40e487a141b3cfb3d968ba:
Some test types (like the compile tests) require that other features have been checked before, so that the compile test sets up the right environment. Implement this through a ‘testTypeDependencies’ section in the json file that explicitly encodes those dependencies for certain test types.
Example from qtbase:
“testTypeDependencies”: { “linkerSupportsFlag”: [ “use_gold_linker” ], “compile”: [ “shared”, “use_gold_linker”, “compiler-flags”, “gcc-sysroot” ], “detectPkgConfig”: [ “cross_compile” ], “library”: [ “pkg-config” ], “getPkgConfigVariable”: [ “pkg-config” ], “neon”: [ “architecture” ] },
The keys are test types. The values are lists of features.
testTypeAliases
Comment from the source code: >>> 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. >>>
Example from qtbase:
“testTypeAliases”: { “compile”: [ “library”, “architecture”, “x86Simd”, “x86SimdAlways” ] },
The
architecture
test calls
qtConfTest_compile
and inspects the build result. The type
architecture
is declared as alias for
compile
. The
testTypeAliases
data is used together with
testTypeDependencies
to calculate the order in which the tests are run / features are evaluated. Putting everything together, in our example the
architecture
test must run after the features
shared
,
use_gold_linker
,
compiler-flags
and
gcc-sysroot
have been evaluated.
summary
TO BE DONE
configure.pri
Optional per module. This file is an extends qt_configure.prf. For example, in QtNetwork configure.pri defines qtConfLibrary_openssl which makes it possible to have libraries of type openssl in that module.
special qmake variables
There are certain qmake variables that only make sense in the context of the Qt build itself. Other qmake variables behave specially in the Qt build.
Public and private modules
A normal module (e.g. QtNetwork) is split into a public and a private module. Usually, users depend on the public one:
QT += network
but you can also depend on the private one. Some tests do that, for example.
QT += network-private
The meaning of
QT
within Qt modules is overloaded.
Dependencies between Qt modules
With the following variables one can express dependencies between Qt modules:
Variable | Meaning |
---|---|
QT
|
Public dependencies of the public module. |
QT_PRIVATE
|
Private dependencies of the public module. |
QT_FOR_PRIVATE
|
Public dependencies of the private module. |
Public dependencies means the dependencies are exported. Private dependencies are not exported.
See the message of commit b8bee40726fc93db9a025324712de6fff6a084d5 for more information.
How to
Check for features
In .pro files
To check for a certain feature use the qtConfig test function:
qtConfig(icu): DEFINES += WE_USE_ICU
There are two ways of making a module’s (private) features available to your pro file: - add <module> (or it’s “-private” equivalent for private features) to QT - add <module> (or it’s “-private” equivalent for private features) to QT_FOR_CONFIG (this only adds the feature related functionality without private include paths)
In C++ code
To check for a certain feature use the QT_CONFIG macro. For example, to check for the private feature
icu
, do the following:
#if QT_CONFIG(icu) doStuffWithFoo(); #endif
This will only work correctly if the
QT_FEATURE_icu
macro is defined. It is defined in
qtcore-config_p.h
. Add the include
qglobal_p.h
for private features of QtCore. This file is also pulled in by any private header. If you already include other private headers from QtCore you may omit the include. Public features are defined in
qtcore-config.h
. Just include any QtCore header (or
qglobal.h
) to be able to check for those. The respective include files for other modules, e.g. QtNetwork, are called
qtnetworkglobal[_p].h
.