├── .cargo └── config ├── Cargo.lock ├── Cargo.toml ├── MobileApp ├── MobileApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── terhechte.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── terhechte.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── MobileApp │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── Rust-Bridging-Header.h └── build-rust-xcode.sh ├── README.md ├── android-example.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── appventure │ │ └── mobileapp │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── appventure │ │ │ └── mobileapp │ │ │ ├── MainActivity.java │ │ │ ├── MobileApp.java │ │ │ └── Worker.java │ ├── libs │ │ ├── armeabi │ │ │ └── libmobcore.so │ │ └── x86_64 │ │ │ └── libmobcore.so │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ └── content_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── me │ └── appventure │ └── mobileapp │ └── ExampleUnitTest.java ├── build.bak ├── build.gradle ├── build.rs ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── macroslib ├── .idea │ ├── macroslib.iml │ ├── misc.xml │ ├── modules.xml │ ├── vcs.xml │ └── workspace.xml ├── Cargo.lock ├── Cargo.toml ├── build.rs ├── src │ ├── cpp │ │ ├── cpp-include.rs │ │ ├── cpp_code.rs │ │ ├── map_type.rs │ │ ├── mod.rs │ │ ├── rust_option.h │ │ ├── rust_result.h │ │ ├── rust_str.h │ │ └── rust_vec.h │ ├── errors.rs │ ├── file_cache.rs │ ├── java_jni │ │ ├── java_code.rs │ │ ├── jni-include.rs │ │ ├── mod.rs │ │ └── rust_code.rs │ ├── lib.rs │ ├── main.rs │ ├── my_ast.rs │ ├── parsing.rs │ ├── test_helper.rs │ └── types_conv_map │ │ ├── mod.rs │ │ ├── parsing.rs │ │ └── utils.rs └── tests │ ├── test_code_in_readme.rs │ ├── test_complex_cases.rs │ └── test_includes_syntax.rs ├── run-on-adroid.sh ├── settings.gradle └── src ├── android_c_headers.rs ├── cascade.rs ├── ios_c_headers.rs ├── java_glue.rs ├── java_glue.rs.in ├── lib.rs └── worker.rs /.cargo/config: -------------------------------------------------------------------------------- 1 | #[target.aarch64-linux-android] 2 | #linker = "" 3 | #runner = "./run-on-adroid.sh" 4 | 5 | [target.arm-linux-androideabi] 6 | linker = "./xtoolchains/android-27-arm-linux-androideabi-4.9/bin/clang" 7 | runner = "./run-on-adroid.sh" 8 | 9 | [target.i686-linux-android] 10 | linker = "./xtoolchains/android-27-x86-4.9/bin/clang" 11 | runner = "./run-on-adroid.sh" 12 | 13 | [target.x86_64-linux-android] 14 | linker = "./xtoolchains/android-27-x86_64-4.9/bin/clang" 15 | runner = "./run-on-adroid.sh" 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "android" 3 | version = "0.0.1" 4 | authors = ["Evgeniy A. Dushistov "] 5 | build = "build.rs" 6 | 7 | [lib] 8 | name = "mobcore" 9 | crate-type = ["cdylib", "staticlib"] 10 | 11 | [dependencies] 12 | log = "0.4" 13 | log-panics = "2.0" 14 | foreign-types = "0.3.0" 15 | 16 | [target.'cfg(target_os = "ios")'.dependencies] 17 | libc = "0.2" 18 | core-foundation = "0.6.2" 19 | 20 | [target.'cfg(target_os = "android")'.dependencies] 21 | android_logger = "0.5" 22 | 23 | [build-dependencies] 24 | #bindgen = "0.37.4" 25 | bindgen = "0.42.2" 26 | syntex = "0.58" 27 | walkdir = "2" 28 | cbindgen = "0.6.0" 29 | rust_swig = { path = "macroslib" } 30 | 31 | [profile.dev] 32 | opt-level = 0 33 | debug = true 34 | rpath = false 35 | lto = false 36 | codegen-units = 8 37 | panic = 'unwind' 38 | incremental = true 39 | overflow-checks = true 40 | 41 | [profile.release] 42 | opt-level = 3 43 | debug = false 44 | rpath = false 45 | lto = true 46 | codegen-units = 1 47 | panic = 'unwind' 48 | incremental = false 49 | overflow-checks = false 50 | -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4DC153E1216BEAB0000EB215 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC153E0216BEAB0000EB215 /* AppDelegate.swift */; }; 11 | 4DC153E3216BEAB0000EB215 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC153E2216BEAB0000EB215 /* ViewController.swift */; }; 12 | 4DC153E6216BEAB0000EB215 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DC153E4216BEAB0000EB215 /* Main.storyboard */; }; 13 | 4DC153E8216BEAB1000EB215 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4DC153E7216BEAB1000EB215 /* Assets.xcassets */; }; 14 | 4DC153EB216BEAB1000EB215 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DC153E9216BEAB1000EB215 /* LaunchScreen.storyboard */; }; 15 | 4DC15400216D25B5000EB215 /* libmobcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DC153FF216D25B5000EB215 /* libmobcore.a */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 4DC153F8216D251F000EB215 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 4DC153D5216BEAB0000EB215 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 4DC153F2216BEC11000EB215; 24 | remoteInfo = mobcore; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 4DC153DD216BEAB0000EB215 /* MobileApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MobileApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 4DC153E0216BEAB0000EB215 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 31 | 4DC153E2216BEAB0000EB215 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 32 | 4DC153E5216BEAB0000EB215 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 33 | 4DC153E7216BEAB1000EB215 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 34 | 4DC153EA216BEAB1000EB215 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 35 | 4DC153EC216BEAB1000EB215 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 4DC153F6216BEC71000EB215 /* build-rust-xcode.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-rust-xcode.sh"; sourceTree = ""; }; 37 | 4DC153FB216D257E000EB215 /* libmobcore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmobcore.dylib; path = ../target/debug/libmobcore.dylib; sourceTree = ""; }; 38 | 4DC153FC216D257E000EB215 /* libmobcore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmobcore.a; path = ../target/debug/libmobcore.a; sourceTree = ""; }; 39 | 4DC153FF216D25B5000EB215 /* libmobcore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmobcore.a; path = "../target/x86_64-apple-ios/debug/libmobcore.a"; sourceTree = ""; }; 40 | 4DC15401216D260B000EB215 /* mobileapp-ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "mobileapp-ios.h"; path = "../target/mobileapp-ios.h"; sourceTree = ""; }; 41 | 4DC15402216D262A000EB215 /* Rust-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Rust-Bridging-Header.h"; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 4DC153DA216BEAB0000EB215 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | 4DC15400216D25B5000EB215 /* libmobcore.a in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 4DC153D4216BEAB0000EB215 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 4DC15402216D262A000EB215 /* Rust-Bridging-Header.h */, 60 | 4DC153FF216D25B5000EB215 /* libmobcore.a */, 61 | 4DC15401216D260B000EB215 /* mobileapp-ios.h */, 62 | 4DC153F6216BEC71000EB215 /* build-rust-xcode.sh */, 63 | 4DC153DF216BEAB0000EB215 /* MobileApp */, 64 | 4DC153DE216BEAB0000EB215 /* Products */, 65 | 4DC153FA216D257D000EB215 /* Frameworks */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | 4DC153DE216BEAB0000EB215 /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 4DC153DD216BEAB0000EB215 /* MobileApp.app */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 4DC153DF216BEAB0000EB215 /* MobileApp */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 4DC153E0216BEAB0000EB215 /* AppDelegate.swift */, 81 | 4DC153E2216BEAB0000EB215 /* ViewController.swift */, 82 | 4DC153E4216BEAB0000EB215 /* Main.storyboard */, 83 | 4DC153E7216BEAB1000EB215 /* Assets.xcassets */, 84 | 4DC153E9216BEAB1000EB215 /* LaunchScreen.storyboard */, 85 | 4DC153EC216BEAB1000EB215 /* Info.plist */, 86 | ); 87 | path = MobileApp; 88 | sourceTree = ""; 89 | }; 90 | 4DC153FA216D257D000EB215 /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 4DC153FC216D257E000EB215 /* libmobcore.a */, 94 | 4DC153FB216D257E000EB215 /* libmobcore.dylib */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | /* End PBXGroup section */ 100 | 101 | /* Begin PBXLegacyTarget section */ 102 | 4DC153F2216BEC11000EB215 /* mobcore */ = { 103 | isa = PBXLegacyTarget; 104 | buildArgumentsString = "\"$(SRCROOT)/build-rust-xcode.sh\""; 105 | buildConfigurationList = 4DC153F3216BEC12000EB215 /* Build configuration list for PBXLegacyTarget "mobcore" */; 106 | buildPhases = ( 107 | ); 108 | buildToolPath = /bin/bash; 109 | buildWorkingDirectory = ../; 110 | dependencies = ( 111 | ); 112 | name = mobcore; 113 | passBuildSettingsInEnvironment = 1; 114 | productName = mobcore; 115 | }; 116 | /* End PBXLegacyTarget section */ 117 | 118 | /* Begin PBXNativeTarget section */ 119 | 4DC153DC216BEAB0000EB215 /* MobileApp */ = { 120 | isa = PBXNativeTarget; 121 | buildConfigurationList = 4DC153EF216BEAB1000EB215 /* Build configuration list for PBXNativeTarget "MobileApp" */; 122 | buildPhases = ( 123 | 4DC153D9216BEAB0000EB215 /* Sources */, 124 | 4DC153DA216BEAB0000EB215 /* Frameworks */, 125 | 4DC153DB216BEAB0000EB215 /* Resources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | 4DC153F9216D251F000EB215 /* PBXTargetDependency */, 131 | ); 132 | name = MobileApp; 133 | productName = MobileApp; 134 | productReference = 4DC153DD216BEAB0000EB215 /* MobileApp.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 4DC153D5216BEAB0000EB215 /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastSwiftUpdateCheck = 1000; 144 | LastUpgradeCheck = 1000; 145 | ORGANIZATIONNAME = "Benedikt Terhechte"; 146 | TargetAttributes = { 147 | 4DC153DC216BEAB0000EB215 = { 148 | CreatedOnToolsVersion = 10.0; 149 | }; 150 | 4DC153F2216BEC11000EB215 = { 151 | CreatedOnToolsVersion = 10.0; 152 | }; 153 | }; 154 | }; 155 | buildConfigurationList = 4DC153D8216BEAB0000EB215 /* Build configuration list for PBXProject "MobileApp" */; 156 | compatibilityVersion = "Xcode 9.3"; 157 | developmentRegion = en; 158 | hasScannedForEncodings = 0; 159 | knownRegions = ( 160 | en, 161 | Base, 162 | ); 163 | mainGroup = 4DC153D4216BEAB0000EB215; 164 | productRefGroup = 4DC153DE216BEAB0000EB215 /* Products */; 165 | projectDirPath = ""; 166 | projectRoot = ""; 167 | targets = ( 168 | 4DC153DC216BEAB0000EB215 /* MobileApp */, 169 | 4DC153F2216BEC11000EB215 /* mobcore */, 170 | ); 171 | }; 172 | /* End PBXProject section */ 173 | 174 | /* Begin PBXResourcesBuildPhase section */ 175 | 4DC153DB216BEAB0000EB215 /* Resources */ = { 176 | isa = PBXResourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | 4DC153EB216BEAB1000EB215 /* LaunchScreen.storyboard in Resources */, 180 | 4DC153E8216BEAB1000EB215 /* Assets.xcassets in Resources */, 181 | 4DC153E6216BEAB0000EB215 /* Main.storyboard in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXSourcesBuildPhase section */ 188 | 4DC153D9216BEAB0000EB215 /* Sources */ = { 189 | isa = PBXSourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | 4DC153E3216BEAB0000EB215 /* ViewController.swift in Sources */, 193 | 4DC153E1216BEAB0000EB215 /* AppDelegate.swift in Sources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXSourcesBuildPhase section */ 198 | 199 | /* Begin PBXTargetDependency section */ 200 | 4DC153F9216D251F000EB215 /* PBXTargetDependency */ = { 201 | isa = PBXTargetDependency; 202 | target = 4DC153F2216BEC11000EB215 /* mobcore */; 203 | targetProxy = 4DC153F8216D251F000EB215 /* PBXContainerItemProxy */; 204 | }; 205 | /* End PBXTargetDependency section */ 206 | 207 | /* Begin PBXVariantGroup section */ 208 | 4DC153E4216BEAB0000EB215 /* Main.storyboard */ = { 209 | isa = PBXVariantGroup; 210 | children = ( 211 | 4DC153E5216BEAB0000EB215 /* Base */, 212 | ); 213 | name = Main.storyboard; 214 | sourceTree = ""; 215 | }; 216 | 4DC153E9216BEAB1000EB215 /* LaunchScreen.storyboard */ = { 217 | isa = PBXVariantGroup; 218 | children = ( 219 | 4DC153EA216BEAB1000EB215 /* Base */, 220 | ); 221 | name = LaunchScreen.storyboard; 222 | sourceTree = ""; 223 | }; 224 | /* End PBXVariantGroup section */ 225 | 226 | /* Begin XCBuildConfiguration section */ 227 | 4DC153ED216BEAB1000EB215 /* Debug */ = { 228 | isa = XCBuildConfiguration; 229 | buildSettings = { 230 | ALWAYS_SEARCH_USER_PATHS = NO; 231 | CLANG_ANALYZER_NONNULL = YES; 232 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 233 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 234 | CLANG_CXX_LIBRARY = "libc++"; 235 | CLANG_ENABLE_MODULES = YES; 236 | CLANG_ENABLE_OBJC_ARC = YES; 237 | CLANG_ENABLE_OBJC_WEAK = YES; 238 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 239 | CLANG_WARN_BOOL_CONVERSION = YES; 240 | CLANG_WARN_COMMA = YES; 241 | CLANG_WARN_CONSTANT_CONVERSION = YES; 242 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INFINITE_RECURSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 250 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 251 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 254 | CLANG_WARN_STRICT_PROTOTYPES = YES; 255 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 256 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 257 | CLANG_WARN_UNREACHABLE_CODE = YES; 258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 259 | CODE_SIGN_IDENTITY = "iPhone Developer"; 260 | COPY_PHASE_STRIP = NO; 261 | DEBUG_INFORMATION_FORMAT = dwarf; 262 | ENABLE_STRICT_OBJC_MSGSEND = YES; 263 | ENABLE_TESTABILITY = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu11; 265 | GCC_DYNAMIC_NO_PIC = NO; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_OPTIMIZATION_LEVEL = 0; 268 | GCC_PREPROCESSOR_DEFINITIONS = ( 269 | "DEBUG=1", 270 | "$(inherited)", 271 | ); 272 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 274 | GCC_WARN_UNDECLARED_SELECTOR = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 276 | GCC_WARN_UNUSED_FUNCTION = YES; 277 | GCC_WARN_UNUSED_VARIABLE = YES; 278 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 279 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 280 | MTL_FAST_MATH = YES; 281 | ONLY_ACTIVE_ARCH = YES; 282 | SDKROOT = iphoneos; 283 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 284 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 285 | }; 286 | name = Debug; 287 | }; 288 | 4DC153EE216BEAB1000EB215 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | CLANG_ANALYZER_NONNULL = YES; 293 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_MODULES = YES; 297 | CLANG_ENABLE_OBJC_ARC = YES; 298 | CLANG_ENABLE_OBJC_WEAK = YES; 299 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 300 | CLANG_WARN_BOOL_CONVERSION = YES; 301 | CLANG_WARN_COMMA = YES; 302 | CLANG_WARN_CONSTANT_CONVERSION = YES; 303 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INFINITE_RECURSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 311 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 312 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 313 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 315 | CLANG_WARN_STRICT_PROTOTYPES = YES; 316 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 317 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | CODE_SIGN_IDENTITY = "iPhone Developer"; 321 | COPY_PHASE_STRIP = NO; 322 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 323 | ENABLE_NS_ASSERTIONS = NO; 324 | ENABLE_STRICT_OBJC_MSGSEND = YES; 325 | GCC_C_LANGUAGE_STANDARD = gnu11; 326 | GCC_NO_COMMON_BLOCKS = YES; 327 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 328 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 329 | GCC_WARN_UNDECLARED_SELECTOR = YES; 330 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 331 | GCC_WARN_UNUSED_FUNCTION = YES; 332 | GCC_WARN_UNUSED_VARIABLE = YES; 333 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 334 | MTL_ENABLE_DEBUG_INFO = NO; 335 | MTL_FAST_MATH = YES; 336 | SDKROOT = iphoneos; 337 | SWIFT_COMPILATION_MODE = wholemodule; 338 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 339 | VALIDATE_PRODUCT = YES; 340 | }; 341 | name = Release; 342 | }; 343 | 4DC153F0216BEAB1000EB215 /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 347 | CODE_SIGN_STYLE = Automatic; 348 | DEVELOPMENT_TEAM = 8TL75556TP; 349 | INFOPLIST_FILE = MobileApp/Info.plist; 350 | LD_RUNPATH_SEARCH_PATHS = ( 351 | "$(inherited)", 352 | "@executable_path/Frameworks", 353 | ); 354 | LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../target/x86_64-apple-ios/debug"; 355 | PRODUCT_BUNDLE_IDENTIFIER = com.stylemac.MobileApp; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/Rust-Bridging-Header.h"; 358 | SWIFT_VERSION = 4.2; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Debug; 362 | }; 363 | 4DC153F1216BEAB1000EB215 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 367 | CODE_SIGN_STYLE = Automatic; 368 | DEVELOPMENT_TEAM = 8TL75556TP; 369 | INFOPLIST_FILE = MobileApp/Info.plist; 370 | LD_RUNPATH_SEARCH_PATHS = ( 371 | "$(inherited)", 372 | "@executable_path/Frameworks", 373 | ); 374 | LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../target/x86_64-apple-ios/debug"; 375 | PRODUCT_BUNDLE_IDENTIFIER = com.stylemac.MobileApp; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/Rust-Bridging-Header.h"; 378 | SWIFT_VERSION = 4.2; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Release; 382 | }; 383 | 4DC153F4216BEC12000EB215 /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | CODE_SIGN_STYLE = Automatic; 387 | DEBUGGING_SYMBOLS = YES; 388 | DEBUG_INFORMATION_FORMAT = dwarf; 389 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 390 | GCC_OPTIMIZATION_LEVEL = 0; 391 | OTHER_CFLAGS = ""; 392 | OTHER_LDFLAGS = ""; 393 | PRODUCT_NAME = "$(TARGET_NAME)"; 394 | }; 395 | name = Debug; 396 | }; 397 | 4DC153F5216BEC12000EB215 /* Release */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | CODE_SIGN_STYLE = Automatic; 401 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 402 | OTHER_CFLAGS = ""; 403 | OTHER_LDFLAGS = ""; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | }; 406 | name = Release; 407 | }; 408 | /* End XCBuildConfiguration section */ 409 | 410 | /* Begin XCConfigurationList section */ 411 | 4DC153D8216BEAB0000EB215 /* Build configuration list for PBXProject "MobileApp" */ = { 412 | isa = XCConfigurationList; 413 | buildConfigurations = ( 414 | 4DC153ED216BEAB1000EB215 /* Debug */, 415 | 4DC153EE216BEAB1000EB215 /* Release */, 416 | ); 417 | defaultConfigurationIsVisible = 0; 418 | defaultConfigurationName = Release; 419 | }; 420 | 4DC153EF216BEAB1000EB215 /* Build configuration list for PBXNativeTarget "MobileApp" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | 4DC153F0216BEAB1000EB215 /* Debug */, 424 | 4DC153F1216BEAB1000EB215 /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | 4DC153F3216BEC12000EB215 /* Build configuration list for PBXLegacyTarget "mobcore" */ = { 430 | isa = XCConfigurationList; 431 | buildConfigurations = ( 432 | 4DC153F4216BEC12000EB215 /* Debug */, 433 | 4DC153F5216BEC12000EB215 /* Release */, 434 | ); 435 | defaultConfigurationIsVisible = 0; 436 | defaultConfigurationName = Release; 437 | }; 438 | /* End XCConfigurationList section */ 439 | }; 440 | rootObject = 4DC153D5216BEAB0000EB215 /* Project object */; 441 | } 442 | -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/project.xcworkspace/xcuserdata/terhechte.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/MobileApp/MobileApp.xcodeproj/project.xcworkspace/xcuserdata/terhechte.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/xcuserdata/terhechte.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /MobileApp/MobileApp.xcodeproj/xcuserdata/terhechte.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MobileApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | mobcore.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /MobileApp/MobileApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // MobileApp 4 | // 5 | // Created by Benedikt Terhechte on 08.10.18. 6 | // Copyright © 2018 Benedikt Terhechte. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /MobileApp/MobileApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /MobileApp/MobileApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MobileApp/MobileApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /MobileApp/MobileApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /MobileApp/MobileApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /MobileApp/MobileApp/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class ViewController: UIViewController { 4 | 5 | @IBOutlet var actionLabel: UILabel? 6 | 7 | override func viewDidLoad() { 8 | super.viewDidLoad() 9 | 10 | // Create a session 11 | let session = session_new() 12 | 13 | // Call the action method 14 | let string = session_action(session!, "Hello World")!.takeRetainedValue() 15 | 16 | // Apply string to UI 17 | let s = string as NSString 18 | self.actionLabel?.text = s as String 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /MobileApp/Rust-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Rust-Bridging-Header.h 3 | // MobileApp 4 | // 5 | // Created by Benedikt Terhechte on 09.10.18. 6 | // Copyright © 2018 Benedikt Terhechte. All rights reserved. 7 | // 8 | 9 | #ifndef Rust_Bridging_Header_h 10 | #define Rust_Bridging_Header_h 11 | 12 | #import "mobileapp-ios.h" 13 | 14 | #endif /* Rust_Bridging_Header_h */ 15 | -------------------------------------------------------------------------------- /MobileApp/build-rust-xcode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Lifted from xi-mac editor 4 | 5 | # When building from Xcode we want to ensure that `cargo` is in PATH. 6 | # as a convenience, add the default cargo install location 7 | export PATH="$PATH:${HOME}/.cargo/bin" 8 | 9 | set -e 10 | set -x 11 | 12 | function build_target () { 13 | TARGET_NAME="$1" 14 | CARGO_PROJECT_FLAG="$2" 15 | cd "${SRCROOT}/../" 16 | if [[ ${ACTION:-build} = "build" ]]; then 17 | if [[ $PLATFORM_NAME = "" ]]; then 18 | # default for building with xcodebuild 19 | PLATFORM_NAME="macosx" 20 | fi 21 | 22 | if [[ $PLATFORM_NAME = "macosx" ]]; then 23 | RUST_TARGET_OS="darwin" 24 | else 25 | RUST_TARGET_OS="ios" 26 | fi 27 | 28 | for ARCH in $ARCHS 29 | do 30 | if [[ $(lipo -info "${BUILT_PRODUCTS_DIR}/${TARGET_NAME}" 2>&1) != *"${ARCH}"* ]]; then 31 | rm -f "${BUILT_PRODUCTS_DIR}/${TARGET_NAME}" 32 | fi 33 | done 34 | 35 | if [[ $CONFIGURATION = "Debug" ]]; then 36 | RUST_CONFIGURATION="debug" 37 | RUST_CONFIGURATION_FLAG="" 38 | else 39 | RUST_CONFIGURATION="release" 40 | RUST_CONFIGURATION_FLAG="--release" 41 | fi 42 | 43 | EXECUTABLES=() 44 | for ARCH in $ARCHS 45 | do 46 | RUST_ARCH=$ARCH 47 | if [[ $RUST_ARCH = "arm64" ]]; then 48 | RUST_ARCH="aarch64" 49 | fi 50 | env 51 | cargo build $RUST_CONFIGURATION_FLAG $CARGO_PROJECT_FLAG --target "${RUST_ARCH}-apple-${RUST_TARGET_OS}" 52 | EXECUTABLES+=("target/${RUST_ARCH}-apple-${RUST_TARGET_OS}/${RUST_CONFIGURATION}/${TARGET_NAME}") 53 | done 54 | 55 | #mkdir -p "${BUILT_PRODUCTS_DIR}" 56 | #xcrun --sdk $PLATFORM_NAME lipo -create "${EXECUTABLES[@]}" -output "${BUILT_PRODUCTS_DIR}/${TARGET_NAME}" 57 | elif [[ $ACTION = "clean" ]]; then 58 | cargo clean 59 | rm -f "${BUILT_PRODUCTS_DIR}/${TARGET_NAME}" 60 | fi 61 | } 62 | 63 | build_target mobcore "" 64 | 65 | set +e 66 | set +x 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an old fork of [https://github.com/rust-windowing/android-rs-glue](https://github.com/rust-windowing/android-rs-glue) in order to add Swift / iOS support. Ignore the Android parts (use the above-linked android-rs-glue instead). The Swift/iOS part is maybe useful. What it does is the following: 2 | 3 | - Add `C` bindings to Rust types (via Repr(C) and `cbindgen`) in [ios_c_headers.rs](https://github.com/terhechte/rust-ios-android-example/blob/master/src/ios_c_headers.rs) 4 | - Add Xcode Project [MobileApp](MobileApp) 5 | - Add a [build script to the Xcode project that automatically compiles Rust as a dependency](MobileApp/https://github.com/terhechte/rust-ios-android-example/blob/master/MobileApp/build-rust-xcode.sh) (Shamelessly pulled from XI-Mac) 6 | - Configure the Rust [build.rs](https://github.com/terhechte/rust-ios-android-example/blob/master/build.rs) script to also create a C header file in `target/mobileapp-ios.h` (created on each compile) 7 | - Add that `mobileapp-ios.h` to the Xcode project and import it 8 | - Finally, use the imported Rust in the [ViewController](MobileApp/MobileApp/ViewController.swift) 9 | 10 | This is all a bit undocumented. I always wanted to clean it up, but never did so. 11 | 12 | # Prerequisites 13 | 14 | ## iOS 15 | ``` 16 | rustup target add x86_64-apple-ios 17 | rustup target add aarch64-apple-ios 18 | ``` 19 | 20 | ## Android 21 | 22 | 1. Android SDK (w/ Android Studio) 23 | 2. Android NDK (might not be necessary, just a 500mb download, no installation required) 24 | 3. the following env needs to be set: 25 | ``` 26 | ANDROID_HOME=/Users/terhechte/Library/Android/sdk/ 27 | ``` 28 | (or wherever the android SDK is installed) i.e. `set -x ANDROID_HOME /sdjkl` 29 | 4. `PATH` should also contain `/Users/terhechte/Library/Android/sdk/platform-tools/` 30 | (i.e. sdk platform-tools) so that the `adb` command is in path 31 | 32 | 5. Do all the stuff explained below 33 | 34 | 6. Make sure you have a running emulator 35 | ``` 36 | /Users/terhechte/Library/Android/sdk/emulator 37 | ./emulator -list-avds 38 | ./emulator -avd Nexus_5X_API_28 39 | ``` 40 | (or where you installed the sdk, and which emulator you installed via android studio) 41 | 42 | 7. To run on the device do `./run-on-android.sh` This will build, install, run 43 | 44 | # Android Example 45 | 46 | This example shows off how to use rust to build a native library from android 47 | and use it through an automatically generated JNI wrapper. 48 | 49 | ## Project Structure 50 | 51 | The file `build.rs` defines how rust_swig generates wrapper code. It 52 | automatically finds a suitable `jni.h` and generates a rust source file against 53 | it. Then, the script recursively looks for files ending in `.rs.in` in the 54 | source directory and uses rust_swig to generate a JNI wrapper both in Rust and 55 | in Java. 56 | 57 | This build script is intended to be launched from gradle through e.g. `./gradlew 58 | aR`. The gradle build files contain definitions on how to build the Rust 59 | libraries and where to find them for inclusion in the apk. 60 | 61 | ## Building 62 | 63 | ### Prerequisites 64 | To build the demo, you will need the latest version of Cargo and at least rustc 65 | 1.16. You will also need to add support for android targets: 66 | 67 | ``` shell 68 | rustup target add arm-linux-androideabi 69 | rustup target add aarch64-linux-android 70 | rustup target add i686-linux-android 71 | rustup target add x86_64-linux-android 72 | ``` 73 | 74 | To link the libraries, you will need the android NDK and generate standalone 75 | toolchains for each target (edit the install dir as required): 76 | 77 | Some env variables need to be present: 78 | ``` shell 79 | # The Android NDK 80 | set -x ANDROID_NDK ~/Desktop/android-ndk-r18/ 81 | ``` 82 | 83 | ``` shell 84 | # Where you want the Android toolchains to be installed 85 | # folder has to be created 86 | set -x ANDROID_TOOLCHAINS ~/Desktop/Archive/mobilecore-rust/xtoolchains/ 87 | ``` 88 | (use eval on fish) 89 | ``` shell 90 | # ARM 91 | $ANDROID_NDK/build/tools/make-standalone-toolchain.sh --platform="android-27" --toolchain=arm-linux-androideabi-4.9 --install-dir=$ANDROID_TOOLCHAINS/android-27-arm-linux-androideabi-4.9 --arch=arm 92 | $ANDROID_NDK/build/tools/make-standalone-toolchain.sh --platform="android-27" --toolchain=aarch64-linux-android-4.9 --install-dir=$ANDROID_TOOLCHAINS/android-27-aarch64-linux-android-4.9 --arch=aarch64 93 | 94 | # x86 95 | $ANDROID_NDK/build/tools/make-standalone-toolchain.sh --platform="android-27" --toolchain=x86-4.9 --install-dir=$ANDROID_TOOLCHAINS/android-27-x86-4.9 --arch=x86 96 | $ANDROID_NDK/build/tools/make-standalone-toolchain.sh --platform="android-27" --toolchain=x86_64-4.9 --install-dir=$ANDROID_TOOLCHAINS/android-27-x86_64-4.9 --arch=x86_64 97 | ``` 98 | 99 | Then edit `.cargo/config` to point to the toolchains you just generated. 100 | 101 | Finally, wrapping Rust around `jni.h` depends on bindgen, for which you will 102 | need libclang installed on your machine. 103 | 104 | ### Invocation 105 | 106 | Gradle will take care of building and deploying the Rust sources. Thus, to build 107 | the project in release mode, simply call `./gradlew androidRelease`. 108 | 109 | To build only the rust libraries for a specific target, call cargo as usual, e.g. 110 | `cargo build --target arm-linux-androideabi`. 111 | -------------------------------------------------------------------------------- /android-example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion "27.0.3" 6 | defaultConfig { 7 | applicationId "me.appventure.mobileapp" 8 | minSdkVersion 16 9 | targetSdkVersion 27 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | sourceSets { 16 | main { 17 | jni.srcDirs = [] 18 | jniLibs.srcDir 'src/main/libs' 19 | } 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled true 25 | shrinkResources true 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 34 | exclude group: 'com.android.support', module: 'support-annotations' 35 | }) 36 | api 'com.android.support:appcompat-v7:27.+' 37 | api 'com.android.support.constraint:constraint-layout:1.1.0' 38 | api 'com.android.support:design:27.+' 39 | testImplementation 'junit:junit:4.12' 40 | } 41 | 42 | def rustBasePath = ".." 43 | def cargoOutputDir = "${rustBasePath}/target" 44 | def archTriplets = ['armeabi': 'arm-linux-androideabi', 45 | //'arm64': 'aarch64-linux-android', 46 | //'x86': 'i686-linux-android', 47 | 'x86_64': 'x86_64-linux-android'] 48 | 49 | // TODO: only pass --release if buildType is release 50 | archTriplets.each { arch, target -> 51 | // Build with cargo 52 | tasks.create(name: "cargo-build-${arch}", type: Exec, description: "Building core for ${arch}") { 53 | workingDir rustBasePath 54 | commandLine 'cargo', 'build', "--target=${target}", '--release' 55 | } 56 | // Sync shared native dependencies 57 | tasks.create(name: "sync-rust-deps-${arch}", type: Sync, dependsOn: "cargo-build-${arch}") { 58 | from "${rustBasePath}/src/libs/${arch}" 59 | include "*.so" 60 | into "src/main/libs/${arch}" 61 | } 62 | // Copy build libs into this app's libs directory 63 | tasks.create(name: "rust-deploy-${arch}", type: Copy, dependsOn: "sync-rust-deps-${arch}", description: "Copy rust libs for (${arch}) to jniLibs") { 64 | from "${cargoOutputDir}/${target}/release" 65 | include "*.so" 66 | into "src/main/libs/${arch}" 67 | } 68 | 69 | // Hook up tasks to execute before building java 70 | tasks.withType(JavaCompile) { 71 | compileTask -> compileTask.dependsOn "rust-deploy-${arch}" 72 | } 73 | preBuild.dependsOn "rust-deploy-${arch}" 74 | 75 | // Hook up clean tasks 76 | tasks.create(name: "clean-${arch}", type: Delete, description: "Deleting built libs for ${arch}") { 77 | delete fileTree("${cargoOutputDir}/${target}/release") { 78 | include '*.so' 79 | } 80 | } 81 | clean.dependsOn "clean-${arch}" 82 | } 83 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/evgeniy/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/appventure/mobileapp/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package me.appventure.mobileapp; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("me.appventure.mobileapp", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/me/appventure/mobileapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.appventure.mobileapp; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | doSetup(); 19 | 20 | 21 | final TextView label = (TextView) findViewById(R.id.greetingLabel); 22 | 23 | 24 | // create a new worker and call it 25 | final Worker worker = new Worker(); 26 | 27 | // assign the result 28 | label.setText(worker.action("Hello World")); 29 | } 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | @Override 51 | public boolean onCreateOptionsMenu(Menu menu) { 52 | // Inflate the menu; this adds items to the action bar if it is present. 53 | getMenuInflater().inflate(R.menu.menu_main, menu); 54 | return true; 55 | } 56 | 57 | @Override 58 | public boolean onOptionsItemSelected(MenuItem item) { 59 | // Handle action bar item clicks here. The action bar will 60 | // automatically handle clicks on the Home/Up button, so long 61 | // as you specify a parent activity in AndroidManifest.xml. 62 | int id = item.getItemId(); 63 | 64 | //noinspection SimplifiableIfStatement 65 | if (id == R.id.action_settings) { 66 | return true; 67 | } 68 | 69 | return super.onOptionsItemSelected(item); 70 | } 71 | 72 | void doSetup() { 73 | setContentView(R.layout.activity_main); 74 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 75 | setSupportActionBar(toolbar); 76 | 77 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 78 | fab.setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View view) { 81 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 82 | .setAction("Action", null).show(); 83 | } 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/me/appventure/mobileapp/MobileApp.java: -------------------------------------------------------------------------------- 1 | package me.appventure.mobileapp; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | /** 7 | * Created by evgeniy on 16.03.17. 8 | */ 9 | 10 | public final class MobileApp extends Application { 11 | private static MobileApp sSelf; 12 | private Worker mWorker; 13 | private static final String TAG = "exm MobileApp"; 14 | 15 | public MobileApp() { 16 | super(); 17 | sSelf = this; 18 | } 19 | 20 | @Override 21 | public void onCreate() { 22 | Log.i(TAG, "onCreate"); 23 | super.onCreate(); 24 | try { 25 | System.loadLibrary("mobcore"); 26 | } catch (UnsatisfiedLinkError e) { 27 | Log.e(TAG, "Load libary ERROR: " + e); 28 | return; 29 | } 30 | mWorker = new Worker(); 31 | } 32 | 33 | public static MobileApp get() { 34 | return sSelf; 35 | } 36 | 37 | public Worker getWorker() { 38 | return mWorker; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/me/appventure/mobileapp/Worker.java: -------------------------------------------------------------------------------- 1 | // Automaticaly generated by rust_swig 2 | package me.appventure.mobileapp; 3 | import android.support.annotation.NonNull; 4 | 5 | public final class Worker { 6 | 7 | public Worker() { 8 | 9 | mNativeObj = init(); 10 | } 11 | private static native long init() ; 12 | 13 | public final String action(@NonNull String a0) { 14 | 15 | return do_action(mNativeObj, a0); 16 | } 17 | private static native String do_action(long me, String a0) ; 18 | 19 | public synchronized void delete() { 20 | if (mNativeObj != 0) { 21 | do_delete(mNativeObj); 22 | mNativeObj = 0; 23 | } 24 | } 25 | @Override 26 | protected void finalize() throws Throwable { 27 | try { 28 | delete(); 29 | } 30 | finally { 31 | super.finalize(); 32 | } 33 | } 34 | private static native void do_delete(long me); 35 | /*package*/ long mNativeObj; 36 | } -------------------------------------------------------------------------------- /app/src/main/libs/armeabi/libmobcore.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/libs/armeabi/libmobcore.so -------------------------------------------------------------------------------- /app/src/main/libs/x86_64/libmobcore.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/libs/x86_64/libmobcore.so -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 23 | 24 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terhechte/rust-ios-android-example/4423149df22186eff56e1ccc65deb797865334b5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | My Application 3 | Settings 4 | We can do math in Rust and get %1$d 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |