Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 53 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jobs:
- name: Install dependencies
run: sudo apt -y install libgtk-3-dev libudev-dev libxdo-dev
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
target: wasm32-unknown-unknown
targets: wasm32-unknown-unknown,armv7-linux-androideabi,aarch64-linux-android
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
Expand All @@ -34,6 +34,10 @@ jobs:
run: cargo check --workspace
- name: Cargo check WASM
run: cargo check --target wasm32-unknown-unknown --package minimal-web
- name: Cargo check Android ARMv7
run: cargo check --target armv7-linux-androideabi --package minimal-winit-android --lib
- name: Cargo check Android AARCH64
run: cargo check --target aarch64-linux-android --package minimal-winit-android --lib

lints:
name: Lints
Expand All @@ -46,11 +50,11 @@ jobs:
- name: Install dependencies
run: sudo apt -y install libgtk-3-dev libudev-dev libxdo-dev
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: clippy, rustfmt
target: wasm32-unknown-unknown
targets: wasm32-unknown-unknown,armv7-linux-androideabi,aarch64-linux-android
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
Expand All @@ -67,6 +71,10 @@ jobs:
run: cargo clippy --workspace --tests -- -D warnings
- name: Cargo clippy WASM
run: cargo clippy --target wasm32-unknown-unknown --package minimal-web --tests -- -D warnings
- name: Cargo clippy Android ARMv7
run: cargo clippy --target armv7-linux-androideabi --package minimal-winit-android --lib -- -D warnings
- name: Cargo clippy Android AARCH64
run: cargo clippy --target aarch64-linux-android --package minimal-winit-android --lib -- -D warnings
- name: Cargo machete
run: cargo machete

Expand All @@ -88,7 +96,7 @@ jobs:
- name: Install dependencies
run: sudo apt -y install libgtk-3-dev libudev-dev libxdo-dev
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Rust cache
Expand All @@ -110,17 +118,54 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: wasm32-unknown-unknown
targets: wasm32-unknown-unknown
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: common
- name: WASM build
run: cargo run-wasm --build-only --package ${{ matrix.example }}

android:
name: Android
runs-on: ubuntu-latest
needs: [checks, lints]
strategy:
matrix:
example:
- minimal-winit-android
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: armv7-linux-androideabi,aarch64-linux-android
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
cmdline-tools-version: 13114758
packages: build-tools;35.0.1 ndk;28.2.13676358 platforms;android-35
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: common
- name: Install cargo-apk
uses: baptiste0928/cargo-install@v2
with:
crate: cargo-apk
- name: Android build
run: cargo apk build --package ${{ matrix.example }} --lib

# See https://github.com/parasyte/pixels-ci-rust-version
rust-version:
name: Rust-Version
Expand All @@ -136,7 +181,7 @@ jobs:
with:
repository: parasyte/pixels-ci-rust-version
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Rust cache
Expand Down
21 changes: 15 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions examples/minimal-winit-android/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore everything
*
16 changes: 14 additions & 2 deletions examples/minimal-winit-android/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,23 @@ winit = { workspace = true, features = ["android-native-activity"] }
env_logger.workspace = true

