qt_register_target_dependencies does the same thing as
qt_record_extra_qt_package_dependency but in more convenient way.
Update the qt_register_target_dependencies signature and adjust naming,
it now accepts PUBLIC and PRIVATE multi-value arguments and called
qt_internal_register_target_dependencies.
Use it and deprecate qt_record_extra_qt_package_dependency.
Pick-to: 6.5 6.8 6.9
Change-Id: I0594cf699ec1e3af7210dd7450fa3f81c1f565ae
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
qt_find_package is only meant to be used for looking up 3rd party
packages. Using it with Qt packages can cause issues where we record
the Qt packages as 3rd party packages.
When using a developer build, issue a warning when qt_find_package is
called with a provided target that starts with the Qt6:: namespace.
Pick-to: 6.8
Change-Id: Ic2a2d613dbf4fa7e7c51e9b73696bf14e4af866f
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Backstory.
The main reason why we keep getting "unable to promote 3rd party 'X'
target to global scope" errors when building Qt repositories, is
because we try to promote 3rd party imported targets in a different
scope than where the imported targets were created.
What were the main motivations for promoting 3rd party targets to
global?
1) imported targets are by default local to the directory scope they
were created in
2) we want 3rd party targets to be accessible across subdirectory
scopes, but looked up once, e.g. qt_find_package(JPEG) looked up in
src/gui/CMakeLists.txt, but the target should also be usable in the
sibling scope
src/plugins/imageformats/CMakeLists.txt
Having the package lookup close to the consuming qt module is easier
to maintain, because all the other 3rd party dependency lookups are
in the same file. This goes against the conventional CMake advice
where each subdirectory should look for its own dependencies, or the
dependency should be available directly in the root project scope.
3) to make the 3rd party targets available in the root project scope
as part of the following flow:
QtPostProcess.cmake ->
qt_internal_create_module_depends_file() ->
qt_collect_third_party_deps() ->
get_property(INTERFACE_QT_PACKAGE_NAME) ->
write 3rd party Dependencies.cmake file for each qt module.
Properties can only be queried from an imported target if it's in
the same scope or was promoted to global, otherwise you get
'non-existent target' errors.
4) for prl and pri file generation, where we need the targets to be
available during generator expression evaluation within the
relevant qt module directory scope
Here is a list of approaches I came up with on how to improve the
situation.
1) Make all imported targets global during the Qt build, by iterating
over the directory property IMPORTED_TARGETS and making each one
global.
Requires CMake 3.21.
Status: Already implemented for a long time, but is opt-in.
Pros: Relatively robust
Cons: Minimum CMake version for building Qt is 3.16.
2) Make all imported targets global during the Qt build using the
CMAKE_FIND_PACKAGE_TARGETS_GLOBAL variable.
Requires CMake 3.24.
Status: Not implemented, but can be set by Qt builders directly on
the command line.
Pros: Should be robust
Cons: Minimum CMake version for building Qt is 3.16.
3) Abandon the desire to have a single qt_find_package in a single
directory scope, and embrace the CMake-way of repeating the
dependency in each subdirectory that requires it.
Status: Not implemented.
Pros: Should be robust
Cons: A lot of qt_find_package duplication, will require rewriting
various code paths, QtPostProcess would have to be done at
directory scope, unclear if dependency tracking will still work
work reliably when there might be multiple same-named
directory-scoped targets, other unknown unknowns
4) Move all qt_find_package calls into a $repo_name/dependencies.cmake
file which would be read at project root scope. This would
potentially avoid all scoping issues, because all dependencies will
have to be specified at root scope.
Status: Not implemented.
Pros: No duplication
Cons: Dependencies are not scoped anymore to module directories,
won't be able to conditionally look for dependencies based on
module feature evaluation, not clear yet how this will tie into
standalone tests which are in tests/ subdir, other unknown unknowns
5) Try to promote as many 3rd party libraries at project root scope
as possible.
Currently we have 2 general locations where we look up
dependencies.
One is each qt_find_package call. The other is
Qt6FooDependencies.cmake ->
_qt_internal_find_third_party_dependencies().
Many 3rd party targets are created by
_qt_internal_find_third_party_dependencies() in the root scope, but
not promoted, and then we try to promote them in child scopes using
qt_find_package, which causes the promotion errors.
Starting with 58eefbd0b6169d0749b312268c1ae1e594e04362 and
37a5e001277db9e1392a242171ab2b88cb6c3049 we now record the provided
targets of previous qt_find_package calls.
So instead of waiting to try and promote targets later during the
configuration process, we can make sure we promote the targets at
_qt_internal_find_third_party_dependencies() call time, right
when we lookup the Qt dependencies of the qt repo, in the root
scope.
Status: Implemented in this change
Notably, we only promote 3rd party targets to global for qt builds,
and not user projects, to not accidentally break user project
behaviors.
Also, we only promote 3rd party targets, and not Qt internal
targets like Qt6::Core, Qt6::Platform, Qt6::PlatformCommonInternal,
Qt6::GlobalConfig, etc, for a few reasons:
- the code that requires targets to be global only cares about
3rd party targets
- promoting the internal targets is more prone to breaking, because
there is more than one place where find_package(Qt6Foo) might be
called, and if that ends up being in a different directory scope,
we encounter the same global promotion errors.
Some notable cases where this happens:
- tests/CMakeLists.txt brings in extra Qt packages via
StandaloneTestsConfig.cmake files
- qtbase standalone tests qt_internal_qtbase_pre_project_setup()
calls find_package(Qt6 COMPONENTS BuildInternals) which ends
up creating the Platform target in the root scope instead of
the tests/ scope
- Qt6::BundledLibpng links against Core, which ends up trying to
promote Core's internal dependencies Platform and GlobalConfig
To only promote 3rd party targets, we walk the dependencies of
an initial target recursively, and skip promoting targets that have
the _qt_is_internal_target or
_qt_should_skip_global_promotion_always properties set.
Pros: Improves the situation compared to the status quo
Cons: Still not ideal due to the various filtering of internal
targets and having to mark them as such.
6) Avoid promoting targets to global if we can detect that the target
was created in a different scope than where we are trying to
promote it.
We can do that by comparing the target's BINARY_DIR to the
CMAKE_CURRENT_BINARY_DIR and skip promotion if they are not equal.
Status: Not implemented, but we can consider it because it's
quick to do.
Pros: More robust than newly implemented approach (5)
Cons: Requires CMake 3.18, because trying to read the BINARY_DIR
property on an INTERFACE_LIBRARY would error out.
Also, if we implement it and make it the default when using 3.18+,
we might 'collect' a lot more hidden promotion errors that will
only be revealed later once someone uses CMake 3.16 or 3.17,
because most will probably use newer CMake versions.
Perhaps the trade-off is worth it?
Pick-to: 6.8
Fixes: QTBUG-89204
Fixes: QTBUG-94356
Fixes: QTBUG-95052
Fixes: QTBUG-98807
Fixes: QTBUG-125371
Change-Id: I088a17a98ef35aa69537a3ad208c61de40def581
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
They will used from another Public.cmake file in a follow up commit.
Pick-to: 6.8
Change-Id: I71b69ed76ca48c391ba45329eb9c305e4a2a238b
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
qt_find_package() sets QT_TARGETS_OF_QMAKE_LIB_<NAME> to all provided
targets, without checking if each target exists.
qt_generate_qmake_libraries_pri_content() iterates targets listed in
QT_TARGETS_OF_QMAKE_LIB_<NAME>. If a target does not exist,
qt_generate_qmake_libraries_pri_content() trusts it as a library name
and adds it into QMAKE_LIB_<NAME>_<CONFIG> directly.
3073b9c4dec5e5877363794bf81cbd4b84fdb9ee adds zstd::libzstd_shared to
the PROVIDED_TARGETS argument of qt_find_package().
When WrapZSTD::WrapZSTD is found but zstd::libzstd_shared doesn't exist,
QMAKE_LIBS_ZSTD now contains wrong content "libzstd::libzstd_shared".
Pick-to: 6.8 6.7
Change-Id: Id2a79d6c028a80e53d7b9a6a6d11f436d40dde65
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This change adds a new -sbom configure option to allow generating and
installing an SPDX v2.3 SBOM file when building a qt repo.
The -sbom-dir option can be used to configure the location where
each repo sbom file will be installed.
By default it is installed into
$prefix/$archdatadir/sbom/$sbom_lower_project_name.sdpx
which is basically ~/Qt/sbom/qtbase-6.8.0.spdx
The file is installed as part of the default installation rules, but
it can also be installed manually using the "sbom" installation
component, or "sbom_$lower_project_name" in a top-level build. For
example: cmake install . --component sbom_qtbase
CMake 3.19+ is needed to read the qt_attribution.json files for
copyrights, license info, etc. When using an older cmake version,
configuration will error out. It is possible to opt into using an
older cmake version, but the generated sbom will lack all the
attribution file information.
Using an older cmake version is untested and not officially supported.
Implementation notes.
The bulk of the implementation is split into 4 new files:
- QtPublicSbomHelpers.cmake - for Qt-specific collecting, processing
and dispatching the generation of various pieces of the SBOM document
e.g. a SDPX package associated with a target like Core, a SDPX
file entry for each target binary file (per-config shared library,
archive, executable, etc)
- QtPublicSbomGenerationHelpers.cmake - for non-Qt specific
implementation of SPDX generation. This also has some code that was
taken from the cmake-sbom 3rd party project, so it is dual licensed
under the usual Qt build system BSD license, as well as the MIT
license of the 3rd party project
- QtPublicGitHelpers.cmake - for git related features, mainly to embed
queried hashes or tags into version strings, is dual-licensed for
the same reasons as QtPublicSbomGenerationHelpers.cmake
- QtSbomHelpers.cmake - Qt-specific functions that just forward
arguments to the public functions. These are meant to be used in our
Qt CMakeLists.txt instead of the public _qt_internal_add_sbom ones
for naming consistency. These function would mostly be used to
annotate 3rd party libraries with sbom info and to add sbom info
for unusual target setups (like the Bootstrap library), because most
of the handling is already done automatically via
qt_internal_add_module/plugin/etc.
The files are put into Public cmake files, with the future hope of
making this available to user projects in some capacity.
The distinction of Qt-specific and non-Qt specific code might blur a
bit, and thus the separation across files might not always be
consistent, but it was best effort.
The main purpose of the code is to collect various information about
targets and their relationships and generate equivalent SPDX info.
Collection is currently done for the following targets: Qt modules,
plugins, apps, tools, system libraries, bundled 3rd party libraries
and partial 3rd party sources compiled directly as part of Qt targets.
Each target has an equivalent SPDX package generated with information
like version, license, copyright, CPE (common vulnerability
identifier), files that belong to the package, and relationships on
other SPDX packages (associated cmake targets), mostly gathered from
direct linking dependencies.
Each package might also contain files, e.g. libQt6Core.so for the Core
target. Each file also has info like license id, copyrights, but also
the list of source files that were used to generate the file and a
sha1 checksum.
SPDX documents can also refer to packages in other SPDX documents, and
those are referred to via external document references. This is the
case when building qtdeclarative and we refer to Core.
For qt provided targets, we have complete information regarding
licenses, and copyrights.
For bundled 3rd party libraries, we should also have most information,
which is usually parsed from the
src/3rdparty/libfoo/qt_attribution.json files.
If there are multiple attribution files, or if the files have multiple
entries, we create a separate SBOM package for each of those entries,
because each might have a separate copyright or version, and an sbom
package can have only one version (although many copyrights).
For system libraries we usually lack the information because we don't
have attribution files for Find scripts. So the info needs to be
manually annotated via arguments to the sbom function calls, or the
FindFoo.cmake scripts expose that information in some form and we
can query it.
There are also corner cases like 3rdparty sources being directly
included in a Qt library, like the m4dc files for Gui, or PCRE2 for
Bootstrap.
Or QtWebEngine libraries (either Qt bundled or Chromium bundled or
system libraries) which get linked in by GN instead of CMake, so there
are no direct targets for them.
The information for these need to be annotated manually as well.
There is also a distinction to be made for static Qt builds (or any
static Qt library in a shared build), where the system libraries found
during the Qt build might not be the same that are linked into the
final user application or library.
The actual generation of the SBOM is done by file(GENERATE)-ing one
.cmake file for each target, file, external ref, etc, which will be
included in a top-level cmake script.
The top-level cmake script will run through each included file, to
append to a "staging" spdx file, which will then be used in a
configure_file() call to replace some final
variables, like embedding a file checksum.
There are install rules to generate a complete SBOM during
installation, and an optional 'sbom' custom target that allows
building an incomplete SBOM during the build step.
The build target is just for convenience and faster development
iteration time. It is incomplete because it is missing the installed
file SHA1 checksums and the document verification code (the sha1 of
all sha1s). We can't compute those during the build before the files
are actually installed.
A complete SBOM can only be achieved at installation time. The install
script will include all the generated helper files, but also set some
additional variables to ensure checksumming happens, and also handle
multi-config installation, among other small things.
For multi-config builds, CMake doesn't offer a way to run code after
all configs are installed, because they might not always be installed,
someone might choose to install just Release.
To handle that, we rely on ninja installing each config sequentially
(because ninja places the install rules into the 'console' pool which
runs one task at a time).
For each installed config we create a config-specific marker file.
Once all marker files are present, whichever config ends up being
installed as the last one, we run the sbom generation once, and then
delete all marker files.
There are a few internal variables that can be set during
configuration to enable various checks (and other features) on the
generated spdx files:
- QT_INTERNAL_SBOM_VERIFY
- QT_INTERNAL_SBOM_AUDIT
- QT_INTERNAL_SBOM_AUDIT_NO_ERROR
- QT_INTERNAL_SBOM_GENERATE_JSON
- QT_INTERNAL_SBOM_SHOW_TABLE
- QT_INTERNAL_SBOM_DEFAULT_CHECKS
These use 3rd party python tools, so they are not enabled by default.
If enabled, they run at installation time after the sbom is installed.
We will hopefully enable them in CI.
Overall, the code is still a bit messy in a few places, due to time
constraints, but can be improved later.
Some possible TODOs for the future:
- Do we need to handle 3rd party libs linked into a Qt static library
in a Qt shared build, where the Qt static lib is not installed, but
linked into a Qt shared library, somehow specially?
We can record a package for it, but we can't
create a spdx file record for it (and associated source
relationships) because we don't install the file, and spdx requires
the file to be installed and checksummed. Perhaps we can consider
adding some free-form text snippet to the package itself?
- Do we want to add parsing of .cpp source files for Copyrights, to
embed them into the packages? This will likely slow down
configuration quite a bit.
- Currently sbom info attached to WrapFoo packages in one repo is
not exported / available in other repos. E.g. If we annotate
WrapZLIB in qtbase with CPE_VENDOR zlib, this info will not be
available when looking up WrapZLIB in qtimageformats.
This is because they are IMPORTED libraries, and are not
exported. We might want to record this info in the future.
[ChangeLog][Build System] A new -sbom configure option can be used
to generate and install a SPDX SBOM (Software Bill of Materials) file
for each built Qt repository.
Pick-to: 6.8
Task-number: QTBUG-122899
Change-Id: I9c730a6bbc47e02ce1836fccf00a14ec8eb1a5f4
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Due to QTBUG-125371 we currently record Qt6 as a third party
dependency for many qt packages.
Until that is fixed, we should not record the provided targets of the
Qt6 package, because it causes issues during SBOM generation.
Amends 58eefbd0b6169d0749b312268c1ae1e594e04362
Task-number: QTBUG-125371
Change-Id: I35d548996c3820aaa7a1175b3a1f34c23ec2290f
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Each qt_find_package can specify a PROVIDED_TARGETS option, to inform
which targets will be created by that package.
The call then saves the package name, version, etc on each of the
provided targets.
Currently the provided targets info is not persisted anywhere after
configuration ends.
We will need this for SBOM creation, so that we can collect
information about such dependencies when configuring leaf
repos, where find_dependency calls are implicit, and don't contain
the PROVIDED_TARGETS option, and we need to go from package name to
target name (and any recorded info it the target has).
This is especially relevant for static library builds, where private
dependencies become public dependencies.
Collect the provided targets information at post process time and
persist it for each 'package name + components requested' combination
into the Dependencies.cmake file.
This information will be used in a later change for SBOM generation.
Change-Id: I1693f81b1ad3beaf9b02e44b09a5e977923f0d85
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
The QtFindWrapHelper include used in FindWrap scripts can choose to
call find_package() on one of two packages. The packages might set a
VERSION variable. We should set the same version for the FindWrap
package as well.
There are two sources where the version will be queried from. First
from the underlying ${package_name}_VERSION variable.
And if that is empty, from a property that is set by qt_find_package()
The former might be empty because find_package might be called from
a function instead of a macro, which is the case for any find_package
call in configure.cmake files that get loaded by the
qt_feature_evaluate_features function.
Thus we need the indirection via the property that qt_find_package
will set.
Change-Id: I57fd818cb9dedf5e27a6d805e3d817d8d18be36d
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Replace Qt:: namespace with Qt6:: namespace in target_link_libraries
for the Qt modules/plugins/libraries.
Fixes: QTBUG-114706
Change-Id: Idfd0917dbe1a6a266bc4e9d5f465e550788b5aaf
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
When configuring Qt the second time it might be situation that
the set of qt_find_package calls is changed. One of the scenarios
is the changing of the submodule list that needs to be built in
top-level builds. It's also applicable for Qt features that lead to
extra package lookup in the unlocked subdirectories. Current approach
collects packages that were found at the previous run and skips
search of the packages that are missing. The problem is that
it also skips packages even if qt_find_package was not called at
previous run. QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES collects
all packages that were actually searched at the previous run
to make sure that qt_find_package don't skip packages that
appeared at second run only.
Note: Described scenarios may still have other issues and are not
tested well.
Fixes: QTBUG-113244
Pick-to: 6.5
Change-Id: Iab36060a28fbaa16a3b3bdba67795955c496b0c3
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Amir Masoud Abdol <amir.abdol@qt.io>
For -developer-buildS qt_find_package caches which packages were found
on the first configuration, to make the build system pick up a newly
added qt_find_package call one needs to follow one of the methods
that are now mentioned in the docs.
Hugely based on commit message from commit
6847a19e3edc76cce6ca0f0c25e520db591cedb9.
Change-Id: I4a13d3c97a6172f504a57298c4b3edee30d21250
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This reverts commit 545400addd7935c87ec79596ac3010b4f9016a84.
Reason for revert: Adding NO_CMAKE_PACKAGE_REGISTRY doesn't resolve the initial issue. So reverting this change as redundant.
Change-Id: I284600d6f0e0f2408a7a8b31827251dad4c73eba
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Allow forwarding the NO_CMAKE_PACKAGE_REGISTRY option to the
find_package call from qt_find_package.
When we look for host tool packages the package dependencies are
recorded in the cmake package registry. This leads to the situation
when the lookup retry will use the package that is already found in
host path instead of looking the right one in target paths.
Adding the 'NO_CMAKE_PACKAGE_REGISTRY' to the qt_find_package calls
suppresses records in cmake package registry and starts a clean search
using target paths.
Task-number: QTBUG-111140
Pick-to: 6.5
Change-Id: I97ce1755b2f8e3413f1b0276fe26568b2f5efe33
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Instead of constantly trying to find packages by calling
qt_find_package on each reconfiguration, record which packages were
found during initial configuration. Then on a second reconfiguration,
skip looking for packages that were not found on the initial
configuration.
This speeds up reconfiguration on certain platforms and repos.
Here are some stats for my macOS qtbase build.
not skip 3.69s user 4.96s system 98% cpu 8.750 total
skip 2.69s user 1.00s system 97% cpu 3.792 total
Top-level build with -submodules=qtquick3d
not skip 15.03s user 10.58s system 97% cpu 26.334 total
skip 13.87s user 5.16s system 96% cpu 19.724 total
Note this is a behavior change from how find_package is used in most
CMake projects, where if a package was previously missing, the
developer can just install the package and reconfigure to pick it up.
With this change, they will first have to remove their CMakeCache.txt
file and configure from scratch, or remove the
QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES cache variable and reconfigure.
For this reason, we enable this behavior by default only in
-developer-builds.
Builders can also opt in or out by setting the
QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES variable to either ON or
OFF.
Note this behavior does not apply to user projects, or direct
find_package calls (as opposed to qt_find_package).
Fixes: QTBUG-107251
Change-Id: Iee9c5d120eb09e2a94eebb059a2174ef6b241e03
Reviewed-by: Kai Köhne <kai.koehne@qt.io>
Reviewed-by: Amir Masoud Abdol <amir.abdol@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
CMakeLists.txt and .cmake files of significant size
(more than 2 lines according to our check in tst_license.pl)
now have the copyright and license header.
Existing copyright statements remain intact
Task-number: QTBUG-88621
Change-Id: I3b98cdc55ead806ec81ce09af9271f9b95af97fa
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
Add PlatformCommonInternal to the list of packages
compared in qt_internal_is_lib_part_of_qt6_package
It gets rid of the following warnings when configuring
standalone tests
CMake Warning at cmake/QtFindPackageHelpers.cmake:406 (message):
Could not find target Qt6::PlatformCommonInternal to query its
package name. Defaulting to package name Qt6PlatformCommonInternal.
Consider re-arranging the project structure to ensure the target
exists by this point.
CMake Warning at cmake/QtFindPackageHelpers.cmake:374 (message):
Could not determine package version of target
PlatformCommonInternal. Defaulting to project version 6.5.0.
Amends 606124c5cceba0dd4a406a9278588b58bb9f9800
Amends dd1030a4501ca067e96f50085c8cfda19d85afd4
Amends dffcc2370e43722afb25d7aec7cd9d6a36f61e03
Pick-to: 6.4
Task-number: QTBUG-104998
Change-Id: I65c23c20b3c1b70dbfd54edd4f5b83c6781f5e6f
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Previously if a target depended on CorePrivate, we would write a
_qt_internal_find_qt_dependencies(... Qt6CorePrivate) call into a
FooDependencies.cmake file.
That find_qt_deps call would remove the 'Private' suffix and would run
find_dependency with NAMES set to both the altered and non-altered
names.
This would find the relevant package but it would set the wrong
_FOUND variable name, e.g it would set Qt6CorePrivate_FOUND instead
of Qt6Core_FOUND.
This in turn could cause multiple lookups of the Qt6Core package
during dependency handling because the correct _FOUND var would not be
set.
Instead of always looking for the Qt6CorePrivate package, make sure
we look for an appropriately named package for all Privates modules,
because we have the necessary info to determine the correct name.
Note that INTERNAL modules will still be looked up via a Private
suffixed package name because that's how the package name is chosen
for them.
Remove the code that accounted for Private modules in
qt_internal_remove_qt_dependency_duplicates because it's not needed
anymore.
Warn when a package name can't be queried from a target's property
because the target might not exist yet.
Add a TODO comment for the code that searches with two NAMES.
We can't remove it right now, because it might break user projects
that use stale Dependencies.cmake files.
The dbus subdirectory is added before the tools subdirectory
to ensure that the new package name extraction does not error out, due
to trying to access a target that does not yet exist.
Amends 425ff34aa10a02524f2d52f544dc00b539ef9a26
Pick-to: 6.4
Task-number: QTBUG-104998
Change-Id: Ib34ae5ed92f68b4265518c2b8802daeb1a3a04d6
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
When recording which package version to look for in
QtFooModuleDependencies.cmake and other files like it,
instead of using PROJECT_VERSION, use the version of the
package that contains the dependency.
For example if we're hypothetically building the qtdeclarative repo
from the 6.4 branch, against an installed 6.2 qtbase, then
the Qt6QmlModuleDependencies.cmake file will have a
find_package(Qt6Core 6.2) call because qtdeclarative's
find_package(Qt6Core) call found a 6.2 Core when it was configured.
This allows switching the versioning scheme of specific Qt modules
that might not want to follow the general Qt versioning scheme.
The first candidate would be QtWebEngine which might want to
follow the Chromium versioning scheme, something like
Qt 6.94.0 where 94 is the Chromium major version.
Implementation notes.
We now record the package version of a target in a property
called _qt_package_version. We do it for qt modules, plugins,
3rd party libraries, tools and the Platform target.
When we try to look up which version to write into the
QtFooModuleDependencies.cmake file (or the equivalent Plugins and
Tools file), we try to find the version
from a few sources: the property mentioned above, then the
Qt6{target}_VERSION variable, and finally PROJECT_VERSION.
In the latter case, we issue a warning because technically that should
never have to happen, and it's a bug or an unforeseen case if it does.
A few more places also need adjustments:
- package versions to look for when configuring standalone
tests and generating standalone tests Config files
- handling of tools packages
- The main Qt6 package lookup in each Dependencies.cmake files
Note that there are some requirements and consequences in case a
module wants to use a different versioning scheme like 6.94.0.
Requirements.
- The root CMakeLists.txt file needs to call find_package with a
version different from the usual PROJECT_VERSION. Ideally it
should look for a few different Qt versions which are known to be
compatible, for example the last stable and LTS versions, or just
the lowest supported Qt version, e.g. 6.2.6 or whenever this change
would land in the 6.2 branch.
- If the repository has multiple modules, some of which need to
follow the Qt versioning scheme and some not,
project(VERSION x.y.z) calls need to be carefully placed in
subdirectory scopes with appropriate version numbers, so that
qt_internal_add_module / _tool / _plugin pick up the correct
version.
Consequences.
- The .so / .dylib names will contain the new version, e.g. .so.6.94
- Linux ELF symbols will contain the new versions
- syncqt private headers will now exist under a
include/QtFoo/6.94.0/QtFoo/private folder
- pri and prl files will also contain the new version numbers
- pkg-config .pc files contain the new version numbers
- It won't be possible to write
find_package(Qt6 6.94 COMPONENTS WebEngineWidgets) in user code.
One would have to write find_package(Qt6WebEngineWidgets 6.94)
otherwise CMake will try to look for Qt6Config 6.94 which won't
exist.
- Similarly, a
find_package(Qt6 6.4 COMPONENTS Widgets WebEngineWidgets) call
would always find any kind of WebEngine package that is higher than
6.4, which might be 6.94, 6.95, etc.
- In the future, if we fix Qt6Config to pass EXACT to its
subcomponent find_package calls,
a find_package(Qt6 6.5.0 EXACT COMPONENTS Widgets WebEngineWidgets)
would fail to find WebEngineWidgets, because its 6.94.0 version
will not be equal to 6.5.0. Currently we don't pass through EXACT,
so it's not an issue.
Augments 5ffc744b791a114a3180a425dd26e298f7399955
Task-number: QTBUG-103500
Change-Id: I8bdb56bfcbc7f7f6484d1e56651ffc993fd30bab
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
The previous implementation would pick up static Qt deps of a
shared Qt library as packages to find, but packages are not
created for these static libraries in a shared Qt build.
For example Qt::BundledSpirv_Cross is a static helper lib
that is linked directly into ShaderTools shared lib and no CMake
package is created for it, so we shouldn't look for it.
Separate the code path to filter out private dependencies
of a shared library target that don't have packages.
Amends 87215c70c0ff0bdc52dfa463f050d2aa049cdd91
Pick-to: 6.2
Fixes: QTBUG-97673
Task-number: QTBUG-86533
Change-Id: I43490b4d20c150256ccfa8b511a6e0e6b0f4b313
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Private Qt module dependencies of a Qt module are recorded
in the IMPORTED_LINK_DEPENDENT_LIBRARIES property of a Qt module.
This property is used to compute the runtime dependency dir path
to be passed to the linker via the -rpath-link option.
If the referenced target does not exist in the scope where it's
used, no -rpath-link will be generated (or at least that specific
dir path won't be passed).
The linking operation will either fail saying the library is not found,
or a different version of the library might be silently picked up in
the sysroot or other implicit lib dir.
Make sure that QtFooModuleDependencies.cmake calls find_package() for
all Qt module private dependencies (or other Qt provided 3rd party
libs in the Qt6:: namespace) so that the targets are in scope and
IMPORTED_LINK_DEPENDENT_LIBRARIES does its job.
qmake also records the INTERFACE_LINK_LIBRARIES of a private Qt module
as the runtime dependencies of the module.
It's not clear why it does that. A private Qt module is an
INTERFACE_LIBRARY so it shouldn't add any new runtime dependencies.
Nevertheless, the find_package part of that has been recently addressed
in 2b6500cd15c0a41cf3e5eea8178e2044012dbd97 for a different reason.
This change is basically the CMake equivalent of
326b91ea788b013512ae911c51cc19497d88916d
Pick-to: 6.2
Fixes: QTBUG-86533
Change-Id: Iaf514a14acaded4e8752149cca0c159a271be188
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
When CMP00126 is set to NEW, set(CACHE) doesn't remove regular
variable bindings with the same name as the cache variable.
This introduced an issue in qt_find_package, which called
find_package(CONFIG QUIET) to try and find a package config file, but
did not clean up the non-cache _FOUND variable which is automatically
set to 0 by CMake if no Config file is found.
Make sure to unset both the regular and cache _FOUND variables if either
the package config file was not found, or if none of the provided
targets found even if the Config file was found.
Also move the _DIR cache variable cleaning into the same code block.
Amends 4c31ce68d5367a6ec4dd3cf2f55e4b226add876d
Amends 34b1c1c23cbddf67f878579bee9d10dcac29d8ca
Fixes: QTBUG-95635
Pick-to: 6.2
Change-Id: I871987217526e0f0a20038a8da52625838e49488
Reviewed-by: Craig Scott <craig.scott@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
If Vulkan headers are present on the system when qtbase is configured,
QtGui and QtOpenGL should be compiled with Vulkan support.
If a user project uses a Qt built with Vulkan support, but their system
is missing Vulkan headers, the project configuration needs to succeed.
The project will get compilation errors if it uses Vulkan headers, but
that's intended.
This use case was broken when fixing Vulkan to be found when building
Qt for Android.
Fix the regression with a combination of things
1) Mark the WrapVulkanHeaders package as optional (already the case)
2) Use the include directories directly when compiling Gui and OpenGL
3) Propagate WrapVulkanHeaders::WrapVulkanHeaders link requirement to
consumers only if the target exists. It won't exist if Vulkan
include dirs are not found
This also requires some changes in pri and prl file generation.
For prl file generation, we don't want to link to the
WrapVulkanHeaders target, so we filter out all dependencies that
use TARGET_NAME_IF_EXISTS for anything that calls
__qt_internal_walk_libs which includes qt_collect_libs.
For pri files, we make sure to generate a uses=vulkan/nolink clause
by inspecting a new _qt_is_nolink_target property on the target.
We also don't add include dirs to the pri file if the new
_qt_skip_include_dir_for_pri property is set.
This is intended for Vulkan, because there is separate qmake logic to
try and find the include dirs when configuring a user project.
As a drive-by, fix nolink handling for WrapOpenSSLHeaders.
Amends bb25536a3db657b41ae31e1690d230ef8722b57d
Amends 7b9904849fe1a43f0db8216076a9e974ebca5c78
Pick-to: 6.2
Fixes: QTBUG-95391
Change-Id: I21e2f4be5c386f9e40033e4691f4786a91ba0e2d
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
The optional components arguments were not handled before which
caused the recorded package information for static builds to be
incorrect, it only recorded the package name without the component.
Remove REQUIRED_COMPONENTS TODO, there is no such find_package option,
it's already handled by the regular COMPONENTS code path.
Amends 07b6d3367debd8f15974abf0f5cdf48f0fe3a536
Pick-to: 6.1 6.2
Fixes: QTBUG-94501
Change-Id: Ib48a7befcb70e20c3f21315897d51d3064b48134
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Dominik Holland <dominik.holland@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
User projects can set the QT_PROMOTE_TO_GLOBAL_TARGETS variable to
true so that the various imported targets created by find_package(Qt6)
are promoted to global targets.
This would allow a project to find Qt packages in a subdirectory scope
while using those Qt targets from a different scope.
E.g. it fixes errors like
CMake Error at CMakeLists.txt:5 (target_link_libraries):
Error evaluating generator expression:
$<TARGET_OBJECTS:Qt6::Widgets_resources_1>
Objects of target "Qt6::Widgets_resources_1" referenced but no such
target exists.
when trying to use a static Qt from a sibling scope.
Various 3rd party dependency targets (like Atomic or ZLIB) are not
made global due to limitations in CMake, but as long as those targets
are not mentioned directly, it shouldn't cause issues.
The targets are made global in the generated
QtFooAdditionalTargetInfo.cmake file.
To ensure that resource object libraries promoted, the generation
of the file has to be done at the end of the defining scope
where qt_internal_export_additional_targets_file is called,
which is achieved with a deferred finalizer.
Replaced all occurrences of target promotion with a helper function
which allows tracing of all promoted targets by specifying
--log-level=debug to CMake.
Pick-to: 6.2
Fixes: QTBUG-92878
Change-Id: Ic4ec03b0bc383d7e591a58c520c3974fbea746d2
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This makes qt_internal_disable_find_package_global_promotion available,
which is needed when linking against QtMultimedia in a static build
Pick-to: 6.2
Change-Id: I9b8f6d7b74a8693ac471f8a280e893f4da80a44b
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
In the future it might be useful to print the config summary entries
of a Qt module configure.cmake file even if the associated module
is not built and thus qt_feature_module_begin is not called.
The repo src/CMakeLists.txt could then use a combination of
qt_feature_evaluate_features and a conditional
qt_feature_record_summary_entries to ensure the that summary entries
are still shown.
Change-Id: I124efc82163ddae48d9e72c70a677ec4c6588fac
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
In cmake, targets are used as an entity for modules. This causes a
number of problems when we want to manipulate a module as a separate
entity with properties associated with it.
The _qt_internal_module_interface_name target property is introduced to
represent the module entity. All modules write a name to this property,
which will subsequently expand into the module name matched with
the module name in qmake.
The 'qt_internal_module_info' function is responsible for providing the
correct values for the module properties used when working with a module
target.
Unlike qmake, for internal modules in cmake it is expected that the
Private suffix will be specified explicitly. In case the user wants to
have a different module name, an additional argument
MODULE_INTERFACE_NAME of the qt_internal_add_module function is
introduced.
This also changes the way how target dependencies are collected and
resolved. Since the 'Private' suffix no longer means an unique
identifier of the module 'Private' part, we look for the both Private
and non-Private package names when resolving dependencies.
TODO: This change doesn't affect the existing internal modules, so to
keep compatibility with the existing code the existing internal modules
create 'Private' aliases. The code that provides backward compatibility
must be removed once all internal modules will get the proper names.
Taks-number: QTBUG-87775
Change-Id: Ib4f28341506fb2e73eee960a709e24c42bbcd5ec
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Needed for the upcoming static plugin mechanism, where we have to
extract the list of Qt module dependencies of a target and then extract
the plugins associated with those modules.
To do that we need to recursively collect the dependencies of a given
target.
Rename the moved functions to contain the __qt_internal prefix.
Also rename the existing QtPublicTargetsHelpers.cmake into
QtPlatformTargetHelpers.cmake to avoid confusion with the newly
introduced QtPublicTargetHelpers.cmake.
Task-number: QTBUG-92933
Change-Id: I48b5b6a8718a3424f59ca60f11fc9e97a809765d
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
The qt_internal_module_info function suppose to provide the information
only about the Qt modules. Avoid using it for the tool and extra
package dependencies, since some targets do not always exist, when
function is called.
Add the qt_internal_qtfy_target function to make the prefixed target
names.
Change-Id: Ifa8c61064d9c6c430889f00a4ead304029da711b
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Those entries were always empty. The INTERFACE_QT_MODULE_USES property
was never set.
Map each public dependency to its qmake lib name and place this value
into the module's QT.<module-name>.uses variable.
Take into account the "_nolink" target modifier and translate it to
qmake's "/nolink".
Pick-to: 6.0
Fixes: QTBUG-88951
Change-Id: Ib6ef65b842a1fe1da3ade55867583343b4ee76ee
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Rename QT_QMAKE_LIB_TARGETS_foo to QT_TARGETS_OF_QMAKE_LIB_foo, because
we want to introduce the counterpart QT_QMAKE_LIB_OF_TARGET_bar in a
subsequent commit.
Pick-to: 6.0
Task-number: QTBUG-88951
Change-Id: I33f00f4fe65c5977da6e74c632ebeab3b891c89a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
The CMake build of Qt intends to improve the developer experience in
regards to static Qt builds and Qt resource files. Specifically with a
CMake build of Qt, Qt developers don't have to manually call
Q_INIT_RESOURCE anymore.
For details see the following commits
e343affd6345ef8db041789a96016c3a84830dc9
e817ac3d68295fc0670ccede4df08bf1c7e627d2
4ab54320817ebbb465af343514d21139a654aed3
The last commit's implementation is incomplete though.
To ensure successful linking, each target's prl file should contain
not only the resource object files that are assigned to the target,
but also all resource object files of the target's dependencies.
To achieve that, qt_collect_libs will now recursively collect all
resource object files assigned to the QT_RCC_OBJECTS property of each
dependency.
Note this implementation is still incomplete. We do not export rcc
object file information in the CMake Targets files.
That means that when configuring qtdeclarative in a
non-top-level build, the generated Qml prl file will not
contain references to Core's mimetypes resource object file, etc.
So with the current change, only the object files that are part of the
current CMake configuration build are tracked.
Exporting the resource object files locations proves in a format
usable for prl files proves to be difficult (due to CMake not
supporting exporting genexes in random properties) and will have to be
addressed in a separate change.
Amends 4ab54320817ebbb465af343514d21139a654aed3
Task-number: QTBUG-88425
Change-Id: I546655bdfdf7aa86a8df9aadfc054fa415130a33
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
The use-case is relevant for other platforms as well.
Now that Qt has a module system we can also replace a lot of the
hand crafted logic for linking with simpler constructs.
Change-Id: Ib6853aaf81bfea79c31f2de741d65b4b56f23ef6
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Introduce a bunch of helper functions to manipulate compiler
flags and linker flags for the
CMAKE_<LANG>_FLAGS_<CONFIG>
and
CMAKE_<LINK_TYPE>_LINKER_FLAGS_<CONFIG>
CMake variables.
These variables can be assigned and modified either in the cache
or for a specific subdirectory scope, which will apply the flags
only to targets in that scope.
Add qt_internal_add_optimize_full_flags() function which mimics
qmake's CONFIG += optimize_full behavior.
Calling it will force usage of the '-O3' optimization flag on supported
platforms (falling back '-O2' where not supported).
Use the function for the Core and Gui subdirectories, to enable full
optimization for the respective Qt modules as it is done in the qmake
projects.
To ensure that the global qmake-like compiler flags are assigned
eveywhere,
qt_internal_set_up_config_optimizations_like_in_qmake() needs
to be called after Qt global features like optimize_size and
optimize_full are available.
This means that qtbase and its standalone tests need some special
handling in regards to when to call that function.
Task-number: QTBUG-86866
Change-Id: Ic7ac23de0265561cb06a0ba55089b6c0d3347441
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This reverts commit b0c51f86f40b6b6d18fe2bb75cc851d36395240d.
The build failure caused by 58c1c6ee5c986d502b56eb1cc57f1d9444d42031 has
been fixed.
Change-Id: Ic7458d54c7a874588e8b1bfeca61df1842763656
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This reverts commit 3685483c4b79b4075bab6d341174a395359d1b4a.
This lead to configuration errors on some machines, blocking
development.
Change-Id: I309cdd55a8ef64899afcbeca54458d1c6d686951
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Every public dependency of a Qt module results in a find_package call in
the consuming project. But not all public dependencies are mandatory.
For example, vulkan is only needed if the user project actually uses Qt
classes that pull in vulkan headers.
This patch adds the option MARK_OPTIONAL to qt_find_package.
Dependencies that are marked as optional will not produce an error on
find failure.
Task-number: QTBUG-86421
Change-Id: Ia767e7f36991e236582c7509cbd37ea3487bb695
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This is needed for qtwayland, where QtWaylandCompositor package should
call find_package(QtWaylandScanner) in the 'Tools' section of the
ModuleDependencies.cmake file, rather than the regular 'Qt' section.
This takes care of handling host path prefixes, to ensure that a host
package is found even when tools have also been cross-compiled via the
QT_BUILD_TOOLS_WHEN_CROSSCOMPILING option.
Task-number: QTBUG-83968
Change-Id: I4725a630214d053105fb6d2a0f7c5ff6128d13f9
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
qt_record_extra_package_dependency is called by qtwayland to register a
dependency between the qtwaylandscanner tool and the waylandscanner
tool.
When cross-compiling the tools in a Yocto environment, the adjusted
target name was not taken into account.
Task-number: QTBUG-83968
Change-Id: Ibf7b94876bf29827cf0d9c9bb471f359ef6ff15f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
QtBuild.cmake is huge. Split it.
Move module, plugin, tools, executables and test related functions out
of QtBuild.cmake into separate files.
Do the same for many other things too.
An additional requirement is that all the new Helpers files only
define functions and macros.
No global variable definitions are allowed, nor execution of commands
with side effects.
Some notes:
qt_install_qml_files is removed because it's dead code.
Some functions still need to be figured out, because they are
interspersed and depend on various global state assignments.
Task-number: QTBUG-86035
Change-Id: I21d79ff02eef923c202eb1000422888727cb0e2c
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>