CMake 3.31 introduced the policy CMP0174 that triggers a warning if a
single-value argument is passed to a function without a value.
We did this doing this when forwarding arguments in code that doesn't
use _qt_internal_forward_function_args yet, e.g. in qt_internal_add_app:
qt_internal_add_executable(...
TARGET_PRODUCT ${arg_TARGET_PRODUCT}
...)
Forward the warning-triggering arguments with
_qt_internal_forward_function_args now, because that only forwards used
arguments.
In the future, we can offload more forwarding work to the
_qt_internal_forward_function_args command and simplify the forwarding
code in qt_internal_add_app and qt_internal_add_tool. This patch only
fixes the worst offenders for now.
Pick-to: 6.8
Change-Id: Ie786691e4b236decf4c62f4dd0751ed76b721177
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This complements commit 30e04340dac26ebd09f9bc8ceb598e873ab63ba7
("Switch to non-strict C++ builds so QT_SUPPORTS_INT128 is true") and
adds the same modification to tools and apps.
Otherwise qtconnectivity's sdspscanner won't compile, as it needs
quint128.
Task-number: QTBUG-119901
Pick-to: 6.8
Change-Id: Ib9a6fe573e9420a471fdfffd76a2e43d3c5496d8
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Previously, only a very short subset of options related to attribution
files could be specified to qt_internal_add_module /
qt_internal_extend_target.
It is more convenient to allow specifying most (safe) options, instead
of calling another function.
Unsafe are considered paths like INSTALL_PATH and derivatives, TYPE
which is too generic, and some other ones like LIBRARIES which would
be duplicated, and causes warnings in cmake_parse_arguments if
duplicated.
Change the code to allow specifying most SBOM options and forwarding
them to _qt_internal_extend_sbom.
Pick-to: 6.8
Task-number: QTBUG-122899
Change-Id: I6eb723e165edf59973d83c66eace43acdce237de
Reviewed-by: Joerg Bornemann <joerg.bornemann@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>
The new approach allows to imply the macro definitions for every Qt
submodule and user project without the need of setting it explicitly
from CMake. This also prevent users from introducing the
incompatibility between Qt modules due to defining
the QT_DISABLE_DEPRECATED_UP_TO version lower than qtbase was built
with.
Task-number: QTBUG-124765
Change-Id: I7ba481f62cb9073ae0343c400ffc26f239f080f1
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
The former implies the latter, so it makes little sense to treat them
differently. Even if some types of targets are (currently) never
compiled with PCH, users of qt_internal_all_x() shouldn't need to know
such details.
Pick-to: 6.6 6.5
Change-Id: I8ead238a8d9e55da632b2929638b67724a42d73c
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
As I was investigating the NO_UNITY_BUILD_SOURCES issue, I realized that
we don't need to pass these quoted, especially now that we have moved
to `cmake_parse_arguments(PARSE_ARGV`, and we can check their existence
just by checking the `arg_*`, and that should be sufficient.
I also left a warning that we are aware of this.
Pick-to: 6.5
Change-Id: I4d939e80dc4671ea3ae9dc61516279f69ba2c5a5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This replaces the qt_parse_all_arguments macro with the built-in
`cmake_parse_arguments(PARSE_ARGV`. In addition, a new function,
_qt_internal_validate_all_args_are_parsed, can be used to check whether
any _UNPARSED_ARGUMENTS have been passed to the function.
Fixes: QTBUG-99238
Change-Id: I8cee83dc92dc6acdaaf747ea6ff9084c11dc649b
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
In cross builds, we are not creating versioned links for qt tools. This
patch addresses that. I've changed the signature of the
`qt_internal_install_versioned_link` such that it can be used for
non-target as well, so in cross build the qmake or qtmake.bat can be
processed with the same function.
Fixes: QTBUG-109024
Change-Id: I246621c18325d084622ca92b422e815ed06f1381
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
If Qt itself is built without the deprecated APIs, so should be the
tools and apps.
This patch makes sure that the specified QT_DISABLE_DEPRECATED_UP_TO
and QT_WARN_DEPRECATED_UP_TO values are correctly used in the internal
tools and apps.
Fixes: QTBUG-105102
Change-Id: I7a51bddbd839c7b71efa0bff8ec959df64c53b82
Reviewed-by: Alexandru Croitor <alexandru.croitor@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>
Warn projects not to use it because PUBLIC_LIBRARIES don't make
sense for executable targets and it also led to some issues in the
internal functions where some of them did not expect to receive
PUBLIC_LIBRARIES.
To ensure builds don't needlessly break, treat PUBLIC_LIBRARIES values
as regular LIBRARIES. In the future we might add an error instead.
Using PUBLIC_LIBRARIES in qt_internal_add_app, etc, accidentally
worked because the option name and the values following it were
parsed as values of the "previous" option, like SOURCES or
INCLUDE_DIRECTORIES or LIBRARIES, and when those got
passed through to qt_internal_extend_target, things magically worked.
We have a lot of projects using PUBLIC_LIBRARIES, mostly due to the
way qmake pro files were written and how pro2cmake converted them.
We'll have to clean up each repo.
Change-Id: I69e09d34afdf98f0d47c08d324643fc986f8131c
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
The only place the function was used was to generate the title case of
a target, so the issue wasn't spotted until now.
Pick-to: 6.2 6.3 6.4
Change-Id: Iee66ecea569e7411c6b5a5e5312cde910a48fa01
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
CMake has logic to rewrite build rpaths that contain
CMAKE_STAGING_PREFIX to instead point to CMAKE_INSTALL_PREFIX.
This breaks running executables from the build directory, because
their build rpath will point to a location where the libraries might
not exist yet (we didn't install Qt yet).
Work around this by setting CMAKE_STAGING_PREFIX to a fake path, so
that CMake does not do the rewriting anymore.
CMAKE_STAGING_PREFIX needs to be set at subdirectory scope, not
function scope, which is why
qt_internal_apply_staging_prefix_build_rpath_workaround() is a macro
that is called from within each Qt internal function that creates
a target.
The workaround can be disabled by configuring with
-DQT_NO_STAGING_PREFIX_BUILD_RPATH_WORKAROUND=ON
The downside of this workaround is that it breaks per-subdirectory
install rules like 'ninja src/gui/install'.
Regular global installation like 'ninja install' works fine.
This is similar to what we do for tests in
qt_set_up_fake_standalone_tests_install_prefix()
introduced by 20292250d44e08437306096e9096fc655cc9fb8b
The reason it's not as good for other target types is because in
contrast to tests, we do want to install them.
In case if someone does call `ninja src/gui/install' they will most
likely get a permission error, telling them it's not possible to
install into
/qt_fake_staging_prefix/
check_qt_internal_apply_staging_prefix_build_rpath_workaround
Fixes: QTBUG-102592
Change-Id: I6ce78dde1924a8d830ef5c62808ff674c9639d65
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
Add the possibility to install a Qt app into a directory different from
${INSTALL_BINDIR}.
If INSTALL_DIR is not specified, qt_internal_add_app still installs to
${INSTALL_BINDIR}.
Pick-to: 6.2 6.3
Task-number: QTBUG-99295
Task-number: QTBUG-100047
Change-Id: I52371aa0f770d80c32bb0b3442ce3c463916be63
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
In a -debug-and-release build, apps were placed under bin/Release
rather than just bin.
Apply the logic we use for tools for apps as well. Rename and move
the common functions into QtTargetHelpers.cmake.
Pick-to: 6.2
Fixes: QTBUG-95028
Change-Id: I5a9082ea50c9238c8fcf0c6dd099708fbc571bf8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Add the option argument INSTALL_VERSIONED_LINK to qt_internal_add_tool
and qt_internal_add_app. For tools/apps with this argument we create an
install rule that creates a versioned hard link. For example, for
bin/qmake we create bin/qmake6.
Note that this only applies to prefix builds.
Apply this argument to qmake.
The qt_internal_add_app change is necessary for qtdiag and in qttools.
Task-number: QTBUG-89170
Change-Id: Id32d6055544c475166f4d854aaeb6292fbb5fbb5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
(cherry picked from commit c19d957f45fa27f61b5ecc566f8dbc19f12a44c3)
When packaging different Qt versions for Linux distributions (or any
distribution with a common bin dir), Qt tools cannot be installed to
/usr/bin, because the executable names of the different Qt versions
clash.
To solve this conflict, our recommendation is to install Qt's tools to
/usr/lib/qt6/bin and to create versioned symlinks to user-facing tools
in /usr/bin.
User-facing tools are tools that are supposed to be started manually by
the user. They are marked in Qt's build system. Distro package
maintainers can now configure with
-DCMAKE_INSTALL_PREFIX=/usr
-DINSTALL_BINDIR=/usr/lib/qt6/bin
-DINSTALL_PUBLICBINDIR=/usr/bin
and will find a file called user_facing_tool_links.txt in the build
directory after the cmake run. Nothing will be installed to
INSTALL_PUBLICBINDIR.
Each line of user_facing_tool_links.txt consists of the installation
path of a user-facing application followed by a space and the versioned
link name in INSTALL_PUBLICBINDIR.
Example content:
/usr/lib/qt6/bin/qmake /usr/bin/qmake6
To actually create the versioned symlinks, the content of this file can
be fed to ln like this:
xargs ln -s < build-dir/user_facing_tool_links.txt
Or the package maintainer may decide to do something completely
different as suits their needs.
This patch adds the USER_FACING argument to qt_internal_add_tool to mark
tools as user-facing. In addition, every Qt created by
qt_internal_add_app is treated as user-facing.
The only tool this patch marks as user-facing in qtbase is qmake.
Pick-to: 6.1
Fixes: QTBUG-89170
Change-Id: I52673b1c8d40f40f56a74203065553115e2c4de5
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
In multi-config builds (which equals the debug-and-release feature) we
exclude tools of the non-main configurations from the default build.
But we still create installation rules for them. Mark those as optional
to avoid "cmake --install" yielding errors if those tools weren't built.
Fixes: QTBUG-85411
Change-Id: Ic2d3897d1a1c28a715d9a024ec8606fff00e0315
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Some of them have a different (hopefully better) name now.
Some are marked as Technical Preview.
Some are renamed to be internal.
Marking add_qt_gui_executable as TP with the intention to un-TP it
after we rename it and change its behavior as discussed in the API
review meeting.
Additional changes to add_qt_gui_executable and qt6_add_resources have
been filed as separate tasks that will be worked on separately.
See comments on PS1 for details.
Task-number: QTBUG-86827
Change-Id: I56a84a1943b0902bb807310dc620eb381824e8dd
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Offer compatibility wrapper functions until we update all of the Qt
repos to use the new names.
Task-number: QTBUG-86815
Change-Id: I5826a4116f52a8509db32601ef7c200f9bd331de
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
qt_apply_rpaths takes into account properties like MACOSX_BUNDLE. This
property might not yet be set when qt_internal_add_app is called, but
later.
To handle that, move the call of qt_apply_rpaths to
qt_internal_finalize_app.
As a result, the installed apps will have 2 rpaths, the $ORIGIN style
relocatable one, and an absolute path one pointing to the Qt
prefix/lib. The last one might be unnecessary.
Fixes: QTBUG-86514
Change-Id: I25e0d695c78c8b5703e94c99cc2457f772721456
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
We never passed a valid target name to qt_apply_rpaths.
This amends fde98f77945.
Task-number: QTBUG-85399
Change-Id: I1c023ce30a3a8b5ec43d020373960d19fe20f59a
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
We need to call qt_apply_rpaths for targets that are created with
qt_internal_add_app too. This is in line with what qt_app.prf does.
Task-number: QTBUG-85399
Change-Id: If5ffb05cca191c6cae9a330e1f4556d342a68ff8
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@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>