|
1 | 1 | require "json" |
2 | 2 |
|
| 3 | +# ============================================================================= |
| 4 | +# ExpoLitertLm.podspec — manifest-driven xcframework consumer |
| 5 | +# ============================================================================= |
| 6 | +# ios/Frameworks/rewrap-manifest.json is the single source of truth for |
| 7 | +# the xcframework names, versions, and sha256 values. It is populated by |
| 8 | +# scripts/sync-litertlm-swift.sh (Phase 14 D-31, D-34). |
| 9 | +# |
| 10 | +# If the manifest is missing, pod install will fail with a clear message. |
| 11 | +# Run `make sync TAG=v<upstream>+rewrap.<n>` first. |
| 12 | +# ============================================================================= |
| 13 | + |
| 14 | +# Layer C assertion: read the manifest and validate invariants at install time. |
| 15 | +begin |
| 16 | + manifest_path = File.expand_path("ios/Frameworks/rewrap-manifest.json", __dir__) |
| 17 | + raise "rewrap-manifest.json missing at #{manifest_path} — run `make sync TAG=v<upstream>+rewrap.<n>` first (Phase 14 D-34)" unless File.exist?(manifest_path) |
| 18 | + |
| 19 | + rewrap_manifest = JSON.parse(File.read(manifest_path)) |
| 20 | + raise "unexpected manifest schema_version=#{rewrap_manifest['schema_version']} (expected 1)" unless rewrap_manifest["schema_version"] == 1 |
| 21 | + |
| 22 | + xcfws = rewrap_manifest["xcframeworks"] || [] |
| 23 | + raise "manifest.xcframeworks must have >=2 entries, got #{xcfws.length} — re-run `make sync TAG=...`" unless xcfws.length >= 2 |
| 24 | + |
| 25 | + # Layer C assertion #1: the LiteRTLM xcframework MUST carry the '-rewrapped' qualifier. |
| 26 | + # A future upstream slip-up (raw LiteRTLM.xcframework vendored without rewrap) will |
| 27 | + # fail pod install loudly here rather than crashing silently at runtime. |
| 28 | + litertlm_entry = xcfws.find { |x| x["name"].to_s.start_with?("LiteRTLM") } |
| 29 | + raise "manifest has no LiteRTLM xcframework entry" unless litertlm_entry |
| 30 | + raise "LiteRTLM entry name (#{litertlm_entry['name']}) must contain '-rewrapped' (raw upstream xcframework is not accepted)" unless litertlm_entry["name"].include?("-rewrapped") |
| 31 | + |
| 32 | + # Layer C assertion #2: every entry must have a non-empty 64-hex sha256. |
| 33 | + xcfws.each do |x| |
| 34 | + sha = x["zip_sha256"].to_s |
| 35 | + raise "xcframework #{x['name']} has missing/invalid zip_sha256 (#{sha.inspect}) — re-run `make sync TAG=...`" unless sha.match?(/\A[0-9a-f]{64}\z/) |
| 36 | + end |
| 37 | + |
| 38 | + # Build vendored_frameworks array: ios/Frameworks/<name> for each entry |
| 39 | + VENDORED_XCFRAMEWORKS = xcfws.map { |x| "ios/Frameworks/#{x['name']}" }.freeze |
| 40 | + |
| 41 | + # Derive version from manifest: <upstream_ver_without_v>.rewrap.<iteration> |
| 42 | + upstream_ver = rewrap_manifest["upstream_version"].to_s.sub(/^v/, "") |
| 43 | + rewrap_iter = rewrap_manifest["rewrap_iteration"].to_s |
| 44 | + MANIFEST_VERSION = "#{upstream_ver}.rewrap.#{rewrap_iter}".freeze |
| 45 | + |
| 46 | +rescue => e |
| 47 | + # Provide an informative failure rather than a Ruby NoMethodError deep in the stack. |
| 48 | + # pod lib lint will see this; `pod install` will also fail with a clear message. |
| 49 | + warn "[ExpoLitertLm] WARNING: could not read rewrap-manifest.json — #{e.message}" |
| 50 | + VENDORED_XCFRAMEWORKS = [ |
| 51 | + "ios/Frameworks/LiteRTLM-rewrapped.xcframework", |
| 52 | + "ios/Frameworks/GemmaModelConstraintProvider.xcframework", |
| 53 | + ].freeze |
| 54 | + MANIFEST_VERSION = "0.0.0-manifest-missing".freeze |
| 55 | +end |
| 56 | + |
3 | 57 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) |
4 | 58 |
|
5 | 59 | Pod::Spec.new do |s| |
6 | 60 | s.name = "ExpoLitertLm" |
7 | | - s.version = package["version"] |
| 61 | + # Version derived from manifest (single SoT). Falls back to package.json version |
| 62 | + # if manifest is not yet synced (e.g. pod lib lint on a fresh checkout). |
| 63 | + s.version = MANIFEST_VERSION == "0.0.0-manifest-missing" ? package["version"] : MANIFEST_VERSION |
8 | 64 | s.summary = package["description"] |
9 | 65 | s.description = package["description"] |
10 | 66 | s.license = package["license"] || "MIT" |
@@ -36,10 +92,10 @@ Pod::Spec.new do |s| |
36 | 92 | # ios/MediaPipeFallback/. |
37 | 93 | c.exclude_files = "ios/MediaPipeFallback/**/*" |
38 | 94 |
|
39 | | - c.vendored_frameworks = [ |
40 | | - "ios/Frameworks/CLiteRTLM.xcframework", |
41 | | - "ios/Frameworks/GemmaModelConstraintProvider.xcframework" |
42 | | - ] |
| 95 | + # vendored_frameworks is manifest-driven (BOTH LiteRTLM-rewrapped + GemmaModelConstraintProvider). |
| 96 | + # The array is populated from ios/Frameworks/rewrap-manifest.json at pod install time. |
| 97 | + # Populated by: make sync TAG=v<upstream>+rewrap.<n> |
| 98 | + c.vendored_frameworks = VENDORED_XCFRAMEWORKS |
43 | 99 |
|
44 | 100 | c.pod_target_xcconfig = { |
45 | 101 | "DEFINES_MODULE" => "YES", |
|
0 commit comments