Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add instructions to readme
  • Loading branch information
owlmafia committed Aug 17, 2019
1 parent 4c564bf commit d6c2a57
Showing 1 changed file with 119 additions and 7 deletions.
126 changes: 119 additions & 7 deletions README.md
@@ -1,31 +1,143 @@
# rust_android_ios

Android/iOS app with shared Rust logic
Android / iOS app with shared Rust logic.

Based on the [Rust Swig](https://github.com/Dushistov/rust_swig) Android example with added support for iOS from [rust-ios-android-example](https://github.com/terhechte/rust-ios-android-example) + upgrade and customization.
#### ✅ Functions
Calls Rust functions from Android / iOS, shows return value in UI.

The idea is to continue evolving this. Maybe a little mobile Rust framework? It would be interesting to explore reactive (have a Rust stream propagate down to Swift UI or Jetpack compose!).
#### ✅ Callback
Passes callback to Rust and updates UI on Android / iOS with call.

See [talk](https://www.youtube.com/watch?v=fq1pQ0RpstM) from [@terhechte](https://github.com/terhechte) - this started this!
#### ✅ Reactive
Subscribes in Android / iOS to events triggered by Rust and updates UI with them.

#### ✅ Unidirectional flow
UI sends event to Rust. Rust emits to channel that is observed in Android / iOS. This allows to e.g. implement MVVM architecture writing the view models in Rust (with some glue to convert the observer-callbacks in observables/channels/SwiftUI/Jetpack compose/whatever).

## Instructions

### Android / iOS

Ensure [rustup](https://rustup.rs/) is installed. This includes [Cargo](https://doc.rust-lang.org/cargo/), so you should be able to compile & build Rust projects + install the required targets to build for Android and iOS.

List available targets: `rustup target list`
Show currently installed targets: `rustup toolchain list`

The Rust sources, i.e. of the shared library, are in <TODO path>/lib.rs


### Android

These steps show how to build and run an Android app in debug mode for a 64 bits emulator.

See [rust_swig documentation](https://dushistov.github.io/rust_swig/java-android-example.html)


### NDK

Ensure the [NDK](https://developer.android.com/ndk/guides) is installed and there's an environment variable `ANDROID_NDK` pointing to the NDS's root directory.


#### Add targets

TODO install dir?
`rustup target add x86_64-linux-android`

#### Add path to clang

TODO install dir?
- Update linker path in <project_root>/.cargo/config:

```
[target.x86_64-linux-android]
linker = "<targets installation directory>/android-29-x86_64-4.9/bin/clang"
runner = "../run-on-adroid.sh"
```

#### Build
From the project's root directory:
```
./gradlew assembleDebug
```

#### Install

Ensure [adb](https://developer.android.com/studio/command-line/adb) is installed and the emulator or device open.

From the project's root directory:
```
adb install ./app/build/outputs/apk/debug/app-debug.apk
```

#### Run

Start the app in the emulator / device!

Alternatively just run the project in Android Studio. This will build, install and run.


#### Relevant configuration files

If you want to add targets or tweak the configuration, you have to edit one or more of these files:

- [Gradle build file](TODO path): This contains the apk settings (like application id, sdk version) and build steps. It builds for the provided architectures using cargo and puts the generated shared libraries (.so files) in the expected directories. If you want to build for a new target, add it [here](TODO). The target's key is the folder name where the shared library will be put and has to match abi identifiers listed [here](https://developer.android.com/ndk/guides/abis.html) (TODO confirm identifiers/link), and the value is the toolchain's name used by rustup.

- [Cargo config](TODO path): Contains linker and runner paths for targets.

- [Build.rs](TODO path): This is a script invoked by Cargo before everything else. For Android, it's used to tell rust_swig to generate the glue Rust files needed for Java interop. If you change the app's package structure / names, you have to update this file accordingly. It also sets the import to use for the `NonNull` annotation ( `use_null_annotation_from_package`). If you're using a recent Android SDK version, you don't need to change it.

#### Updating Rust

You edited something in Rust! Now you have to:

- Update [java_glue.rs.in](<TODO PATH/java_glue.rs.in) accordingly. This is a file [rust_swig](https://github.com/Dushistov/rust_swig) uses to generate the JNI glue. Consult [rust_swig](https://github.com/Dushistov/rust_swig) docs for syntax.

- Build, install, run, as described above.

#### Updating Kotlin/Java

The code of the Android app can be found [here](TODO path to /app/src/main/java/com/schuetz/rust_android_ios/MainActivity.java). This is a regular Android app which you can work with normally. Just don't modify the generated JNI files and remember to update the configuration files if you change the package structure.

### iOS

See [rust-ios-android-example](https://github.com/terhechte/rust-ios-android-example)
#### App code

The code of the iOS app can be found [here](TODO path to /app/src/main/java/com/schuetz/rust_android_ios/MainActivity.java).

#### Add targets
`rustup target add x86_64-apple-ios`

#### Build & run
From the project's root directory:
```
cargo build --target=x86_64-apple-ios
```
This will generate the required library files: <project root directory>/target/mobileapp-ios.h with the headers and the (static) library for the target, <project root directory>/target/<target name>/libmobcore.a. The header is referenced by the iOS project so you don't have to do anything. The library could not be referenced, so at the moment you have to copy manually libmobcore.a into the iOS app's directory each time you update it.

With the header and library in place, you can now run the iOS app.

#### Updating Rust

You edited something in Rust! Now you have to:

#### TODO
- Update the [C headers Rust implementation file](TODO PATH). Here, differently to Android, we have to write the glue manually. Orient with the existing code.

Add complete step-by-step for Android & iOS here!
- Build as described in "Build & run". Cargo invokes build.rs, which uses cbindgen to generate the iOS library files.

- Copy manually the generated <project root directory>/target/<target name>/libmobcore.a to the iOS app project's root folder.

- Run!

#### Updating Swift/ObjC

The code of the iOS app can be found [here](TODO path to /app/src/main/java/com/schuetz/rust_android_ios/MainActivity.java). This is a regular iOS app which you can work with normally.

## Contribute

1. Fork
2. Commit changes to a branch in your fork
3. Push your code and make a pull request

## Credits

The general setup and example to call functions is based on https://github.com/Dushistov/rust_swig and https://github.com/terhechte/rust-ios-android-example for Android and iOS respectively.

0 comments on commit d6c2a57

Please sign in to comment.