Skip to content

Instantly share code, notes, and snippets.

@humblehacker
Last active January 22, 2024 07:07
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save humblehacker/6a2e38072b0e237de20ba6d1f2efc80f to your computer and use it in GitHub Desktop.
Save humblehacker/6a2e38072b0e237de20ba6d1f2efc80f to your computer and use it in GitHub Desktop.
Make opencv2.xcframework for iOS arm64, and iOSSimulator arm64 & x86_64

I had some trouble attempting to build an XCFramework of OpenCV, but I finally got a successful build with the following steps:

  1. Clone the OpenCV repo:
    git clone git@github.com:opencv/opencv.git
    cd opencv
    
  2. Disable building with libjpeg-turbo1 by applying a patch:
    git apply path/to/opencv-5-28-50.patch
  3. Make a build directory adjacent to the opencv repo
    cd ..
    mkdir build-opencv
    cd build-opencv
  4. Build the xcframework (change these options per your requirements):
    python3 ../opencv/platforms/apple/build_xcframework.py \
      --out . \
      --without=video \
      --iphoneos_archs=arm64 \
      --iphonesimulator_archs x86_64,arm64 \
      --iphoneos_deployment_target=13 \
      --disable-bitcode \
      --build_only_specified_archs

If all goes well, after quite some time you should see:

============================================================
Finished building ./opencv2.xcframework
============================================================

Footnotes

  1. Why do we need to disable libjpeg-turbo? Because it fails to build during the configuration stage with:

    -- libjpeg-turbo: VERSION = 2.1.2, BUILD = opencv-4.6.0-libjpeg-turbo
    -- Check size of size_t
    CMake Error at /usr/local/share/cmake-3.25/Modules/CheckTypeSize.cmake:148 (try_compile):
      Cannot copy output executable
    
        ''
    
      to destination specified by COPY_FILE:
    
        'opencv-build-ios13/iphoneos/build/build-arm64-iphoneos/CMakeFiles/CheckTypeSize/SIZEOF_SIZE_T.bin'
    
      Recorded try_compile output location doesn't exist:
    
        opencv-build-ios13/iphoneos/build/build-arm64-iphoneos/CMakeFiles/CMakeScratch/TryCompile-kqujHS/Release/cmTC_afcdc.app/cmTC_afcdc
    
    Call Stack (most recent call first):
      /usr/local/share/cmake-3.25/Modules/CheckTypeSize.cmake:278 (__check_type_size_impl)
      3rdparty/libjpeg-turbo/CMakeLists.txt:25 (check_type_size)
    
    
    -- Check size of unsigned long
    CMake Error at /usr/local/share/cmake-3.25/Modules/CheckTypeSize.cmake:148 (try_compile):
      Cannot copy output executable
    
        ''
    
      to destination specified by COPY_FILE:
    
        'opencv-build-ios13/iphoneos/build/build-arm64-iphoneos/CMakeFiles/CheckTypeSize/SIZEOF_UNSIGNED_LONG.bin'
    
      Recorded try_compile output location doesn't exist:
    
        opencv-build-ios13/iphoneos/build/build-arm64-iphoneos/CMakeFiles/CMakeScratch/TryCompile-Mi900g/Release/cmTC_68bed.app/cmTC_68bed
    
    Call Stack (most recent call first):
      /usr/local/share/cmake-3.25/Modules/CheckTypeSize.cmake:278 (__check_type_size_impl)
      3rdparty/libjpeg-turbo/CMakeLists.txt:26 (check_type_size)
    

    I'm not sure what the consequences are of this change, so use at your own risk!

