Files
vnidrop/apple/README.md
cdricms 5f5f7e0515 chore(apple): drop the unused SwiftPM manifest
Package.swift named its module VniDropApp while all 16 test files import
VniDrop, and it never declared the SFSafeSymbols dependency that project.yml
links, so neither swift build nor swift test worked. The Xcode project is
already the only functioning build definition for the UI and the tests.

Removes a second dependency list that had drifted, and corrects the README,
which documented the CLI path as if it worked.
2026-08-06 17:21:51 +02:00

122 lines
5.5 KiB
Markdown

# VniDrop — native Apple app (iOS / iPadOS / macOS)
A native SwiftUI app for Apple platforms, sharing the existing Rust transfer core
(`crates/vnidrop`) through UniFFI-generated Swift bindings. The Rust crate is not
modified; the Kotlin/Compose app layer is ported to Swift and mirrors the Compose
UI screen-for-screen. Android, Windows, and Linux continue to use `shared/` + Compose.
## Layout
```
apple/
scripts/build-core.sh # builds the Rust core + generates Swift bindings + xcframework
VnidropCore/ # local SwiftPM package: xcframework + generated Vnidrop.swift
VniDrop/ # SwiftUI app sources
App/ # entry point, object graph, root view, environment
Core/ # repository, models, preferences, notifications, progress
Features/Send|Receive|Approvals|Settings/
UI/Theme|Components|Navigation|Feedback|Shell/
Platform/ # pickers, QR, NFC, share/export, per-OS file services
Resources/ # Localizable.xcstrings, Info.plist, entitlements, assets
Tests/ # XCTest bundle (VniDropTests target)
project.yml # XcodeGen spec for the iOS/macOS app and test targets
```
## Build & run
Prerequisites: Xcode, Rust with the Apple targets
(`aarch64-apple-ios`, `aarch64-apple-ios-sim`, `x86_64-apple-ios`,
`aarch64-apple-darwin`), and `xcodegen` (`brew install xcodegen`).
```bash
# From the repository root:
make apple-core # Rust core, Swift bindings, and XCFramework
make apple-project # generate apple/VniDrop.xcodeproj
make open-apple-project # generate and open the project in Xcode
make build-apple-macos # unsigned macOS build (App Store target)
make open-apple # build and launch the macOS app
make build-apple-ios # unsigned iOS simulator app
make check-apple # iOS simulator tests
```
`make apple-project` also generates ignored Store and Direct version xcconfig
files. Their `CURRENT_PROJECT_VERSION` values come from the central version
resolver as UTC `YYYYMMDD.HHMM.SS` build identifiers. Regenerate the project
before creating another App Store archive so it receives a fresh build number;
direct DMG builds refresh their own value automatically.
### macOS shipping channels
The macOS app ships through two targets that build identical sources:
- **`VniDrop`** (`Release`) — Mac App Store / TestFlight. Sandboxed, no
self-updater.
- **`VniDropDirect`** (`Release-Direct`) — direct-download `.dmg` on GitHub
Releases + Homebrew cask. Adds the **Sparkle** auto-updater behind the
`DIRECT_DISTRIBUTION` compile flag, so the App Store binary never links Sparkle.
```bash
make build-apple-macos-direct # unsigned compile-check of the direct target
make build-apple-dmg # signed (+ notarized) .dmg
```
Full signing, notarization, appcast, and cask flow: see
[`RELEASE-MACOS.md`](RELEASE-MACOS.md).
Use `APPLE_PROFILE=release` to request a release Rust core, or set
`APPLE_DESTINATION` to override the automatically selected iOS simulator.
Code signing is disabled for the app and test targets; local and CI builds do
not require an Apple Development team or provisioning profile. Make builds can
opt in with `APPLE_CODE_SIGNING=YES`. For signed builds from Xcode, create the
ignored `apple/Local.xcconfig` and override the signing settings there, including
the development team.
## Typecheck & tests
The Xcode project is the only build definition: it owns the UI, its package
dependencies, and the `VniDropTests` bundle (module `VniDrop`, which is what the
tests import). Everything runs through `xcodebuild`:
```bash
make check-apple # iOS simulator unit tests
make build-apple-macos # unsigned macOS build (typecheck)
```
There is deliberately no SwiftPM manifest for the app. A second build definition
would duplicate the target's package dependencies, and the previous one had
already drifted out of sync with `project.yml` badly enough that neither
`swift build` nor `swift test` worked.
## Generated / ignored artifacts
`build-core.sh` produces build outputs that are gitignored (see `apple/.gitignore`):
`VnidropCore/vnidrop.xcframework/`, `VnidropCore/Sources/VnidropCore/Vnidrop.swift`,
and `.build-core/`. A clean checkout must run `build-core.sh` before generating or
opening the Xcode project. `VniDrop.xcodeproj` itself is generated by XcodeGen from
`project.yml` and does not need to be committed.
## Build profile note
The default is `debug`. The workspace `[profile.release]` uses thin LTO, which the
current macOS toolchain miscompiles into corrupt host proc-macro dylibs
("mis-aligned LINKEDIT string pool"). `build-core.sh` sets
`CARGO_PROFILE_DEV_STRIP=none` (matching the existing Gobley Xcode run-script) so
debug builds succeed. For a release core, disable LTO for proc-macros/build
scripts (e.g. add a `[profile.release.build-override] lto = false` locally) — the
Rust crate itself is never changed.
## System frameworks
The Rust core (iroh network stack) links `SystemConfiguration`, `Security`, and
`libresolv`. These are declared in `project.yml` for the app target.
## Parity & scope
Screens mirror the Compose UI in `shared/`. Two deliberate simplifications:
- Empty-state Lottie animations are rendered as SF Symbols (no `lottie-ios`
dependency); swap in `lottie-ios` if exact-parity animation is required.
- Bug reporting is stubbed behind `BugReportService` (`NoopBugReportService`) and
a real transport lands in a later phase. There is no telemetry or crash
auto-reporting.
```