From 743f1810c7ad4895b0df164395abfb54c9e8015d Mon Sep 17 00:00:00 2001 From: Jonathan Cole Date: Sat, 12 Dec 2020 12:35:25 -0500 Subject: [PATCH] Merge pull request #19088 from Rightpoint:task/colejd/make-xcframework-output-path-explicit Make xcframework output path argument explicit and required * Make output path argument explicit and required * Improve xcframework documentation * Add TODOs for future breaking changes on build_framework.py scripts --- platforms/apple/build_xcframework.py | 10 +++++----- platforms/apple/readme.md | 22 +++++++++++++++++++--- platforms/ios/build_framework.py | 5 +++-- platforms/osx/build_framework.py | 5 +++-- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/platforms/apple/build_xcframework.py b/platforms/apple/build_xcframework.py index 960e9867f9..afea5e4691 100755 --- a/platforms/apple/build_xcframework.py +++ b/platforms/apple/build_xcframework.py @@ -27,7 +27,7 @@ if __name__ == "__main__": Any arguments that are not recognized by this script are passed through to the ios/osx build_framework.py scripts. """ parser = argparse.ArgumentParser(description=description, epilog=epilog) - parser.add_argument('out', metavar='OUTDIR', help='The directory where the xcframework will be created') + parser.add_argument('-o', '--out', metavar='OUTDIR', help=' The directory where the xcframework will be created', required=True) parser.add_argument('--framework_name', default='opencv2', help='Name of OpenCV xcframework (default: opencv2, will change to OpenCV in future version)') parser.add_argument('--iphoneos_archs', default=None, help='select iPhoneOS target ARCHS. Default is "armv7,arm64"') parser.add_argument('--iphonesimulator_archs', default=None, help='select iPhoneSimulator target ARCHS. Default is "x86_64,arm64"') @@ -81,26 +81,26 @@ if __name__ == "__main__": if iphoneos_archs: build_folder = get_or_create_build_folder(args.out, "iphoneos") build_folders.append(build_folder) - command = ["python3", ios_script_path, "--iphoneos_archs", iphoneos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs", build_folder] + unknown_args + command = ["python3", ios_script_path, build_folder, "--iphoneos_archs", iphoneos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args print_header("Building iPhoneOS frameworks") print(command) execute(command, cwd=os.getcwd()) if iphonesimulator_archs: build_folder = get_or_create_build_folder(args.out, "iphonesimulator") build_folders.append(build_folder) - command = ["python3", ios_script_path, "--iphonesimulator_archs", iphonesimulator_archs, "--framework_name", args.framework_name, "--build_only_specified_archs", build_folder] + unknown_args + command = ["python3", ios_script_path, build_folder, "--iphonesimulator_archs", iphonesimulator_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args print_header("Building iPhoneSimulator frameworks") execute(command, cwd=os.getcwd()) if macos_archs: build_folder = get_or_create_build_folder(args.out, "macos") build_folders.append(build_folder) - command = ["python3", osx_script_path, "--macos_archs", macos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs", build_folder] + unknown_args + command = ["python3", osx_script_path, build_folder, "--macos_archs", macos_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args print_header("Building MacOS frameworks") execute(command, cwd=os.getcwd()) if catalyst_archs: build_folder = get_or_create_build_folder(args.out, "catalyst") build_folders.append(build_folder) - command = ["python3", osx_script_path, "--catalyst_archs", catalyst_archs, "--framework_name", args.framework_name, "--build_only_specified_archs", build_folder] + unknown_args + command = ["python3", osx_script_path, build_folder, "--catalyst_archs", catalyst_archs, "--framework_name", args.framework_name, "--build_only_specified_archs"] + unknown_args print_header("Building Catalyst frameworks") execute(command, cwd=os.getcwd()) diff --git a/platforms/apple/readme.md b/platforms/apple/readme.md index f12446c060..222af109fd 100644 --- a/platforms/apple/readme.md +++ b/platforms/apple/readme.md @@ -11,7 +11,7 @@ You'll need the following to run these steps: You can then run build_xcframework.py, as below: ``` cd ~/ -python opencv/platforms/apple/build_xcframework.py ./build_xcframework +python opencv/platforms/apple/build_xcframework.py --out ./build_xcframework ``` Grab a coffee, because you'll be here for a while. By default this builds OpenCV for 8 architectures across 4 platforms: @@ -25,16 +25,32 @@ If everything's fine, you will eventually get `opencv2.xcframework` in the outpu The script has some configuration options to exclude platforms and architectures you don't want to build for. Use the `--help` flag for more information. +## How it Works + +This script generates a fat `.framework` for each platform you specify, and stitches them together into a `.xcframework`. This file can be used to support the same architecture on different platforms, which fat `.framework`s don't allow. To build the intermediate `.framework`s, `build_xcframework.py` leverages the `build_framework.py` scripts in the ios and osx platform folders. + +### Passthrough Arguments + +Any arguments that aren't recognized by `build_xcframework.py` will be passed to the platform-specific `build_framework.py` scripts. The `--without` flag mentioned in the examples is an example of this in action. For more info, see the `--help` info for those scripts. + ## Examples You may override the defaults by specifying a value for any of the `*_archs` flags. For example, if you want to build for arm64 on every platform, you can do this: ``` -python build_xcframework.py somedir --iphoneos_archs arm64 --iphonesimulator_archs arm64 --macos_archs arm64 --catalyst_archs arm64 +python build_xcframework.py --out somedir --iphoneos_archs arm64 --iphonesimulator_archs arm64 --macos_archs arm64 --catalyst_archs arm64 ``` + If you want to build only for certain platforms, you can supply the `--build_only_specified_archs` flag, which makes the script build only the archs you directly ask for. For example, to build only for Catalyst, you can do this: ``` -python build_xcframework.py somedir --catalyst_archs x86_64,arm64 --build_only_specified_archs +python build_xcframework.py --out somedir --catalyst_archs x86_64,arm64 --build_only_specified_archs +``` + +You can also build without OpenCV functionality you don't need. You can do this by using the `--without` flag, which you use once per item you want to go without. For example, if you wanted to compile without `video` or `objc`, you'd can do this: + +``` +python build_xcframework.py --out somedir --without video --without objc ``` +(if you have issues with this, try using `=`, e.g. `--without=video --without=objc`, and file an issue on GitHub.) diff --git a/platforms/ios/build_framework.py b/platforms/ios/build_framework.py index bd27dcf731..77db86fc3c 100755 --- a/platforms/ios/build_framework.py +++ b/platforms/ios/build_framework.py @@ -490,11 +490,12 @@ class iOSBuilder(Builder): 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.') + # TODO: When we can make breaking changes, we should make the out argument explicit and required like in build_xcframework.py. 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('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF)') + parser.add_argument('--without', metavar='MODULE', default=[], action='append', help='OpenCV modules to exclude from the framework. To exclude multiple, specify this flag again, e.g. "--without video --without objc"') + parser.add_argument('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF). To disable multiple, specify this flag again, e.g. "--disable tbb --disable openmp"') 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') diff --git a/platforms/osx/build_framework.py b/platforms/osx/build_framework.py index 32cd00aed7..480f3e3957 100755 --- a/platforms/osx/build_framework.py +++ b/platforms/osx/build_framework.py @@ -58,11 +58,12 @@ class OSXBuilder(Builder): 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 OSX.') + # TODO: When we can make breaking changes, we should make the out argument explicit and required like in build_xcframework.py. 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('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF)') + parser.add_argument('--without', metavar='MODULE', default=[], action='append', help='OpenCV modules to exclude from the framework. To exclude multiple, specify this flag again, e.g. "--without video --without objc"') + parser.add_argument('--disable', metavar='FEATURE', default=[], action='append', help='OpenCV features to disable (add WITH_*=OFF). To disable multiple, specify this flag again, e.g. "--disable tbb --disable openmp"') parser.add_argument('--dynamic', default=False, action='store_true', help='build dynamic framework (default is "False" - builds static framework)') parser.add_argument('--enable_nonfree', default=False, dest='enablenonfree', action='store_true', help='enable non-free modules (disabled by default)') parser.add_argument('--macosx_deployment_target', default=os.environ.get('MACOSX_DEPLOYMENT_TARGET', MACOSX_DEPLOYMENT_TARGET), help='specify MACOSX_DEPLOYMENT_TARGET')