Skip to content

Add arm64 simulator slice to opus.xcframework - #32

Open
danielgomezrico wants to merge 1 commit into
EPNW:masterfrom
danielgomezrico:fix/ios-arm64-simulator-slice
Open

Add arm64 simulator slice to opus.xcframework#32
danielgomezrico wants to merge 1 commit into
EPNW:masterfrom
danielgomezrico:fix/ios-arm64-simulator-slice

Conversation

@danielgomezrico

Copy link
Copy Markdown

Fixes #31.

opus.xcframework has no arm64 iOS-simulator slice. On an Apple Silicon Mac the simulator build targets arm64-ios-simulator, no slice matches, and the link step fails:

Error (Xcode): Framework 'opus' not found
Error (Xcode): Linker command failed with exit code 1

Before:

"LibraryIdentifier" => "ios-x86_64-simulator"   ["x86_64"]
"LibraryIdentifier" => "ios-arm64"              ["arm64"]

After:

"LibraryIdentifier" => "ios-arm64"              ["arm64"]
"LibraryIdentifier" => "ios-arm64_x86_64-simulator"  ["arm64", "x86_64"]

Intel simulator hosts keep working, because the simulator slice is fat rather than arm64-only.

What changed

  • ios/opus.xcframework regenerated with three architectures.
  • tool/build_opus_xcframework.sh added. It downloads an official opus release and reproduces the framework, so the next architecture gap is a script run instead of an archaeology exercise.
  • README documents the slices and the rebuild command.
  • CHANGELOG entry and version bump to 3.0.2.

Two decisions worth your review

1. The device slice is rebuilt too. The shipped device binary was opus 1.1.3; every slice is now 1.5.2. I did this so the simulator and a device run the same codec build — a simulator-only bump would mean testing against a different encoder than you ship. It does mean this PR changes the device binary, not only the simulator one. If you would rather keep the blast radius at the reported bug, I am happy to redo it as a simulator-only slice on top of the existing 1.1.3 device framework.

2. The framework is built here rather than pulled from opus_xcframework. That repo is the documented source of this binary, so the fix arguably belongs there first. I put the script in this package because that is where the bug reproduces, but I am glad to move it to opus_xcframework and reduce this PR to the regenerated binary — tell me which you prefer.

Verification

Built with tool/build_opus_xcframework.sh (opus 1.5.2, deployment target 13.0, CMake — the autotools configure script cannot cross-configure for the simulator triple).

Platform load commands are correct — platform 2 (iOS) on the device slice, platform 7 (iOS simulator) on the simulator slice:

$ otool -l ios-arm64/opus.framework/opus | grep -A3 LC_BUILD_VERSION | grep platform
 platform 2
$ otool -l ios-arm64_x86_64-simulator/opus.framework/opus | grep -A3 LC_BUILD_VERSION | grep platform
 platform 7
 platform 7

Symbol parity against the previously committed device binary: the only exports that disappear are _opusVersionNumber and _opusVersionString, which are Xcode's framework-versioning symbols rather than opus API. Every entry point the Dart FFI layer resolves is present (opus_encoder_create, opus_decoder_create, opus_encode, opus_decode, opus_encoder_destroy, opus_get_version_string).

Tested with a Flutter app that takes opus_flutter_ios as a path dependency on this branch (Flutter 3.41.1, Xcode 26.6, macOS 26.2, Apple Silicon):

$ flutter build ios --simulator --debug
✓ Built build/ios/iphonesimulator/Runner.app

$ lipo -info build/ios/iphonesimulator/Runner.app/Frameworks/opus.framework/opus
Architectures in the fat file: ... are: x86_64 arm64

The app installs and launches on an iPhone 17 Pro simulator, and calls opus over FFI through OpusFlutterIOS().load(), which resolves against DynamicLibrary.process():

library handle: ok
version: libopus 1.5.2
opus_encoder_get_size(1): 43580
RESULT: PASS

So the framework links, embeds with an arm64 slice, loads at runtime, and its symbols resolve.

Note that the plugin's own opus_flutter/example does not build on current Flutter for an unrelated reason — its pinned win32 5.0.9 uses UnmodifiableUint8ListView, which modern Dart removed. That is independent of this change, but it is why the verification above uses a separate app.

What I could not test: I have no iOS hardware here, so the rebuilt device slice is verified by linking and symbol comparison only, not by running on a physical device. Worth a check on your side before release.

The framework carried only ios-arm64 and ios-x86_64-simulator. On an Apple
Silicon Mac the simulator build targets arm64-ios-simulator, no slice matches,
and the link step fails with "Framework 'opus' not found".

Rebuild the framework with three architectures: ios-arm64 for devices and a fat
ios-arm64_x86_64-simulator for simulators, so Intel hosts keep working.

Build every slice from opus 1.5.2 so a simulator run and a device run exercise
the same codec version. The device slice was previously 1.1.3.

Add tool/build_opus_xcframework.sh, which reproduces the framework from an
official opus release.

Fixes EPNW#31
@danielgomezrico

Copy link
Copy Markdown
Author

It seems that #30 is a simpler fix to this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS: opus.xcframework has no arm64 simulator slice — "Framework 'opus' not found" on Apple Silicon

1 participant