Crate Organization

CXX-Qt is made up of multiple crates under the crates/ directory.

This page lays out the goal of each crate and how it is differentiated from the other crates.

⭐ cxx-qt - The Star of the Show

The main crate of CXX-Qt.

It serves as the actual crate our users should interface with. Anything that our users have to name in their downstream crates should be accessible via this crate. Mostly importantly this includes a re-export of the #[cxx_qt::bridge] macro from the cxx-qt-macro crate. Additionally, any code that the bridge references after expansion lives in cxx-qt.

Limitation: The cxx-qt crate itself is limited to implementing a superset of CXX. This means its goal is to add additional Qt-specific features to CXX. Namely support for Qts Meta-Object-System, which includes QObjects, QEnums, properties, signals, slots, etc.

CXX-Qt aims to allow you to wrap Qt APIs and create your own Qt-compatible types. It does not aim to actually wrap Qt API. Apart from a few extremely basic types that are needed for this goal, wrapping the actual Qt API is delegated to cxx-qt-lib and cxx-qt-lib-extras.

This should also allow cxx-qt-lib and cxx-qt-lib-extras to be used without the user needing to use the cxx-qt crate itself, which is why they're explicitly seperated.

πŸ‘· cxx-qt-build - The Construction Worker

cxx-qt-build provides the user-accessible API for building applications with CXX-Qt.

Specifically this means expanding and compiling the C++ code of each bridge.

In addition, it needs to integrate Qt into both Cargo and CMake. For Cargo, it uses Cargos build-script features to instruct linking, etc. For CMake, it exposes the required artifacts into a well-known directory and structure so that CMake can pick them up. The cxx-qt-cmake repo contains the CMake code to pick up the artifacts.

The access to Qts build tooling has actually been made available as a separate crate: qt-build-utils, which cxx-qt-build uses internally

πŸ’š cxx-qt-gen - The Heart of CXX-Qt

This crate contains the "main functionality" of CXX-Qt.

It encapsulates the transpiler that is at the very core of CXX-Qt. As described in the cxx-qt crate section, the goal of CXX-Qt is primarily to serve as an extension to CXX, that allows users to express Qt-specific constructs.

cxx-qt-gen implements the necessary transpiler that transpiles from a #[cxx_qt::bridge] to a #[cxx::bridge] and associated Rust and C++ code.

This transpiler is then used by the #[cxx_qt::bridge] macro via cxx-qt-macro, and also by cxx-qt-build for the C++ code generation.

⚠️ cxx-qt-gen should not be used directly, but only through cxx-qt and cxx-qt-build

For this reason, cxx-qt-gen itself is semver-exempt!

TODO: Add a documentation of the cxx-qt-gen stages and architecture in a separate page

πŸ“– cxx-qt-lib - The "standard" Library

cxx-qt-lib is to cxx-qt, what Rusts std library is to rustc.

It includes high-quality wrappers for the most important Qt types. These are often implemented in terms of plain #[cxx::bridge]s, with only a few types requiring #[cxx_qt::bridges].

During the development of CXX-Qt, we quickly realised that high-quality bindings to the Qt API are best written by hand. Especially for types that should be available as trivial types in Rust. However, this often brought up the problem of maintenance workload.

Qt has a huge API surface. For this reason we decided early on that wrapping all of Qts API is simply out-of-scope. This is exactly why we set the focus of CXX-Qt to empower the user. We want our users to be able to quickly access any part of the API they need by creating their own bindings.

However, without at least a few fundamental types, this is very hard to do. cxx-qt-lib aims to close exactly this gap. It's goal is to provide just enough types and API to provide a basis onto which new bindings can build.

Additional types can be added into a separate, less maintained, crate (namely: cxx-qt-lib-extras).

This leads us to the concrete policy for including types in cxx-qt-lib:

cxx-qt-lib inclusion policy

  • Default to adding anything you think may be useful to cxx-qt-lib-extras
  • Only add types to cxx-qt-lib directly, if they're either:
    • Hard to wrap optimally (i.e. should be trivial/templates, etc.)
    • Often used as parameters/return values within the Qt codebase

We can then always promote types from -lib-extras to -lib, if/when it turns out this type is used regularly.

πŸ“š cxx-qt-lib-extras - The Bookshelf

As mentioned in the cxx-qt-lib library, we do not aim to maintain wrappers for the entire Qt API. However, it would still be useful to have a place where the community can share and collect bindings for whatever they have wrapped of the Qt API.

This is exactly what cxx-qt-lib-extras is for! The details are outlined in #766.

The barrier of entry here is very low. We will accept pretty much any PR, as long as:

βœ… It wraps part of the Qt API

βœ… Compiles

βœ… Isn't obviously broken in some other way

However, we will not spend much (if any) time to actually maintain these bindings!

Specifically this means:

⚠️ cxx-qt-lib-extras is semver-exempt!

Specifically, we may simply drop a binding from the crate if it causes issues.

⚠️ Bindings may be incomplete or undocumented!

⚠️ Memory Safety Errors and other issues are possible!

Basically: There be dragons πŸ‰ - use at your own risk.

Forking of cxx-qt-lib-extras is encouraged to create something stable you can rely on for yourself. Simply copying individual files out of the crate into your own crate is also a reasonable way of using -lib-extras.

We only ask that you contribute your own wrappers and fixes back to -lib-extras so the wider ecosystem can benefit.

πŸ’» cxx-qt-macro - Frontend for cxx-qt-gen

For technical reasons within Cargo, procedural macros need to be a special type of crate.

cxx-qt-macro wraps the bridge macro, which is then re-exported by the cxx-qt crate.

🦾 qt-build-utils - Building with Qt

This crate wraps Qts custom build tooling like moc.

It is mostly used by cxx-qt-build. But because it may be useful to other crates in the Qt ecosystem as well, we have decided to split it into its own crate.

🀝 cxx-qt-cmake - Handoff to CMake

Whilst this is not a crate, it's a separate "project", as it lives in another repository. cxx-qt-cmake simply contains the bits of CMake code that encapsulate the integration of cxx-qt-build artifacts into CMake.

It lives inside a separate repository as that makes the use of CMakes FetchContent a lot faster as users don't have to download all of CXX-Qt.