diff --git a/.gitignore b/.gitignore index 7922dd4..1d53b7e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ build/ local.properties jniLibs +# generated documentation from swift package generate-documentation +docs/ + # Kotlin Gradle plugin data # See https://kotlinlang.org/docs/whatsnew20.html#new-directory-for-kotlin-data-in-gradle-projects .kotlin/ diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..5b071ee --- /dev/null +++ b/Package.swift @@ -0,0 +1,16 @@ +// swift-tools-version: 6.0 + +import PackageDescription + +let package = Package( + name: "swift-android-examples", + products: [ + .library(name: "SwiftAndroid", targets: ["SwiftAndroid"]) + ], + dependencies: [ + .package( + url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0") + ], + targets: [ + .target(name: "SwiftAndroid") + ]) diff --git a/README.md b/README.md index 0742f37..fa33109 100644 --- a/README.md +++ b/README.md @@ -58,3 +58,14 @@ Examples using raw JNI, without generated bridging sources: - **[hello-swift-raw-jni](hello-swift-raw-jni/)** - basic Swift integration that calls a Swift function. - **[hello-swift-raw-jni-callback](hello-swift-raw-jni-callback/)** - demonstrates bidirectional communication with Swift timer callbacks updating Android UI. - **[hello-swift-raw-jni-library](hello-swift-raw-jni-library/)** - shows how to package Swift code as a reusable Android library component. + +## Documentation + +The `Sources/SwiftAndroid/Documentation.docc` directory contains a DocC documentation catalog for Swift on Android. To build and preview it locally: + +```shell +swift package generate-documentation --target SwiftAndroid --transform-for-static-hosting --output-path docs +python3 -m http.server 8000 --directory docs +``` + +Then open in your browser. diff --git a/Sources/SwiftAndroid/Documentation.docc/BuildingForAndroid.md b/Sources/SwiftAndroid/Documentation.docc/BuildingForAndroid.md new file mode 100644 index 0000000..530073b --- /dev/null +++ b/Sources/SwiftAndroid/Documentation.docc/BuildingForAndroid.md @@ -0,0 +1,45 @@ +# Building for Android + +Cross-compile Swift code and package it into Android applications + +## Overview + +Swift on Android uses cross-compilation: you build on a macOS or Linux host, and the compiler produces native ARM or x86_64 binaries targeting Android. + +```shell +$ swift build --swift-sdk aarch64-unknown-linux-android28 +``` + +## Conditional compilation + +Use `#if os(Android)` to conditionalize code for Android: + +```swift +#if os(Android) +import Android +#elseif canImport(Darwin) +import Darwin +#endif +``` + +## Foundation + +Foundation networking types require a separate import on non-Apple platforms: + +```swift +import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif +``` + +## JNI integration + +Export Swift functions for JNI using `@_cdecl`: + +```swift +@_cdecl("Java_com_example_MyClass_hello") +func hello(env: UnsafeMutablePointer, thisObj: jobject) -> jstring { + return env.pointee.pointee.NewStringUTF(env, "Hello from Swift")! +} +``` diff --git a/Sources/SwiftAndroid/Documentation.docc/Documentation.md b/Sources/SwiftAndroid/Documentation.docc/Documentation.md new file mode 100644 index 0000000..3943832 --- /dev/null +++ b/Sources/SwiftAndroid/Documentation.docc/Documentation.md @@ -0,0 +1,19 @@ +# Swift on Android + +Use Swift to build native libraries and applications for Android + +@Metadata { + @TechnologyRoot +} + +## Topics + +### Getting Started + +- +- + +### Guides + +- +- diff --git a/Sources/SwiftAndroid/Documentation.docc/GettingStarted.md b/Sources/SwiftAndroid/Documentation.docc/GettingStarted.md new file mode 100644 index 0000000..c876791 --- /dev/null +++ b/Sources/SwiftAndroid/Documentation.docc/GettingStarted.md @@ -0,0 +1,29 @@ +# Getting Started + +Install the Swift toolchain, Android NDK, and Swift SDK for Android + +## Overview + +Development requires three components: + +1. **Swift Toolchain** -- install with [swiftly](https://github.com/swiftlang/swiftly): `swiftly install latest` +2. **Android NDK** -- download from [developer.android.com](https://developer.android.com/ndk/downloads) (r27d+ recommended) +3. **Swift SDK for Android** -- install with `swift sdk install` (see [swift.org](https://www.swift.org/documentation/articles/swift-sdk-for-android-getting-started.html)) + +## Hello World + +```shell +$ swift package init --type executable +$ swift build --swift-sdk aarch64-unknown-linux-android28 +$ adb push .build/aarch64-unknown-linux-android28/debug/HelloWorld /data/local/tmp/ +$ adb shell /data/local/tmp/HelloWorld +Hello, world! +``` + +## Target triples + +| Architecture | Triple | +|---|---| +| ARM64 | `aarch64-unknown-linux-android28` | +| ARM32 | `armv7-unknown-linux-androideabi28` | +| x86_64 | `x86_64-unknown-linux-android28` | diff --git a/Sources/SwiftAndroid/Documentation.docc/Integration.md b/Sources/SwiftAndroid/Documentation.docc/Integration.md new file mode 100644 index 0000000..b8b98ce --- /dev/null +++ b/Sources/SwiftAndroid/Documentation.docc/Integration.md @@ -0,0 +1,29 @@ +# Integration + +Integrate Swift builds with Android tooling and frameworks + +## Gradle + +Add a custom Gradle task to invoke `swift build` and copy the resulting `.so` into `jniLibs/`: + +```kotlin +tasks.register("buildSwiftLibrary") { + workingDir = file("${rootDir}/swift") + commandLine("swift", "build", + "--swift-sdk", "aarch64-unknown-linux-android28", + "-c", "release", "--static-swift-stdlib") +} +``` + +## Swift Package Manager + +```shell +$ swift build --swift-sdk aarch64-unknown-linux-android28 +``` + +## Resources + +- [Swift SDK for Android -- Getting Started](https://www.swift.org/documentation/articles/swift-sdk-for-android-getting-started.html) +- [swift-java](https://github.com/swiftlang/swift-java) -- Java/Kotlin interop +- [swift-android-action](https://github.com/marketplace/actions/swift-android-action) -- GitHub Actions +- [Swift Forums](https://forums.swift.org/) diff --git a/Sources/SwiftAndroid/Documentation.docc/PortingPackages.md b/Sources/SwiftAndroid/Documentation.docc/PortingPackages.md new file mode 100644 index 0000000..3944136 --- /dev/null +++ b/Sources/SwiftAndroid/Documentation.docc/PortingPackages.md @@ -0,0 +1,27 @@ +# Porting Swift Packages to Android + +Adapt existing Swift packages to build and run on Android + +## Overview + +Many Swift packages build for Android with minimal changes. The typical process is: attempt a build, fix platform-specific code with conditional compilation, then test on a device. + +## Good candidates + +- Business logic, algorithms, data structures +- Networking and API clients +- Parsers, formatters, encoders/decoders +- SQLite and other database access + +## Conditional imports + +```swift +#if canImport(Darwin) +import Darwin +#elseif canImport(Android) +import Android +#elseif canImport(Glibc) +import Glibc +#endif +``` + diff --git a/Sources/SwiftAndroid/Empty.swift b/Sources/SwiftAndroid/Empty.swift new file mode 100644 index 0000000..114df8d --- /dev/null +++ b/Sources/SwiftAndroid/Empty.swift @@ -0,0 +1 @@ +// This file is included so SwiftPM considers the target to be a Swift target.