Using Rust library in Sailfish Application

I want to use the rust library GitHub - matrix-org/vodozemac: An implementation of Olm and Megolm in pure Rust. in my Sailfish application.

Via cargo build --target aarch64-unknown-linux-gnu I compiled the code into libvodozemac.rlib and copied that file in my project directory under /lib, and added it to my project.

In my .pro file I added

library.files = $$PWD/lib/libvodozemac.rlib
library.path = $$[QT_INSTALL_LIBS]
INSTALLS += library

and in my .spec file I added

%{_libdir}/libvodozemac.rlib

In my main .CPP program I added

    QLibrary vodozeMac("libvodozemac.rlib");
    if (!vodozeMac.load()) {
        qDebug() << "Could not load library:" << vodozeMac.errorString();
        return -1;
    }

I run the application on a Sony Xperia 10 III. When running the application, I get [D] main:30 -

Could not load library: "Cannot load library libvodozemac.rlib: (/usr/lib64/libvodozemac.rlib: invalid ELF header)"

07:34:17: Remote process crashed.

Can somebody help what am I doing wrong here?

1 Like

Hi. I don’t know much about rust but it looks like rlib is a rust only thing that is designed to be statically linked to the final binary at compile time by the rust compiler, while you are trying to load it like a dynamic shared object library.

Thank you. I executed the following to get a .so file, but I am still in troubles:

1. Created file ~/.cargo/config.toml

[build]
target = “aarch64-unknown-linux-gnu”

[target.aarch64-unknown-linux-gnu]
linker = “aarch64-suse-linux-gcc”

2. Added the following lines to Cargo.toml

[lib]
name = “vodozemac”
crate-type = [“lib”, “cdylib”]

3. Compiled again via cargo build

Now I am getting following errors

/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find crti.o: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lc: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lm: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lrt: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lpthread: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lgcc_s: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lutil: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lrt: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lpthread: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lm: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -ldl: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find -lc: No such file or directory
/usr/lib64/gcc/aarch64-suse-linux/14/ld: cannot find crtn.o: No such file or directory

Seems I am missing files for this type of cross compilation, but I don’t know how to solve this. I’m using OpenSUSE LEAP 15.6 with following cross-compilation packages installed: cross-aarch64-binutils, cross-aarch64-gcc11, cross-aarch64-gcc14-bootstrap, cross-aarch64-linux-glibc-devel

You might want to look at how Whisperfish (a Signal protocol client) does this. I believe its core is also Rust based.

An overview what is Whisperfish and what is to be considered for the development of an Rust-based native app is shown here: Whisperfish - The unofficial SailfishOS Signal client - #1420 by tmindrup

How to build whisperfish - see chapter “Building from source” - with the Jolla sfdk you can see here: Whisperfish / Whisperfish - Signal on Sailfish OS · GitLab

Thank you, I will try to build the Whisperfish application and learn of it, but looks very elaborate, I’m not there yet with my app :slight_smile:

Currently I just want to generate a library based on the vodozemac Rust code, library to be used for C++ code within Sailfish application.

I also tried
sfdk config target=SailfishOS-5.0.0.62-aarch64
sfdk build-shell cargo build -Znext-lockfile-bump

now getting other errors

error: failed to download base64ct v1.8.0

Caused by:
unable to get packages from source

Caused by:
failed to download replaced source registry crates-io

Caused by:
failed to parse manifest at /home/mersdk/.cargo/registry/src/index.crates.io-1cd66030c949c28d/base64ct-1.8.0/Cargo.toml

Caused by:
feature edition2024 is required

The package requires the Cargo feature called edition2024, but that feature is not stabilized in this version of Cargo (1.75.0-nightly).
Consider trying a more recent nightly release.
See Unstable Features - The Cargo Book for more information about the status of this feature.

Is there any spec file I can use as reference for this? Whisperfish is a Rust based app. OP and I are looking for QtQuick apps that use Rust libraries. Thanks!

EDIT: I’ve sorted it out myself.

Well, now I am interested :slight_smile: I didn’t succeed in it, so I switched to old C files, but would prefer the more recent Rust-ones. Do you have some information?

