Skip to content

Commit d68e1be

Browse files
helenkwokclaude
andcommitted
feat(14-08): rewire ExpoLitertLm.podspec to read xcframework from manifest
Podspec now reads ios/Frameworks/rewrap-manifest.json at pod install time via Ruby JSON.parse (Phase 14 D-31 single source of truth): - schema_version=1 assertion - >=2 xcframeworks entries assertion - '-rewrapped' qualifier check on LiteRTLM entry (Layer C anti-regression) - Per-entry 64-hex sha256 validation - vendored_frameworks becomes an array populated from manifest.xcframeworks[] (both LiteRTLM-rewrapped.xcframework + GemmaModelConstraintProvider.xcframework) - s.version derived from manifest: <upstream_ver>.rewrap.<iteration> - Graceful begin/rescue: informs operator when manifest is missing instead of crashing with Ruby NoMethodError - MediaPipeFallback subspec untouched (D-22 preserved) Run `make sync TAG=v<upstream>+rewrap.<n>` before `pod install`. Phase 14 D-31 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b01798a commit d68e1be

1 file changed

Lines changed: 61 additions & 5 deletions

File tree

ExpoLitertLm.podspec

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,66 @@
11
require "json"
22

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+
357
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
458

559
Pod::Spec.new do |s|
660
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
864
s.summary = package["description"]
965
s.description = package["description"]
1066
s.license = package["license"] || "MIT"
@@ -36,10 +92,10 @@ Pod::Spec.new do |s|
3692
# ios/MediaPipeFallback/.
3793
c.exclude_files = "ios/MediaPipeFallback/**/*"
3894

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
4399

44100
c.pod_target_xcconfig = {
45101
"DEFINES_MODULE" => "YES",

0 commit comments

Comments
 (0)