Building with Cargo
In this example, we will demonstrate how to build the cxxqt_object.rs
as well as any QML files using the Rust build system.
Cargo will do the entire build, including linking to Qt, just like a typical Rust application.
Note that the folder structure of this example is different to the CMake tutorial.
The CMake example uses a rust
folder where the Rust part of the project resides in.
In this setup we'll stick with a standard Cargo folder layout with just the added qml
folder next to the src
folder.
The complete example code is available in examples/cargo_without_cmake
in the CXX-Qt repository.
If you don't want to use Cargo, and only want to use CMake to build your project, skip ahead to the next section.
Using a Cargo based setup is easier though, so if in doubt, try building with Cargo first.
Cargo setup
Add the dependencies to the Cargo.toml
file.
We'll need cxx
, cxx-qt
, cxx-qt-lib
and cxx-qt-build
:
[package]
name = "qml_minimal"
version = "0.1.0"
authors = [
"Andrew Hayzen <andrew.hayzen@kdab.com>",
"Be Wilson <be.wilson@kdab.com>",
"Gerhard de Clercq <gerhard.declercq@kdab.com>",
"Leon Matthes <leon.matthes@kdab.com>"
]
edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
cxx = "1.0.95"
cxx-qt = "0.7"
cxx-qt-lib = { version="0.7", features = ["qt_full"] }
[build-dependencies]
# The link_qt_object_files feature is required for statically linking Qt 6.
cxx-qt-build = { version = "0.7", features = [ "link_qt_object_files" ] }
Now we'll add a build.rs
script next to the Cargo.toml
file.
use cxx_qt_build::{CxxQtBuilder, QmlModule};
fn main() {
CxxQtBuilder::new()
// Link Qt's Network library
// - Qt Core is always linked
// - Qt Gui is linked by enabling the qt_gui Cargo feature of cxx-qt-lib.
// - Qt Qml is linked by enabling the qt_qml Cargo feature of cxx-qt-lib.
// - Qt Qml requires linking Qt Network on macOS
.qt_module("Network")
.qml_module(QmlModule {
uri: "com.kdab.cxx_qt.demo",
rust_files: &["src/cxxqt_object.rs"],
qml_files: &["qml/main.qml"],
..Default::default()
})
.build();
}
This is what generates and compiles the C++ code for our MyObject
class at build time.
It will also link Qt to our Rust binary.
Every Rust source file that uses the #[cxx_qt::bridge]
macro needs to be included in this script.
In our case, this is only the src/cxxqt_object.rs
file.
This is also where the QML module is defined with a QML URI and version.
The files and resources in the module are then exposed in the same way as the qt_add_qml_module
CMake function.
Refer to the CxxQtBuilder
and cc::Build
documentation for further details.
Rust executable
In src/main.rs
, first import the cxxqt_object
module and some types we will need to run our Qt application:
pub mod cxxqt_object;
use cxx_qt_lib::{QGuiApplication, QQmlApplicationEngine, QUrl};
Define the main
function that will be called when the executable starts. This works just like starting a QML
application in C++:
- Create a
QGuiApplication
- Create a
QQmlApplicationEngine
- Set the QML file path to the engine
- Run the application
fn main() {
// Create the application and engine
let mut app = QGuiApplication::new();
let mut engine = QQmlApplicationEngine::new();
// Load the QML path into the engine
if let Some(engine) = engine.as_mut() {
engine.load(&QUrl::from("qrc:/qt/qml/com/kdab/cxx_qt/demo/qml/main.qml"));
}
if let Some(engine) = engine.as_mut() {
// Listen to a signal from the QML Engine
engine
.as_qqmlengine()
.on_quit(|_| {
println!("QML Quit!");
})
.release();
}
// Start the app
if let Some(app) = app.as_mut() {
app.exec();
}
}
To build and run the application, use cargo run
.
📝 Note: In order for CXX-Qt to work, the
qmake
executable must be located. This is because CXX-Qt relies onqmake
to locate the necessary Qt libraries and header files on your system.
cxx-qt
will findqmake
in the following order:
- Look for an environment variable
QMAKE
that should have the path toqmake
.
e.g.:QMAKE=/usr/bin/qmake cargo run
- Use
qmake
from thePATH
. If multipleqmake
exists inPATH
, environment variableQT_VERSION_MAJOR
will control the selected one.To check which version of Qt will be used with
qmake
, you can use theqmake -query
command. This will display information about the Qt installation, including the version number and installation path.Check
CxxQtBuilder
for more information
If this fails for any reason, take a look at the examples/cargo-without-cmake
folder in the CXX-Qt repository, which contains the complete example code.
If you have cloned the CXX-Qt repository, you can run this example from within the repository using:
cargo run -p qml-minimal-no-cmake
You should now see the two Labels that display the state of our MyObject
, as well as the two buttons to call our two Rust functions.
Success 🥳
For further reading, you can take a look at the bridge chapter which goes into detail about all features that CXX-Qt exposes to new QObject
subclasses.
As well as the Concepts chapter, which explains the concepts underlying CXX-Qt.
In the next, optional chapter, we will show how to build the same QML application with CMake.