Build system (5 gaps hardened): - COOKBOOK_OFFLINE defaults to true (fork-mode) - normalize_patch handles diff -ruN format - New 'repo validate-patches' command (25/25 relibc patches) - 14 patched Qt/Wayland/display recipes added to protected list - relibc archive regenerated with current patch chain Boot fixes (fixable): - Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset) - D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped) - redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped) - daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch) - udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async) - relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs - greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait) - greeter-ui: built and linked (header guard unification, sem_compat stubs removed) - mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps - greeter config: removed stale keymapd dependency from display/greeter services - prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified Unfixable (diagnosed, upstream): - i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort - kded6/greeter-ui: page fault 0x8 — Qt library null deref - Thread panics fd != -1 — Rust std library on Redox - DHCP timeout / eth0 MAC — QEMU user-mode networking - hwrngd/thermald — no hardware RNG/thermal in VM - live preload allocation — BIOS memory fragmentation, continues on demand
6.9 KiB
Unofficial Qt CMake Coding Style
CMake scripts are a bit of a wild west. Depending on when the code was written, there were different conventions as well as syntax facilities available. It's also unfortunate that there is no agreed upon CMake code formatter similar to clang-format. https://github.com/cheshirekow/cmake_format exists, but appears abandoned. We might look into using it at some point.
It's hard to convince people to use a certain code style for a language like CMake.
Nevertheless this short document aims to be a guideline for formatting CMake code within the Qt project.
Common conventions
- When in doubt, prefer the local code conventions of the function or file you are editing.
- Prefer functions over macros (macros have certain problems with parameter escaping)
- Prefix macro local variables to avoid naming collisions
Case Styles
For CMake identifiers we refer to following case styles in the text below.
| Case style name | Example identifier |
|---|---|
| Snake case | moc_options |
| Shouty case | INTERFACE_LINK_LIBRARIES |
| Pascal case | QmlModels |
Indentation
- When in doubt, follow local indentation
- Prefer indenting with 4 spaces, e.g.
if(1)
if(2)
message("3")
endif()
endif()
Variables
- local variables inside a function should be snake cased =>
list_of_arguments - local variables inside a macro should be snake cased and have a unique prefix =>
__qt_list_of_packages- If your macro is recursively called, you might need to prepend a dynamically computed prefix
to avoid overriding the same variable in nested calls =>
__qt_${dependency_name}_list_of_packages
- If your macro is recursively called, you might need to prepend a dynamically computed prefix
to avoid overriding the same variable in nested calls =>
- cache variables should be shouty cased =>
BUILD_SHARED_LIBS- Qt cache variables should be prefixed with
QT_
- Qt cache variables should be prefixed with
Properties
Currently the Qt property naming is a bit of a mess. The upstream issue
https://gitlab.kitware.com/cmake/cmake/-/issues/19261 mentions that properties prefixed with
INTERFACE_ are reserved for CMake use.
Prefer to use snake case for new property names.
- Most upstream CMake properties are shouty cased =>
INTERFACE_LINK_LIBRARIES - Properties created in Qt 5 times follow the same CMake convention =>
QT_ENABLED_PUBLIC_FEATURESNo such new properties should be added. - New Qt properties should be snake cased and prefixed with
qt_=>qt_qmake_module_name - Other internal Qt properties should be snake cased and prefixed with
_qt_=>_qt_target_deps
Functions
- Function names should be snake cased =>
qt_add_module- public Qt functions should be prefixed with
qt_ - internal Qt functions should be prefixed with
qt_internal_ - internal Qt functions that live in public CMake API files should be prefixed with
_qt_internal_ - some internal functions that live in public CMake API files are prefixed with
__qt_internal_, prefer not to introduce such functions for now
- public Qt functions should be prefixed with
- If a public function takes more than 1 parameter, consider using
cmake_parse_arguments - If an internal Qt function takes more than 1 parameter, consider using
qt_parse_all_arguments - Public functions should usually have both a version-full and version-less name =>
qt_add_pluginandqt6_add_plugin
Macros
- Try to avoid macros where a function can be used instead
- A common case when a macro can not be avoided is when it wraps a CMake macro e.g
find_package=>qt_find_package
- A common case when a macro can not be avoided is when it wraps a CMake macro e.g
- Macro names should be snake cased =>
qt_find_package - Prefix macro local variables to avoid naming collisions =>
__qt_find_package_arguments
Commands
Command names in CMake are case-insensitive, therefore:
- Only use lower case command names e.g
add_executable(app main.cpp)notADD_EXECUTABLE(app main.cpp) - Command flags / options are usually shouty cased =>
file(GENERATE OUTPUT "foo" CONTENT "bar")
'If' command
-
Keep the parenthesis next to the
if(), so don't writeif ().ifis a command name and like other command names e.g.find_package(foo bar)the parenethesis are next to the name. -
To check that a variable is an empty string (and not just a falsy value, think Javascript's
foo === "") use the following snippet
if(var_name STREQUAL "")
message("${var_name}")
endif()
If you are not sure if the variable is defined, make sure to evaluate the variable name
if("${var_name}" STREQUAL "")
message("${var_name}")
endif()
- Falsy values are
0,OFF,NO,FALSE,N,IGNORE,NOTFOUND, the empty string"", or a string ending in-NOTFOUND. To check that a variable is NOT falsy use the first suggested code snippet
# Nice and clean
if(var_name)
message("${var_name}")
endif()
# Wrong, can lead to problems due to double variable evaluation
if(${var_name})
message("${var_name}")
endif()
# Incorrect if you want to check for all falsy values. This only checks for string emptiness.
if("${var_name}" STREQUAL "")
message("${var_name}")
endif()
- To check if a variable is defined, use
if(DEFINED var_name)
endif()
- To compare a defined variable's contents to a string, use
if(var_name STREQUAL "my_string")
endif()
- To compare a defined variable's contents to another defined variable's contents, use
if(var_name STREQUAL var_name_2)
endif()
- To compare a possibly undefined variable make sure to explicitly evaluate it first
if("${var_name}" STREQUAL "my_string")
endif()
if("${var_name}" STREQUAL "${var_name_2}")
endif()
find_package
- Inside Qt module projects, use the private Qt-specific
qt_find_packagemacro to look for dependencies.- Make sure to specify the
PROVIDED_TARGETSoption to properly register 3rd party target dependencies with Qt's internal build system.
- Make sure to specify the
- Inside examples / projects (which only use public CMake API) use the regular
find_packagecommand.
CMake Target names
- Qt target names should be pascal cased =>
QuickParticles. - When Qt is installed, the Qt CMake targets are put inside the
Qt6::namespace. Associated versionless targets in theQt::namespace are usually automatically created by appropriate functions (qt_internal_add_module,qt_internal_add_tool) - Wrapper 3rd party system libraries usually repeat the target name as the namespace e.g.
WrapSystemHarfbuzz::WrapSystemHarfbuzz
Finding 3rd party libraries via Find modules (FindWrapFoo.cmake)
qmake-Qt uses configure.json and configure.pri and QT_LIBS_FOO variables to implement a
mechnism that searches for system 3rd party libraries.
The equivalent CMake mechanism are Find modules (and CMake package Config files; not to be confused with pkg-config). Usually Qt provides wrapper Find modules that use any available upstream Find modules or Config package files.
The naming convention for the files are:
FindWrapFoo.cmake=>FindWrapPCRE2.cmakeFindWrapSystemFoo.cmake=>FindWrapSystemPCRE2.cmake