[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android_logger = "0.15.0"

[[bin]]
# Rename the bin to avoid https://github.com/rust-lang/cargo/issues/6313
name = "desktop-example"
path = "src/main.rs"

[lib]
crate-type = ["cdylib"]
crate-type = ["cdylib", "lib"]

[package.metadata.android.signing.release]
path = "./path/to/KeyStoreFile.jks"
keystore_password = "password"

[package.metadata.android]
build_targets = ["armv7-linux-androideabi", "aarch64-linux-android"]

[package.metadata.android.sdk]
min_sdk_version = 23
target_sdk_version = 35
50 changes: 50 additions & 0 deletions examples/minimal-winit-android/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Build with the `pixels` MSRV. This will be updated in lockstep.
FROM rust:1.82.0-slim

# Variable arguments
ARG JAVA_VERSION=17
ARG NDK_VERSION=28.2.13676358
ARG BUILDTOOLS_VERSION=35.0.1
ARG PLATFORM_VERSION=android-35
ARG CLITOOLS_VERSION=13114758_latest

# Install Android requirements
RUN apt-get update -yqq && \
apt-get install -y --no-install-recommends \
libcurl4-openssl-dev libssl-dev pkg-config build-essential git python3 wget zip unzip openjdk-${JAVA_VERSION}-jdk && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# Install android targets
RUN rustup target add armv7-linux-androideabi aarch64-linux-android

# Install cargo-apk
RUN cargo install --locked cargo-apk

# Generate Environment Variables
ENV JAVA_VERSION=${JAVA_VERSION}
ENV ANDROID_HOME=/opt/Android
ENV NDK_HOME=/opt/Android/ndk/${NDK_VERSION}
ENV ANDROID_NDK_ROOT=${NDK_HOME}
ENV PATH=$PATH:${ANDROID_HOME}:${ANDROID_NDK_ROOT}:${ANDROID_HOME}/build-tools/${BUILDTOOLS_VERSION}:${ANDROID_HOME}/cmdline-tools/bin

# Install command line tools
RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
wget -qc "https://dl.google.com/android/repository/commandlinetools-linux-${CLITOOLS_VERSION}.zip" -P /tmp && \
unzip -d ${ANDROID_HOME} /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip && \
rm -fr /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip
# Install sdk requirements
RUN echo y | sdkmanager --sdk_root=${ANDROID_HOME} --install \
"build-tools;${BUILDTOOLS_VERSION}" "ndk;${NDK_VERSION}" "platforms;${PLATFORM_VERSION}"

# Create APK keystore for debug profile
# Adapted from https://github.com/rust-mobile/cargo-apk/blob/caa806283dc26733ad8232dce1fa4896c566f7b8/ndk-build/src/ndk.rs#L393-L423
RUN keytool -genkey -v -keystore ${HOME}/.android/debug.keystore -storepass android -alias androiddebugkey \
-keypass android -dname 'CN=Android Debug,O=Android,C=US' -keyalg RSA -keysize 2048 -validity 10000

# Cleanup
RUN rm -rf /tmp/*

WORKDIR /mnt

ENTRYPOINT [ "cargo", "apk", "build", "--lib" ]
42 changes: 39 additions & 3 deletions examples/minimal-winit-android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,51 @@

Minimal example to run on android using `winit` with `android-native-activity` feature

## Running
```
## Running on Android

```bash
export ANDROID_HOME="path/to/sdk"
export ANDROID_NDK_HOME="path/to/ndk"

rustup target add aarch64-linux-android
cargo install cargo-apk
```

Connect your Android device via USB cable to your computer in debug mode and run the following command

```bash
cargo apk run --package minimal-winit-android
```

## Running on Desktop

Sometimes it is helpful to run your Android apps on a Desktop environment (e.g., Windows, macOS, or
Linux). It works the same way as all other `pixels` examples:

```bash
cargo run --package minimal-winit-android
```

## Containerized Builds

A `Containerfile` is included, allowing containerized builds without the need to install the Android
SDK and dependencies on the build host.

The following commands are assumed to be run from the repository root directory.

Build the image in Docker:

```bash
docker build -t rust-android:latest ./examples/minimal-winit-android/
```
cargo apk run

Build the example in the container:

```bash
docker run --rm -it -v "$PWD:/src" rust-android:latest --package minimal-winit-android
```

The APKs are written to `./target/debug/apk/`.

For release builds, add `--release` to the end of the `run` command. (This will need the path to
the keystore corrected in the Cargo.toml manifest.) The APKs are written to `./target/release/apk/`.
44 changes: 20 additions & 24 deletions examples/minimal-winit-android/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![deny(clippy::all)]
#![forbid(unsafe_code)]
#![cfg_attr(not(target_os = "android"), forbid(unsafe_code))]

#[cfg(target_os = "android")]
use winit::platform::android::activity::AndroidApp;
Expand All @@ -22,14 +22,13 @@ struct World {
velocity_y: i16,
}

struct Display<'win> {
struct Display {
window: Arc<Window>,
pixels: Pixels<'win>,
pixels: Pixels<'static>,
}

fn _main(event_loop: EventLoop<()>) {
let mut display: Option<Display> = None;

pub fn _main(event_loop: EventLoop<()>) {
let mut display = None;
let mut world = World::new();

let res = event_loop.run(|event, elwt| {
Expand All @@ -52,10 +51,17 @@ fn _main(event_loop: EventLoop<()>) {
Event::Suspended => {
display = None;
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
world.update();
if let Some(display) = &mut display {
world.draw(display.pixels.frame_mut());
display.pixels.render().unwrap();
Expand All @@ -64,9 +70,6 @@ fn _main(event_loop: EventLoop<()>) {
}
_ => {}
}
if display.is_some() {
world.update();
}
});
res.unwrap();
}
Expand Down Expand Up @@ -119,25 +122,18 @@ impl World {
}
}

#[allow(dead_code)]
#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(app: AndroidApp) {
use android_logger::Config;
use winit::event_loop::EventLoopBuilder;
use winit::platform::android::EventLoopBuilderExtAndroid;
android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Info));
let event_loop = EventLoopBuilder::new().with_android_app(app).build();
log::info!("Hello from android!");
_main(event_loop);
}

#[allow(dead_code)]
#[cfg(not(target_os = "android"))]
fn main() {
env_logger::builder()
.filter_level(log::LevelFilter::Info) // Default Log Level
.parse_default_env()
.init();
let event_loop = EventLoop::new().unwrap();
log::info!("Hello from desktop!");
android_logger::init_once(Config::default().with_max_level(log::LevelFilter::Info));
let event_loop = EventLoopBuilder::new()
.with_android_app(app)
.build()
.unwrap();
log::info!("Hello from android!");
_main(event_loop);
}
Loading
Loading