{"id":13439788,"url":"https://github.com/Geal/rust_on_mobile","last_synced_at":"2025-03-20T09:30:37.617Z","repository":{"id":66119426,"uuid":"61542562","full_name":"Geal/rust_on_mobile","owner":"Geal","description":null,"archived":false,"fork":false,"pushed_at":"2016-07-31T17:45:40.000Z","size":27,"stargazers_count":169,"open_issues_count":1,"forks_count":7,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-04-22T13:31:47.749Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Geal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-06-20T11:26:50.000Z","updated_at":"2024-04-20T14:27:16.000Z","dependencies_parsed_at":"2023-05-16T04:00:51.023Z","dependency_job_id":null,"html_url":"https://github.com/Geal/rust_on_mobile","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geal%2Frust_on_mobile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geal%2Frust_on_mobile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geal%2Frust_on_mobile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geal%2Frust_on_mobile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Geal","download_url":"https://codeload.github.com/Geal/rust_on_mobile/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244585595,"owners_count":20476766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T03:01:17.086Z","updated_at":"2025-03-20T09:30:37.564Z","avatar_url":"https://github.com/Geal.png","language":"Objective-C","funding_links":[],"categories":["Libraries","库 Libraries","库"],"sub_categories":["Mobile","移动 Mobile","移动"],"readme":"# Steps\n\n## Rust\n\n* Create the Rust library\n* export some symbols with libc (for iOS)\n* use rusty-cheddar to generate the headers, or write them manually\n\n## Build for iOS\n\n* install `cargo-lipo`: `cargo install cargo-lipo`\n* install the required toolchains:\n  * rustup target add aarch64-apple-ios\n  * rustup target add armv7-apple-ios\n  * rustup target add armv7s-apple-ios\n  * rustup target add i386-apple-ios\n  * rustup target add x86_64-apple-ios\n\n## iOS with CocoaPods\n\n* install the cocoapods: `sudo gem install cocoapods` (cf https://cocoapods.org/ )\n* use the command `pod lib create InRustWeTrustKit` to create the pod with an example app\n* remove the `.git` folder in the pod\n* move the podspec file at the root of the project\n* change `InRustWeTrustKit/Example/Podfile` to point to the pod at `../../` instead of `../`\n* update the `source_files` path in the podspec from `InRustWeTrustKit/Classes/**/*` to `InRustWeTrustKit/InRustWeTrustKit/Classes/**/*`\n* add the `prepare_command` in the podspec file to build the library\n* use `pod lib lint --verbose` to verify the podspec file\n* `cd InRustWeTrustKit/Example \u0026\u0026 pod install --verbose` to test building with the example app\n\nCocoaPods have a lot of requirements to push them to the repo, like having a valid\nLICENSE file, making a different branch for every version, and storing every podspec\nfile in a github repository, so be prepared to spend some time fighting those issues.\n\n## Build for Android\n\n* download the Android NDK\n* Create the `rust-jni` project to host the JNI interface: `cargo new rust-jni`. It will generate a dylib\n* add the original project as dependency by path\n* create the JNI export functions\n* write a `.cargo/config` file with the following content (adjust the paths, platform and SDK version accordingly):\n  ```\n  [target.arm-linux-androideabi]\n  ar = \"/usr/local/Cellar/android-ndk/r11c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar\"\n  linker = \"/Users/geal/dev/rust_on_mobile/rust-jni/linker-wrapper.sh\"\n  ```\n* the `rust-jni/linker-wrapper.sh` file was a ugly hack I needed to link when a link option was unavailable with the linker version, not sure it's still needed\n* `cargo build --target=arm-linux-androideabi`\n* `cp target/arm-linux-androideabi/debug/libinrustwetrust.so ../android/src/main/jniLibs/armeabi/libinrustwetrust.so`\n* `cp target/arm-linux-androideabi/debug/libinrustwetrust.so ../android/src/main/jniLibs/armeabi-v7a/libinrustwetrust.so` (we should probably build with another arch there)\n\n## Android plugin with Gradle\n\n* create an Android library project with Android studio, put it in the `android/` directory\n* create the classes corresponding to the exported interface\n* load the library. The dylibs should be in `src/main/jniLibs/\u003carch\u003e/`\n\n## Loading the Android plugin\n\nin settings.gradle:\n\n```\ninclude ':InRustWeTrust'\nproject(':InRustWeTrust').projectDir = new File('\u003cPATH_TO\u003e/rust_on_mobile/android')\n```\nin build.gradle:\n\n```\ndependencies {\n    compile project(path: ':InRustWeTrust')\n}\n```\n\nin gradle.properties: `android.useDeprecatedNdk=true`\n\nin local.properties (update paths accordingly):\n\n```\nsdk.dir=/path/to/android-sdk-macosx\nndk.dir=/usr/local/Cellar/android-ndk/r11c\n```\n\nIn the app's code, `import com.geal.InRustWeTrust;` and `Log.d(\"TEST\", \"result: \"+Integer.toString(InRustWeTrust.add(1, 2)));`\n\n# Questions\n\n## Should the exported C symbols be in another crate depending on the main library?\n\nRight now, the exported C symbols will also end up in the Android library\n\n## everything is done manually to write JNI functions right now, could it be automated a bit more?\n\nCan we generate the Java classes?\nCan we avoid writing `Java_com_etc`?\nmaybe with a compiler plugin\n\n## how can we generate a static library with apple's bitcode format?\n\nThe current way for iOS is to generate a so-called \"universal binary\" that will contain code for all\ntargeted architectures. Apple decided that since binaries are becoming large (well, not that large\ncompared to all the Retina aware icons, but I digress), they will make a library format containing\nLLVM bitcode that will be precompiled by Apple, so that you only receive the binaries for your arch\nwhen you download an app (cf http://lowlevelbits.org/bitcode-demystified/ for more info).\n\nWe can generate LLVM bitcode with Rust, but there's an incompatibility in the formats.\nApple's clang uses the following version:\n\n```\n$ xcrun clang -v\nApple LLVM version 7.0.2 (clang-700.1.81)\nTarget: x86_64-apple-darwin14.5.0\nThread model: posix\n```\n\nFrom what I understand, Rust uses LLVM 3.8.1.\n\nApparently, The flag used to ship bitcode in the library is available from LLVM 3.8.1, but Apple used it\nin its 3.7 fork before contributing it back. So the bitcode generated by rustc could be incompatible:\n\n```\n$ cd inrustwetrust/\n$ cargo rustc -- --emit llvm-ir\n[...]\n$ xcrun clang -c target/debug/inrustwetrust.ll\ntarget/debug/inrustwetrust.ll:9:133: error: expected value token\n  ...{ %str_slice, %str_slice, i32 } { %str_slice { i8* getelementptr inbounds ([30 x i8], [30 x i8]* @str6...\n                                                                                         ^\n1 error generated.\n```\n\nSo it looks like right now, it's impossible to generate an iOS library from Rust using the bitcode format.\n\n## Exception unwinding is apparently incompatible between Rust and ObjectiveC because of compact unwinding\n\nLinking the app can fail with the following error:\n\n```\nld: too many personality routines for compact unwind to encode for architecture x86_64\n```\n\nThis can be fixed by passing `-Wl,-keep_dwarf_unwind -Wl,-no_compact_unwind` as \"other linker flags\".\nFrom what I understand, Objective C has a different exception unwinding system that is not using\nthe dwarf based one like Rust.\n\nAnother idea would be to remove exception unwinding from the rust code, with a `panic=abort`, but\nthat means any exception would generate a crash in the Rust code, which is not a great solution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGeal%2Frust_on_mobile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGeal%2Frust_on_mobile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGeal%2Frust_on_mobile/lists"}