MacBook Air (M1) の開発環境を構築してます。
OpenCVを含んだiOSシミュレータ向けビルドが通らない問題ですが、どうもlipoコマンドでは同じアーキテクチャのデバイス向けとシミュレータ向けのバイナリを混在できないようで、それらを混在させるためにはxcframeworkを使う必要があるようです。
現状ではOpenCVのxcframeworkは無いみたいなので、ソースからビルドします。
OpenCV公式からソースをダウンロードして展開します。今回は3.4.6を使いたいので3.4.6で説明します。
platforms/ios/build_framework.py
の300行目あたりにビルド設定している部分があります。
if __name__ == "__main__": folder = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")) parser = argparse.ArgumentParser(description='The script builds OpenCV.framework for iOS.') parser.add_argument('out', metavar='OUTDIR', help='folder to put built framework') parser.add_argument('--opencv', metavar='DIR', default=folder, help='folder with opencv repository (default is "../.." relative to script location)') parser.add_argument('--contrib', metavar='DIR', default=None, help='folder with opencv_contrib repository (default is "None" - build only main framework)') parser.add_argument('--without', metavar='MODULE', default=[], action='append', help='OpenCV modules to exclude from the framework') parser.add_argument('--dynamic', default=False, action='store_true', help='build dynamic framework (default is "False" - builds static framework)') parser.add_argument('--disable-bitcode', default=False, dest='bitcodedisabled', action='store_true', help='disable bitcode (enabled by default)') parser.add_argument('--iphoneos_deployment_target', default=os.environ.get('IPHONEOS_DEPLOYMENT_TARGET', IPHONEOS_DEPLOYMENT_TARGET), help='specify IPHONEOS_DEPLOYMENT_TARGET') parser.add_argument('--iphoneos_archs', default='armv7,armv7s,arm64', help='select iPhoneOS target ARCHS') parser.add_argument('--iphonesimulator_archs', default='i386,x86_64', help='select iPhoneSimulator target ARCHS') parser.add_argument('--enable_nonfree', default=False, dest='enablenonfree', action='store_true', help='enable non-free modules (disabled by default)') args = parser.parse_args() os.environ['IPHONEOS_DEPLOYMENT_TARGET'] = args.iphoneos_deployment_target print('Using IPHONEOS_DEPLOYMENT_TARGET=' + os.environ['IPHONEOS_DEPLOYMENT_TARGET']) iphoneos_archs = args.iphoneos_archs.split(',') print('Using iPhoneOS ARCHS=' + str(iphoneos_archs)) iphonesimulator_archs = args.iphonesimulator_archs.split(',') print('Using iPhoneSimulator ARCHS=' + str(iphonesimulator_archs)) b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.enablenonfree, [ (iphoneos_archs, "iPhoneOS"), ] if os.environ.get('BUILD_PRECOMMIT', None) else [ (iphoneos_archs, "iPhoneOS"), (iphonesimulator_archs, "iPhoneSimulator"), ]) b.build(args.out)
今回は、
- 実機向けframeworkを作成
- シミュレータ向けframeworkを作成
- 実機向けframeworkとシミュレータ向けframeworkを合わせてxcframeworkを作成
という手順でやります。
まず、実機向けビルドですが、
b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.enablenonfree, [ (iphoneos_archs, "iPhoneOS"), ] if os.environ.get('BUILD_PRECOMMIT', None) else [ (iphoneos_archs, "iPhoneOS"), (iphonesimulator_archs, "iPhoneSimulator"), ])
ここを
b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.enablenonfree, [ (iphoneos_archs, "iPhoneOS"), ])
と書き換えて以下のコマンドを実行します。
python platforms/ios/build_framework.py iphoneos
次にシミュレータビルドですが、先ほどのところを
b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.enablenonfree, [ (iphonesimulator_archs, "iPhoneSimulator"), ])
として、さらに
parser.add_argument('--iphonesimulator_archs', default='i386,x86_64', help='select iPhoneSimulator target ARCHS')
の部分に arm64
を追加します。
parser.add_argument('--iphonesimulator_archs', default='i386,x86_64,arm64', help='select iPhoneSimulator target ARCHS')
そして
python platforms/ios/build_framework.py iphonesimulator
を実行します。
これで、 iphoneos/opencv2.framework
と iphonesimulator/opencv2.framework
ができたので、あとはこれを合体させます。
xcodebuild -create-xcframework -output opencv2.xcframework -framework iphoneos/opencv2.framework -framework iphonesimulator/opencv2.framework
これでできた opencv2.xcframework
を使うと、シミュレータでビルド・実行できるようになります。