diff --git forkSrcPrefix/platforms/ios/build_framework.py forkDstPrefix/platforms/ios/build_framework.py
index 08d9fd63dc8e2cbc77358b2e5f92e1ad2672b890..26d89b47a90823a03b490257e4674bdc40d03e46 100755
--- forkSrcPrefix/platforms/ios/build_framework.py
+++ forkDstPrefix/platforms/ios/build_framework.py
@@ -106,7 +106,7 @@ class Builder:
main_build_dir = self.getBuildDir(main_working_dir, target)
dirs.append(main_build_dir)
- cmake_flags = []
+ cmake_flags = ["-DBUILD_JPEG_TURBO_DISABLE=ON"]
if self.contrib:
cmake_flags.append("-DOPENCV_EXTRA_MODULES_PATH=%s" % self.contrib)
if xcode_ver >= 7 and target[1] == 'iPhoneOS' and self.bitcodedisabled == False:
@huyaoyu
Copy link

huyaoyu commented Jan 22, 2024

Thank you for sharing this. By following your instructions, I successfully compile the framework on a M3 chip machine. I need to make some simple tweaks to make it work in my setting. I'm using OpenCV 4.9.0, Swift 5.9, and Xcode 15. I encountered some python error and Swift compiler not found error.

To resolve those errors and in addition to your patch, I need to do the following patch. The solution comes from

diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py
index b876812720..e5807ee64a 100755
--- a/platforms/ios/build_framework.py
+++ b/platforms/ios/build_framework.py
@@ -106,7 +106,7 @@ class Builder:
             main_build_dir = self.getBuildDir(main_working_dir, target)
             dirs.append(main_build_dir)

-            cmake_flags = []
+            cmake_flags = ["-DBUILD_JPEG_TURBO_DISABLE=ON"]
             if self.contrib:
                 cmake_flags.append("-DOPENCV_EXTRA_MODULES_PATH=%s" % self.contrib)
             if xcode_ver >= 7 and target[1] == 'iPhoneOS' and self.bitcodedisabled == False:
@@ -196,6 +196,8 @@ class Builder:
             "cmake",
             "-GXcode",
             "-DAPPLE_FRAMEWORK=ON",
+            "-DPYTHON_DEFAULT_EXECUTABLE=python3",
+            "-DCMAKE_Swift_COMPILER=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc",
             "-DCMAKE_INSTALL_PREFIX=install",
             "-DCMAKE_BUILD_TYPE=%s" % self.getConfiguration(),
             "-DOPENCV_INCLUDE_INSTALL_PATH=include",

In my case, I'm compiling for iOS 17, so I use --iphoneos_deployment_target=17 in the command line. The compilation finished without error.

However, I find that the compiled framework works if I choose a real iPhone as the target but leads to compilation failure for the simulator. It is probably more appropriate to ask the OpenCV developers but I figured that I can share with you to see if you have a quick fix. The error message itself is not very informative by just saying /Users/yaoyuh/Library/Developer/Xcode/DerivedData/test-opencv-hirjnpdhjxoecfejzywvtbryrfik/Build/Products/Debug-iphonesimulator/opencv2.framework/Modules/opencv2.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface:10:19 Could not build Objective-C module 'opencv2' and /Users/yaoyuh/Library/Developer/Xcode/DerivedData/test-opencv-hirjnpdhjxoecfejzywvtbryrfik/Build/Products/Debug-iphonesimulator/opencv2.framework/Headers/opencv2-Swift.h:557:2 Unsupported Swift architecture

Any help would be appreciated, thank you!

@huyaoyu
Copy link

huyaoyu commented Jan 22, 2024

By reading the following
opencv/opencv#21571
https://github.com/opencv/opencv/tree/4.x/platforms/apple

The above problem is solved by

python3 ../opencv/platforms/apple/build_xcframework.py \
  --out . \
  --without=video \
  --iphoneos_archs=arm64 \
  --iphonesimulator_archs=arm64 \
  --iphoneos_deployment_target=17 \
  --disable-bitcode \
  --build_only_specified_archs

The --iphonesimulator_archs=amr64 was --iphonesimulator_archs x86_64,arm64. The difference is using = and only specifying arm64.

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