Everything is in the above repo. However, I’ve put my rust code in the rust dir, and then the important bits are:

QMake project file:

TARGET_TRIPLE = $$(SB2_RUST_TARGET_TRIPLE)
isEmpty(TARGET_TRIPLE) {
    TARGET_TRIPLE = $$(RUST_TARGET)
}

SOURCE_DIR = $$_PRO_FILE_PWD_
isEmpty(TARGET_TRIPLE) {
    RUST_TARGET_DIR = $$SOURCE_DIR/rust/target/release
} else {
    RUST_TARGET_DIR = $$SOURCE_DIR/rust/target/$$TARGET_TRIPLE/release
}

LIBS += -L$$RUST_TARGET_DIR -llemmy_bridge

INCLUDEPATH += $$SOURCE_DIR/src

CARGO_CMD = cd $$SOURCE_DIR && \
    cargo build --release \
        --target-dir $$SOURCE_DIR/rust/target \
        --manifest-path $$SOURCE_DIR/rust/Cargo.toml \
        --locked
!isEmpty(TARGET_TRIPLE): CARGO_CMD += --target $$TARGET_TRIPLE

!exists($$SOURCE_DIR/src/lemmy_bridge.h) {
    message("lemmy_bridge.h not found — running cargo build at qmake time...")
    system($$CARGO_CMD)
}

rust_so.target   = $$RUST_TARGET_DIR/liblemmy_bridge.so
rust_so.commands = $$CARGO_CMD
rust_so.depends  = $$SOURCE_DIR/rust/Cargo.toml \
                   $$SOURCE_DIR/rust/src/lib.rs
QMAKE_EXTRA_TARGETS += rust_so
PRE_TARGETDEPS  += $$RUST_TARGET_DIR/liblemmy_bridge.so

QMAKE_CLEAN += \
    $$SOURCE_DIR/src/lemmy_bridge.h \
    $$RUST_TARGET_DIR/liblemmy_bridge.so

rust_so_install.path  = /usr/lib
rust_so_install.files = $$RUST_TARGET_DIR/liblemmy_bridge.so
INSTALLS += rust_so_install

RPM spec:

%ifarch %arm
export SB2_RUST_TARGET_TRIPLE=armv7-unknown-linux-gnueabihf
export CFLAGS_armv7_unknown_linux_gnueabihf=$CFLAGS
export CXXFLAGS_armv7_unknown_linux_gnueabihf=$CXXFLAGS
%endif
%ifarch aarch64
export SB2_RUST_TARGET_TRIPLE=aarch64-unknown-linux-gnu
export CFLAGS_aarch64_unknown_linux_gnu=$CFLAGS
export CXXFLAGS_aarch64_unknown_linux_gnu=$CXXFLAGS
%endif
%ifarch %ix86
export SB2_RUST_TARGET_TRIPLE=i686-unknown-linux-gnu
export CFLAGS_i686_unknown_linux_gnu=$CFLAGS
export CXXFLAGS_i686_unknown_linux_gnu=$CXXFLAGS
%endif

export CFLAGS="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0"
export CXXFLAGS=$CFLAGS

# Set OpenSSL location for cross-compilation
if [ -n "${SB2_RUST_TARGET_TRIPLE:-}" ]; then
    export OPENSSL_DIR=/usr
fi

# Set meego cross compilers
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=armv7hl-meego-linux-gnueabi-gcc
export CC_armv7_unknown_linux_gnueabihf=armv7hl-meego-linux-gnueabi-gcc
export CXX_armv7_unknown_linux_gnueabihf=armv7hl-meego-linux-gnueabi-g++
export AR_armv7_unknown_linux_gnueabihf=armv7hl-meego-linux-gnueabi-ar
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-meego-linux-gnu-gcc
export CC_aarch64_unknown_linux_gnu=aarch64-meego-linux-gnu-gcc
export CXX_aarch64_unknown_linux_gnu=aarch64-meego-linux-gnu-g++
export AR_aarch64_unknown_linux_gnu=aarch64-meego-linux-gnu-ar

EDIT: turns out my first setup was working in QtCreator, but it wasn’t working with sfdk build. I also migrated the config from a static library to a shared one.

1 Like