This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A SwiftPM binary-distribution wrapper around Google ML Kit. ML Kit ships only via CocoaPods, so this repo downloads those pods, rebuilds them with xcodebuild, converts them to XCFrameworks, zips them, publishes the zips as GitHub Release assets, and exposes 17 SwiftPM library products in Package.swift whose binaryTargets point at those zips.
This is not an app project. Almost all maintenance work happens in the build pipeline (Makefile, Podfile, Package.swift, Resources/*-Info.plist, scripts/*.rb), not in Swift sources. The only first-party Swift file is Sources/Common/export.swift (@_exported import MLKitCommon).
For deeper detail see AGENTS.md (short agent guide), AUTOMATION.md (full automation reference), TESTING.md (manual test checklist + known runtime issues), and scripts/README.md (per-script reference). Avoid duplicating their content here.
git submodule update --init— required before first build (initialisesxcframework-maker/)make bootstrap-builder— build thexcframework-makertool onlymake run— full pipeline: pod install → xcodebuild for both SDKs → inject Info.plists → create XCFrameworks → ar/ranlib FAT-object fix → zip everything intoGoogleMLKit/./build_with_asdf.sh— same asmake run, but sets up the asdf-shimmed Ruby first./scripts/build_all.sh <version>— bumpsPodfile+Resources/*-Info.plist, runsmake run, recomputes SHA256s, rewritesPackage.swiftbinary target URLs/checksums, verifies./scripts/batch_build.sh <v1> [v2] …— sequentialbuild_all.shover multiple versions with auto commit + tag
swift package dump-package— validatePackage.swiftsyntax (CI runs this too)ruby scripts/verify_build.rb— pre/post-flight (Info.plists present,xcframework-makerbuilt, zips present,Package.swiftparses)./scripts/verify_runtime.sh <version>— static checks on built XCFrameworks (architectures, embedded Info.plist, symbol table)ruby scripts/check_mlkit_version.rb— query the CocoaPods Trunk API for the latest GoogleMLKit version
ruby scripts/update_version.rb <version>— rewritePodfilepod versions andCFBundleShortVersionStringin everyResources/*-Info.plistruby scripts/update_checksums.rb <version>— recompute SHA256 of every zip inGoogleMLKit/, rewrite eachbinaryTarget(url:checksum:)inPackage.swift, and sync transitive Google deps fromPodfile.lockruby scripts/update_package_dependencies.rb— sync only the SwiftPMdependencies:block (GoogleDataTransport, GoogleUtilities, gtm-session-fetcher, promises, nanopb) fromPodfile.lock./scripts/upload_release.sh <version>— uploadGoogleMLKit/*.xcframework.zipto an existing GitHub Release (rungh release create <version>first if it doesn't exist)
cd Example && open Example.xcworkspace— SwiftUI demo app. Depends on the package viapath: "../../"and is used for device validation. Run on a real iOS device — the simulator is not supported on Apple Silicon (see Gotchas).
Build MLKit XCFrameworks(.github/workflows/build-mlkit.yml) — manualworkflow_dispatchwith aversioninput. Runsmake run+update_checksums.rband creates/updates the GitHub Release. Preferred over local builds for shipping a version.Check MLKit Updates(.github/workflows/check-mlkit-updates.yml) — daily cron at 09:00 UTC. Opens an issue when CocoaPods has a newer version.
The Makefile is the single source of truth for the build. Targets form a 6-stage flow — when something breaks, locate the right file by stage:
bootstrap-cocoapods—bundle install+pod installwithintegrate_targets: false. We only want the downloaded frameworks, not Xcode project integration.bootstrap-builder—swift build -c releaseinside thexcframework-maker/git submodule. This tool wrapsxcodebuild -create-xcframeworkand patches Info.plists for frameworks that ship without one.build-cocoapods— runsxcodebuildagainst the generatedPods.xcodeprojfor bothiphoneosandiphonesimulatorSDKs at iOS 12.0 deployment target.prepare-info-plist— copies eachResources/<Name>-Info.plisttemplate intoPods/<Name>/Frameworks/<Name>.framework/Info.plist. ML Kit pods ship without proper Info.plists; without this step the SwiftPM consumer crashes at launch with "The bundle doesn't contain…".create-xcframework— callsxcframework-maker/.build/release/make-xcframeworkfor every MLKit module, plus rawxcodebuild -create-xcframeworkforGoogleToolboxForMacandSSZipArchive. Output lands inGoogleMLKit/.archive— for static frameworks shipped as FAT object files (BarcodeScanning, FaceDetection, ImageLabeling, LanguageID, Translate, SmartReply), runsmv → ar r → ranlibinside both slices to convert the Mach-O object into a realararchive. Thenzip -revery.xcframeworkandGoogleMVFaceDetectorResources.bundleintoGoogleMLKit/.
- 17
.libraryproducts and ~30.binaryTargetentries. Each binary target points athttps://github.com/d-date/google-mlkit-swiftpm/releases/download/<version>/<Name>.xcframework.zipwith a SHA256 checksum. - One real
.targetnamedCommonre-exportsMLKitCommonand pulls in non-binary Google SwiftPM dependencies (GoogleUtilities, gtm-session-fetcher, GoogleDataTransport, nanopb, promises). Every public library composes its binary target withCommon, so consumers don't have to wire these themselves. - A block of commented-out
.binaryTarget(name:path:)entries near the top is intentionally kept for local debugging — uncomment them (and comment the URL-based ones) to point SwiftPM atGoogleMLKit/*.xcframeworkdirectly.
- No arm64 iOS Simulator slice. ML Kit's pre-built binaries don't include arm64 simulator. The Makefile only produces
arm64for iphoneos andx86_64for iphonesimulator. Apple Silicon Macs cannot use the simulator — test on a real device. - Consumer linker flags. Apps consuming this package must add
-ObjCand-all_loadto Other Linker Flags, otherwise they crash at runtime withunrecognized selector. MLKitFaceDetectionresource bundle.GoogleMVFaceDetectorResources.bundlecannot ride along inside SwiftPM. It ships as a separate.zipon the GitHub Release; consumers must add it to their Xcode project manually.- Submodule + Ruby version mismatch.
xcframework-maker/is a git submodule (git submodule update --initrequired)..tool-versionspins Ruby 4.0.1 for local dev but CI workflows pin Ruby 3.3 — a recent regression (PR #86) was caused by Ruby 4.0 incompatibility on macos-15 runners. Don't bump CI back to 4.x without verifying. - Adding a new MLKit module is a multi-file change. It touches
Podfile, a newResources/<Name>-Info.plist(copy from a sibling), theMakefile(prepare-info-plist+create-xcframework+archivezip list, plus the ar/ranlib block if it's static-only),Package.swift(new.binaryTargetand either a new.libraryor addition to an existing product's target list), and possiblyscripts/update_checksums.rbif it enumerates frameworks. - Don't hand-edit Pods. The Podfile's
post_installstripsARCHSso the Makefile can drive architecture choice. Don'tpod installoutsidemake bootstrap-cocoapods. Package.swiftURLs/checksums are generated. Runscripts/update_checksums.rbrather than editing checksum strings — the next release run will overwrite manual edits anyway.
- Swift tools
5.9, iOS 15+ deployment target onPackage.swift. - No new third-party dependencies without asking first.
- Ruby scripts use the standard library only (no gems beyond CocoaPods).