An extremely customizable, modular, fast, gpu-accelerated, cross-platform solution for creating user-interfaces minimal effort.
Platform | Status | Rendering Backend(s) |
---|---|---|
Windows 10+ | ✔️ | DX12, Vulkan |
Windows 8.1- | Vulkan, experimental DX11 | |
MacOS/iOS | ✔️ | Metal |
Linux X11/Wayland | ✔️ | Vulkan, GLES3 |
Android | ✔️ | Vulkan, GLES3 |
Download & install the recommended version of the Android NDK ("Current LTS Release", avoid the beta version).
Install cargo-apk
:
cargo install cargo-apk
Setting up your device (pick one, real hardware is easier):
- Real hardware
- Enable developer options and enable USB debugging
- Connect your phone via USB cable to your pc
- Emulator (virtual phone):
- Download & install the official Android emulator from google
- Make sure everything is setup correctly with PATH variables etc.
Recommended setup for single codebase applications supporting both mobile & desktop:
File structure (optional)
my_application
├──res
│ └──image.png
├──src
│ ├──app.rs
│ ├──main.rs
│ └──lib.rs
└──Cargo.toml
Cargo.toml
[features]
default = [] # 1
android = ["ndk-glue", "preon_module_wgpu/android"] # 2
[dependencies]
preon_engine = { path = "../preon_engine" }
ndk-glue = { version = "0.3.0", optional = true } # 3
preon_module_wgpu = { path = "../preon_module_wgpu" }
[lib]
crate-type = ["cdylib"] # 4
- Don't enable any features by default
- When the
android
feature is specified incargo
, it will enable thendk-glue
dependency and enable theandroid
feature inpreon_module_wgpu
- Specify the
ndk-glue
dependency, but don't enable it by default. Warning: If you have a tool that checks for dependencies and their updates, ignore the update forndk-glue
, aswinit
depends on this specific version.- Android requires a dynamic library for native code.
main.rs
mod app;
// Desktop entry point
fn main() {
app::app();
}
app.rs
pub fn app() {
// Regular preon_engine code here
}
lib.rs
mod app;
// Mobile entry point
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
pub fn main() {
app::app();
}
Why so weird?
Android needs native code to be a dynamically linked library, so you simply cant use
fn main()
. And while we can very easily use the official example to narrow it down to only 2 files, I've found that it can sometimes break IDE &rust-analyzer
functionality due to the macro. This solution avoids that.
To run your app on android you would run:
cargo apk run --features android
Running on desktop remains the same:
cargo run
To view stdout
(println!
, panic!
, etc.), run (with your phone connected of course):
adb logcat RustStdoutStderr:D *:S