This blog shows how Qt applications can be built with Cargo. The goalis to make compiling them as simple as installing Qt and running
cargo buildThe cratesqrep andmailmodel areexamples. You can tryqrep with
cargo install qrepqrepqrep is a minimal GUI forripgrep.

mailmodel is a proof-of-concept mail reader.

You can get started quickly with your own Rust Qt application bycopying the foldertemplates/qt_quick_cargo from theRustQt Binding Generator repository.
Inpreviousblogs we built applications with CMake. CMake is probably the mostwidely used tool to compile Qt software. CMake uses Cargo to build theRust parts.
CMake is a familiar tool for Qt developers, but not for Rustdevelopers. For them, CMake is an unneeded hurdle. Rust Qt BindingGenerator can be used with only Cargo. To do so you use the Rust way ofbuilding C++ code:build.rs.
build.rsbuild.rs contains Rust code that is compiled and run byCargo to build an application. Here is a simplebuild.rsfile:
externcrate rust_qt_binding_generator;fn main(){// obtain the output directory from an environment variablelet out_dir=::std::env::var("OUT_DIR").unwrap();// create a new builderrust_qt_binding_generator::build::Build::new(&out_dir)// add Rust Qt bindings.bindings("bindings.json")// add files to compile into the program as resources.qrc("qml.qrc")// add some C++ code.cpp("src/main.cpp")// compile it to a static library.compile("my_project");}This file is placed directly in your project folder. The lastcommand,compile("my_project"), compiles a library calledmy_project.
Cargo.tomlbuild.rs and the name of the library should be added toCargo.toml:
[package]name="my_project"version="0.1.0"build="build.rs"# use build.rs for custom build stepslinks="my_project"# and link to the resulting library[dependencies]libc="0.2"[build-dependencies]rust_qt_binding_generator="0.2"src/main.rsmain.rs is the entry point for Rust applications. Inthese applications, two things should happen:
include the generated Rust codeinterface.rs.
call into the C++ code.
Qt applications have an event loop. Starting this loop requires someC++ code. We start the event loop in a C++ function. The name of theapplication is passed to this function.
externcrate libc;// include the interface generated from bindings.jsonpubmod interface{include!(concat!(env!("OUT_DIR"),"/src/interface.rs"));}// the module with our implementation of the interfacemod implementation;// declare the function that calls into the C++ codeextern{fn main_cpp(app:*const::std::os::raw::c_char);}fn main(){usestd::ffi::CString;let app_name=::std::env::args().next().unwrap();let app_name=CString::new(app_name).unwrap();unsafe{// call the C++ function that starts the Qt event loop main_cpp(app_name.as_ptr());}}src/main.cppThe template contains one C++ file. That is usually all you need. Butit’s possible to add more C++ files by adding more calls toBuild::cpp.
This file loads the GUI from a QML file and starts the eventloop.
#include"Bindings.h"#include<QtCore/QFile>#include<QtGui/QGuiApplication>#include<QtQml/QQmlApplicationEngine>#include<QtQml/qqml.h>extern"C"{int main_cpp(constchar* app);}int main_cpp(constchar* appPath){// create a QGuiApplicationint argc=1;char* argv[1]={(char*)appPath};QGuiApplication app(argc, argv);// register the type that we wrote in RustqmlRegisterType<Simple>("RustCode",1,0,"Simple");// This is QML application. We load the QML file from the file system// or take the one embedded into the application otherwise.QQmlApplicationEngine engine;if(QFile("main.qml").exists()){ engine.load(QUrl(QStringLiteral("main.qml")));}else{ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));}// start the event loopreturn app.exec();}qml.qrcQt applications can contain resources. These are embedded files thatare accessible viaqrc: URLs. The template applicationcontains two resources:main.qml andMainForm.qml. Other resources such as translations orapplication icons can be added as well.
<RCC> <qresource prefix="/"> <file>main.qml</file> <file>MainForm.ui.qml</file> </qresource></RCC>The option to build Qt applications with Cargo should please Rustprogrammers. I’ve ported my personal projects to build this way. UsingCMake is also still supported and is recommended for C++ projects thatcurrently use CMake and would like to introduce Rust.
This feature is new and not widely tested. Bugs can be filedhere.