Build OpenCV Contrib as a .xcframework, for iOS, on a M1
Context
We needed an OpenCV Contrib module in an iOS app. When reviewing options, it was decided we would expose a Swift package, wrapping an Objective-C wrapper, that would itself be the one importing OpenCV.
This meant exposing OpenCV as a Swift Package Manager binary target. Which requires us to build a .xcframework.
Goal
Build a .xcframework
that we can run on both OS devices and Intel & Apple M1 Mac iPhone / iPad Simulators. Why a .xcframework
and not simply a .framework
? Because while Swift Package Manager can import binaries, it can only import .xcframework
ones, not .framework
ones.
Requirements
- cmake (installable using brew)
- python3 (because python2.7 is obsolete) (installable using brew)
- opencv source (via
git clone https://github.com/opencv/opencv.git
) - opencv_contrib source (via
git clone https://github.com/opencv/opencv_contrib.git
)
Building
Build OpenCV using the proper flags (outfile, contrib, iphoneos arch, iphonesimulator archs):
python3 opencv/platforms/apple/build_xcframework.py \
--out ./opencv-build \
--contrib opencv_contrib \
--iphoneos_archs armv7,armv7s,arm64 \
--iphonesimulator_archs arm64 \
--build_only_specified_archs
Where the --contrib
parameter's value is the local path to the opencv_contrib source.
Go make yourself a nice and warm cup of tea 🫖 (because I currently am writing this in the UK 🇬🇧 )
With a dash of whisky in it 🥃, because I'm more specifically in Scotland 🏴 at the moment
Wait
... Wait
... Wait some more
Your tea should be ready now, more or less
Wait
... ... Wait
Wait
Wait some more
Wait
You can now carefully sip your tea
cd /Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/modules/objc_bindings_generator/ios/gen
export LANG\=en_US.US-ASCII
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c++ -target arm64-apple-ios9.0-simulator -fmessage-length\=122 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit\=0 -fcolor-diagnostics -Wno-trigraphs -fpascal-strings -O1 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-implicit-atomic-properties -Wno-objc-interface-ivars -Wno-arc-repeated-use-of-weak -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-emp
Sip some tea.
Wait.
Did you know there are over 3000 varieties of tea out there? I certainly didn't. Until I looked it up to give you some random, vaguely appropriate, fun fact.
Go buy yourself some nice biscuits to go with your tea
-o /Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/modules/objc/framework_build/opencv2.build/Release-iphonesimulator/opencv2.build/Objects-normal/arm64/AffineFeature.o
CompileC /Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/modules/objc/framework_build/opencv2.build/Release-iphonesimulator/opencv2.build/Objects-normal/arm64/AdaptiveManifoldFilter.o /Users/path/opencv-build/build-arm64-iphonesimulator/modules/objc_bindings_generator/ios/gen/objc/ximgproc/AdaptiveManifoldFilter.mm normal arm64 objective-c++ com.apple.compilers.llvm.clang.1_0.compiler (in target 'opencv2' from project 'opencv2')
cd /Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/modules/objc_bindings_generator/ios/gen
export LANG\=en_US.US-ASCII
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c++ -target arm64-apple-ios9.0-simulator
Sip your tea some more, now with biscuits
Wait
... Wait
Put the cup of tea down...
Executing: ['cmake', '-DBUILD_TYPE=Release', '-DCMAKE_INSTALL_PREFIX=/Users/username/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/install', '-P', 'cmake_install.cmake'] in /Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/modules/objc/framework_build
Executing: cmake -DBUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/Users/path/opencv-build/iphonesimulator/build/build-arm64-iphonesimulator/install -P cmake_install.cmake
-- Install configuration: "Release"
... lay back in your chair...
... and do a 360!
Turn around some more!
Oh. That got creepy.
Oh, it's done building! Congrats!
============================================================
Finished building ./opencv-build/opencv2.xcframework
============================================================
That wasn't so hard now, was it? Now you can use OpenCV contrib modules in your app! Isn't that nice! Next, how to import it into our projects as a binary target using Swift Package Manager!
Resources:
- https://docs.opencv.org/4.x/d5/da3/tutorial_ios_install.html
- https://docs.opencv.org/4.x/d7/d88/tutorial_hello.html
- https://fossies.org/linux/opencv/platforms/apple/readme.md
- https://stackoverflow.com/questions/44584343/how-to-build-opencv-in-ios
- https://developer.apple.com/forums/thread/666335
- https://stackoverflow.com/questions/66197098/import-framework-inside-spm-swift-package-manager
- https://forums.swift.org/t/how-to-import-prebuilt-frameworks-from-local-project-in-swift-package/35985
- https://github.com/ezhes/sendbird-ios-xcframework
- https://github.com/spouliot/xcframework
- https://fossies.org/linux/opencv/platforms/apple/readme.md
- https://vovkos.github.io/doxyrest-showcase/opencv/sphinx_rtd_theme/page_tutorial_ios_install.html