mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 12:40:05 +08:00
Merge pull request #18826 from Rightpoint:feature/colejd/build-catalyst-xcframework
Support XCFramework builds, Catalyst * Early work on xcframework support * Improve legibility * Somehow this works * Specify ABIs in a place where they won't get erased If you pass in the C/CXX flags from the Python script, they won't be respected. By doing it in the actual toolchain, the options are respected and Catalyst successfully links. * Clean up and push updates * Actually use Catalyst ABI Needed to specify EXE linker flags to get compiler tests to link to the Catalyst ABIs. * Clean up * Revert changes to common toolchain that don't matter * Try some things * Support Catalyst build in OSX scripts * Remove unnecessary iOS reference to AssetsLibrary framework * Getting closer * Try some things, port to Python 3 * Some additional fixes * Point Cmake Plist gen to osx directory for Catalyst targets * Remove dynamic lib references for Catalyst, copy iOS instead of macos * Add flag for building only specified archs, remove iOS catalyst refs * Add build-xcframework.sh * Update build-xcframework.sh * Add presumptive Apple Silicon support * Add arm64 iphonesimulator target * Fix xcframework build * Working on arm64 iOS simulator * Support 2.7 (replace run with check_output) * Correctly check output of uname_m against arch * Clean up * Use lipo for intermediate frameworks, add python script Remove unneeded __init__.py * Simplify python xcframework build script * Add --only-64-bit flag * Add --framework-name flag * Document * Commit to f-strings, improve console output * Add i386 to iphonesimulator platform in xcframework generator * Enable objc for non-Catalyst frameworks * Fix xcframework builder for paths with spaces * Use arch when specifying Catalyst build platform in build command * Fix incorrect settings for framework_name argparse configuration * Prefer underscores instead of hyphens in new flags * Move Catalyst flags to where they'll actually get used * Use --without=objc on Catalyst target for now * Remove get_or_create_folder and simplify logic * Remove unused import * Tighten up help text * Document * Move common functions into cv_build_utils * Improve documentation * Remove old build script * Add readme * Check for required CMake and Xcode versions * Clean up TODOs and re-enable `copy_samples()` Remove TODO Fixup * Add missing print_function import * Clarify CMake dependency documentation * Revert python2 change in gen_objc * Remove unnecessary builtins imports * Remove trailing whitespace * Avoid building Catalyst unless specified This makes Catalyst support a non-breaking change, though defaults should be specified when a breaking change is possible. * Prevent lipoing for the same archs on different platforms before build * Rename build-xcframework.py to build_xcframework.py * Check for duplicate archs more carefully * Prevent sample copying error when directory already exists This can happen when building multiple architectures for the same platform. * Simplify code for checking for default archs * Improve build_xcframework.py header text * Correctly resolve Python script paths * Parse only known args in ios/osx build_framework.py * Pass through uncaptured args in build_xcframework to osx/ios build * Fix typo * Fix typo * Fix unparameterized build path for intermediate frameworks * Fix dyanmic info.plist path for catalyst * Fix utf-8 Python 3 issue * Add dynamic flag to osx script * Rename platform to platforms, remove armv7s and i386 * Fix creation of dynamic framework on maccatalyst and macos * Update platforms/apple/readme.md * Add `macos_archs` flag and deprecate `archs` flag * Allow specification of archs when generating xcframework from terminal * Change xcframework platform argument names to match archs flag names * Remove platforms as a concept and shadow archs flags from ios/osx .py * Improve documentation * Fix building of objc module on Catalyst, excluding Swift * Clean up build folder logic a bit * Fix framework_name flag * Drop passthrough_args, use unknown_args instead * minor: coding style changes Co-authored-by: Chris Ballinger <cballinger@rightpoint.com>
This commit is contained in:
parent
19d825aa16
commit
85b0fb2a9c
@ -2,7 +2,11 @@ set(OPENCV_APPLE_BUNDLE_NAME "OpenCV")
|
||||
set(OPENCV_APPLE_BUNDLE_ID "org.opencv")
|
||||
|
||||
if(IOS)
|
||||
if (APPLE_FRAMEWORK AND DYNAMIC_PLIST)
|
||||
if(MAC_CATALYST)
|
||||
# Copy the iOS plist over to the OSX directory if building iOS library for Catalyst
|
||||
configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in"
|
||||
"${CMAKE_BINARY_DIR}/osx/Info.plist")
|
||||
elseif(APPLE_FRAMEWORK AND DYNAMIC_PLIST)
|
||||
configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.Dynamic.plist.in"
|
||||
"${CMAKE_BINARY_DIR}/ios/Info.plist")
|
||||
else()
|
||||
|
@ -1512,10 +1512,16 @@ function(ocv_add_library target)
|
||||
|
||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG 1)
|
||||
|
||||
if(IOS AND NOT MAC_CATALYST)
|
||||
set(OPENCV_APPLE_INFO_PLIST "${CMAKE_BINARY_DIR}/ios/Info.plist")
|
||||
else()
|
||||
set(OPENCV_APPLE_INFO_PLIST "${CMAKE_BINARY_DIR}/osx/Info.plist")
|
||||
endif()
|
||||
|
||||
set_target_properties(${target} PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
MACOSX_FRAMEWORK_IDENTIFIER org.opencv
|
||||
MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_BINARY_DIR}/ios/Info.plist
|
||||
MACOSX_FRAMEWORK_INFO_PLIST ${OPENCV_APPLE_INFO_PLIST}
|
||||
# "current version" in semantic format in Mach-O binary file
|
||||
VERSION ${OPENCV_LIBVERSION}
|
||||
# "compatibility version" in semantic format in Mach-O binary file
|
||||
|
@ -119,7 +119,7 @@ if(APPLE OR APPLE_FRAMEWORK)
|
||||
endif()
|
||||
if(IOS)
|
||||
list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/ios_conversions.mm)
|
||||
list(APPEND IMGCODECS_LIBRARIES "-framework UIKit" "-framework AssetsLibrary")
|
||||
list(APPEND IMGCODECS_LIBRARIES "-framework UIKit")
|
||||
endif()
|
||||
if(APPLE AND (NOT IOS))
|
||||
list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/macosx_conversions.mm)
|
||||
|
@ -13,7 +13,13 @@ set (SUPPRESS_WARNINGS_FLAGS "-Wno-incomplete-umbrella")
|
||||
set (CMAKE_CXX_FLAGS "$${CMAKE_CXX_FLAGS} $${OBJC_COMPILE_FLAGS} $${SUPPRESS_WARNINGS_FLAGS}")
|
||||
|
||||
# grab the files
|
||||
file(GLOB_RECURSE objc_sources "objc/*\.h" "objc/*\.m" "objc/*\.mm" "objc/*\.swift" "objc/*\.modulemap")
|
||||
if(SWIFT_DISABLED)
|
||||
message(STATUS "Swift wrapper disabled")
|
||||
file(GLOB_RECURSE objc_sources "objc/*\.h" "objc/*\.m" "objc/*\.mm" "objc/*\.modulemap")
|
||||
else()
|
||||
enable_language(Swift)
|
||||
file(GLOB_RECURSE objc_sources "objc/*\.h" "objc/*\.m" "objc/*\.mm" "objc/*\.swift" "objc/*\.modulemap")
|
||||
endif()
|
||||
file(GLOB_RECURSE objc_headers "*\.h")
|
||||
|
||||
add_library($framework STATIC $${objc_sources})
|
||||
@ -29,8 +35,6 @@ endforeach()
|
||||
|
||||
install(TARGETS $framework LIBRARY DESTINATION lib)
|
||||
|
||||
enable_language(Swift)
|
||||
|
||||
# Additional target properties
|
||||
if (CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL 12)
|
||||
set_target_properties($framework PROPERTIES
|
||||
|
0
platforms/apple/__init__.py
Normal file
0
platforms/apple/__init__.py
Normal file
123
platforms/apple/build_xcframework.py
Executable file
123
platforms/apple/build_xcframework.py
Executable file
@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
This script builds OpenCV into an xcframework compatible with the platforms
|
||||
of your choice. Just run it and grab a snack; you'll be waiting a while.
|
||||
"""
|
||||
|
||||
import sys, os, argparse, pathlib, traceback
|
||||
from cv_build_utils import execute, print_error, print_header, get_xcode_version, get_cmake_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Check for dependencies
|
||||
assert sys.version_info >= (3, 6), f"Python 3.6 or later is required! Current version is {sys.version_info}"
|
||||
# Need CMake 3.18.5/3.19 or later for a Silicon-related fix to building for the iOS Simulator.
|
||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/21425 for context.
|
||||
assert get_cmake_version() >= (3, 18, 5), f"CMake 3.18.5 or later is required. Current version is {get_cmake_version()}"
|
||||
# Need Xcode 12.2 for Apple Silicon support
|
||||
assert get_xcode_version() >= (12, 2), f"Xcode 12.2 command line tools or later are required! Current version is {get_xcode_version()}. \
|
||||
Run xcode-select to switch if you have multiple Xcode installs."
|
||||
|
||||
# Parse arguments
|
||||
description = """
|
||||
This script builds OpenCV into an xcframework supporting the Apple platforms of your choice.
|
||||
"""
|
||||
epilog = """
|
||||
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('--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"')
|
||||
parser.add_argument('--macos_archs', default=None, help='Select MacOS ARCHS. Default is "x86_64,arm64"')
|
||||
parser.add_argument('--catalyst_archs', default=None, help='Select Catalyst ARCHS. Default is "x86_64,arm64"')
|
||||
parser.add_argument('--build_only_specified_archs', default=False, action='store_true', help='if enabled, only directly specified archs are built and defaults are ignored')
|
||||
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
if unknown_args:
|
||||
print(f"The following args are not recognized by this script and will be passed through to the ios/osx build_framework.py scripts: {unknown_args}")
|
||||
|
||||
# Parse architectures from args
|
||||
iphoneos_archs = args.iphoneos_archs
|
||||
if not iphoneos_archs and not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
iphoneos_archs = "armv7,arm64"
|
||||
print(f'Using iPhoneOS ARCHS={iphoneos_archs}')
|
||||
|
||||
iphonesimulator_archs = args.iphonesimulator_archs
|
||||
if not iphonesimulator_archs and not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
iphonesimulator_archs = "x86_64,arm64"
|
||||
print(f'Using iPhoneSimulator ARCHS={iphonesimulator_archs}')
|
||||
|
||||
macos_archs = args.macos_archs
|
||||
if not macos_archs and not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
macos_archs = "x86_64,arm64"
|
||||
print(f'Using MacOS ARCHS={macos_archs}')
|
||||
|
||||
catalyst_archs = args.macos_archs
|
||||
if not catalyst_archs and not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
catalyst_archs = "x86_64,arm64"
|
||||
print(f'Using Catalyst ARCHS={catalyst_archs}')
|
||||
|
||||
# Build phase
|
||||
|
||||
try:
|
||||
# Build .frameworks for each platform
|
||||
osx_script_path = os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../osx/build_framework.py')
|
||||
ios_script_path = os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios/build_framework.py')
|
||||
|
||||
build_folders = []
|
||||
|
||||
def get_or_create_build_folder(base_dir, platform):
|
||||
build_folder = f"./{base_dir}/{platform}".replace(" ", "\\ ") # Escape spaces in output path
|
||||
pathlib.Path(build_folder).mkdir(parents=True, exist_ok=True)
|
||||
return build_folder
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
print_header("Building Catalyst frameworks")
|
||||
execute(command, cwd=os.getcwd())
|
||||
|
||||
# Put all the built .frameworks together into a .xcframework
|
||||
print_header("Building xcframework")
|
||||
xcframework_build_command = [
|
||||
"xcodebuild",
|
||||
"-create-xcframework",
|
||||
"-output",
|
||||
f"{args.out}/{args.framework_name}.xcframework",
|
||||
]
|
||||
for folder in build_folders:
|
||||
xcframework_build_command += ["-framework", f"{folder}/{args.framework_name}.framework"]
|
||||
execute(xcframework_build_command, cwd=os.getcwd())
|
||||
|
||||
print("")
|
||||
print_header(f"Finished building {args.out}/{args.framework_name}.xcframework")
|
||||
except Exception as e:
|
||||
print_error(e)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(1)
|
65
platforms/apple/cv_build_utils.py
Normal file
65
platforms/apple/cv_build_utils.py
Normal file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Common utilities. These should be compatible with Python 2 and 3.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
import sys, re
|
||||
from subprocess import check_call, check_output, CalledProcessError
|
||||
|
||||
def execute(cmd, cwd = None):
|
||||
print("Executing: %s in %s" % (cmd, cwd), file=sys.stderr)
|
||||
print('Executing: ' + ' '.join(cmd))
|
||||
retcode = check_call(cmd, cwd = cwd)
|
||||
if retcode != 0:
|
||||
raise Exception("Child returned:", retcode)
|
||||
|
||||
def print_header(text):
|
||||
print("="*60)
|
||||
print(text)
|
||||
print("="*60)
|
||||
|
||||
def print_error(text):
|
||||
print("="*60, file=sys.stderr)
|
||||
print("ERROR: %s" % text, file=sys.stderr)
|
||||
print("="*60, file=sys.stderr)
|
||||
|
||||
def get_xcode_major():
|
||||
ret = check_output(["xcodebuild", "-version"]).decode('utf-8')
|
||||
m = re.match(r'Xcode\s+(\d+)\..*', ret, flags=re.IGNORECASE)
|
||||
if m:
|
||||
return int(m.group(1))
|
||||
else:
|
||||
raise Exception("Failed to parse Xcode version")
|
||||
|
||||
def get_xcode_version():
|
||||
"""
|
||||
Returns the major and minor version of the current Xcode
|
||||
command line tools as a tuple of (major, minor)
|
||||
"""
|
||||
ret = check_output(["xcodebuild", "-version"]).decode('utf-8')
|
||||
m = re.match(r'Xcode\s+(\d+)\.(\d+)', ret, flags=re.IGNORECASE)
|
||||
if m:
|
||||
return (int(m.group(1)), int(m.group(2)))
|
||||
else:
|
||||
raise Exception("Failed to parse Xcode version")
|
||||
|
||||
def get_xcode_setting(var, projectdir):
|
||||
ret = check_output(["xcodebuild", "-showBuildSettings"], cwd = projectdir).decode('utf-8')
|
||||
m = re.search("\s" + var + " = (.*)", ret)
|
||||
if m:
|
||||
return m.group(1)
|
||||
else:
|
||||
raise Exception("Failed to parse Xcode settings")
|
||||
|
||||
def get_cmake_version():
|
||||
"""
|
||||
Returns the major and minor version of the current CMake
|
||||
command line tools as a tuple of (major, minor, revision)
|
||||
"""
|
||||
ret = check_output(["cmake", "--version"]).decode('utf-8')
|
||||
m = re.match(r'cmake\sversion\s+(\d+)\.(\d+).(\d+)', ret, flags=re.IGNORECASE)
|
||||
if m:
|
||||
return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
|
||||
else:
|
||||
raise Exception("Failed to parse CMake version")
|
40
platforms/apple/readme.md
Normal file
40
platforms/apple/readme.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Building for Apple Platforms
|
||||
|
||||
build_xcframework.py creates an xcframework supporting a variety of Apple platforms.
|
||||
|
||||
You'll need the following to run these steps:
|
||||
- MacOS 10.15 or later
|
||||
- Python 3.6 or later
|
||||
- CMake 3.18.5/3.19.0 or later (make sure the `cmake` command is available on your PATH)
|
||||
- Xcode 12.2 or later (and its command line tools)
|
||||
|
||||
You can then run build_xcframework.py, as below:
|
||||
```
|
||||
cd ~/<my_working_directory>
|
||||
python opencv/platforms/apple/build_xcframework.py ./build_xcframework
|
||||
```
|
||||
|
||||
Grab a coffee, because you'll be here for a while. By default this builds OpenCV for 8 architectures across 4 platforms:
|
||||
|
||||
- iOS (`--iphoneos_archs`): arm64, armv7
|
||||
- iOS Simulator (`--iphonesimulator_archs`): x86_64, arm64
|
||||
- macOS (`--macos_archs`): x86_64, arm64
|
||||
- Mac Catalyst (`--catalyst_archs`): x86_64, arm64
|
||||
|
||||
If everything's fine, you will eventually get `opencv2.xcframework` in the output directory.
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
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
|
||||
```
|
0
platforms/ios/__init__.py
Normal file
0
platforms/ios/__init__.py
Normal file
@ -32,35 +32,15 @@ Adding --dynamic parameter will build {framework_name}.framework as App Store dy
|
||||
"""
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
import glob, re, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing
|
||||
import glob, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing
|
||||
from subprocess import check_call, check_output, CalledProcessError
|
||||
from distutils.dir_util import copy_tree
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../apple'))
|
||||
from cv_build_utils import execute, print_error, get_xcode_major, get_xcode_setting
|
||||
|
||||
IPHONEOS_DEPLOYMENT_TARGET='9.0' # default, can be changed via command line options or environment variable
|
||||
|
||||
def execute(cmd, cwd = None):
|
||||
print("Executing: %s in %s" % (cmd, cwd), file=sys.stderr)
|
||||
print('Executing: ' + ' '.join(cmd))
|
||||
retcode = check_call(cmd, cwd = cwd)
|
||||
if retcode != 0:
|
||||
raise Exception("Child returned:", retcode)
|
||||
|
||||
def getXCodeMajor():
|
||||
ret = check_output(["xcodebuild", "-version"]).decode('utf-8')
|
||||
m = re.match(r'Xcode\s+(\d+)\..*', ret, flags=re.IGNORECASE)
|
||||
if m:
|
||||
return int(m.group(1))
|
||||
else:
|
||||
raise Exception("Failed to parse Xcode version")
|
||||
|
||||
def getXCodeSetting(var, projectdir):
|
||||
ret = check_output(["xcodebuild", "-showBuildSettings"], cwd = projectdir)
|
||||
m = re.search("\s" + var + " = (.*)", ret)
|
||||
if m:
|
||||
return m.group(1)
|
||||
else:
|
||||
raise Exception("Failed to parse Xcode settings")
|
||||
|
||||
class Builder:
|
||||
def __init__(self, opencv, contrib, dynamic, bitcodedisabled, exclude, disable, enablenonfree, targets, debug, debug_info, framework_name, run_tests, build_docs):
|
||||
self.opencv = os.path.abspath(opencv)
|
||||
@ -99,7 +79,7 @@ class Builder:
|
||||
main_working_dir = os.path.join(outdir, "build")
|
||||
dirs = []
|
||||
|
||||
xcode_ver = getXCodeMajor()
|
||||
xcode_ver = get_xcode_major()
|
||||
|
||||
# build each architecture separately
|
||||
alltargets = []
|
||||
@ -119,6 +99,30 @@ class Builder:
|
||||
if xcode_ver >= 7 and target[1] == 'iPhoneOS' and self.bitcodedisabled == False:
|
||||
cmake_flags.append("-DCMAKE_C_FLAGS=-fembed-bitcode")
|
||||
cmake_flags.append("-DCMAKE_CXX_FLAGS=-fembed-bitcode")
|
||||
if xcode_ver >= 7 and target[1] == 'Catalyst':
|
||||
sdk_path = check_output(["xcodebuild", "-version", "-sdk", "macosx", "Path"]).decode('utf-8').rstrip()
|
||||
c_flags = [
|
||||
"-target %s-apple-ios13.0-macabi" % target[0], # e.g. x86_64-apple-ios13.2-macabi # -mmacosx-version-min=10.15
|
||||
"-isysroot %s" % sdk_path,
|
||||
"-iframework %s/System/iOSSupport/System/Library/Frameworks" % sdk_path,
|
||||
"-isystem %s/System/iOSSupport/usr/include" % sdk_path,
|
||||
]
|
||||
if self.bitcodedisabled == False:
|
||||
c_flags.append("-fembed-bitcode")
|
||||
cmake_flags.append("-DCMAKE_C_FLAGS=" + " ".join(c_flags))
|
||||
cmake_flags.append("-DCMAKE_CXX_FLAGS=" + " ".join(c_flags))
|
||||
cmake_flags.append("-DCMAKE_EXE_LINKER_FLAGS=" + " ".join(c_flags))
|
||||
|
||||
# CMake annot compile Swift for Catalyst https://gitlab.kitware.com/cmake/cmake/-/issues/21436
|
||||
# cmake_flags.append("-DCMAKE_Swift_FLAGS=" + " " + target_flag)
|
||||
cmake_flags.append("-DSWIFT_DISABLED=1")
|
||||
|
||||
cmake_flags.append("-DIOS=1") # Build the iOS codebase
|
||||
cmake_flags.append("-DMAC_CATALYST=1") # Set a flag for Mac Catalyst, just in case we need it
|
||||
cmake_flags.append("-DWITH_OPENCL=OFF") # Disable OpenCL; it isn't compatible with iOS
|
||||
cmake_flags.append("-DCMAKE_OSX_SYSROOT=%s" % sdk_path)
|
||||
cmake_flags.append("-DCMAKE_CXX_COMPILER_WORKS=TRUE")
|
||||
cmake_flags.append("-DCMAKE_C_COMPILER_WORKS=TRUE")
|
||||
self.buildOne(target[0], target[1], main_build_dir, cmake_flags)
|
||||
|
||||
if not self.dynamic:
|
||||
@ -128,10 +132,10 @@ class Builder:
|
||||
self.makeFramework(outdir, dirs)
|
||||
if self.build_objc_wrapper:
|
||||
if self.run_tests:
|
||||
check_call([sys.argv[0].replace("build_framework", "run_tests"), "--framework_dir=" + outdir, "--framework_name=" + self.framework_name, dirs[0] + "/modules/objc_bindings_generator/{}/test".format(self.getObjcTarget())])
|
||||
check_call([sys.argv[0].replace("build_framework", "run_tests"), "--framework_dir=" + outdir, "--framework_name=" + self.framework_name, dirs[0] + "/modules/objc_bindings_generator/{}/test".format(self.getObjcTarget(target[1]))])
|
||||
else:
|
||||
print("To run tests call:")
|
||||
print(sys.argv[0].replace("build_framework", "run_tests") + " --framework_dir=" + outdir + " --framework_name=" + self.framework_name + " " + dirs[0] + "/modules/objc_bindings_generator/{}/test".format(self.getObjcTarget()))
|
||||
print(sys.argv[0].replace("build_framework", "run_tests") + " --framework_dir=" + outdir + " --framework_name=" + self.framework_name + " " + dirs[0] + "/modules/objc_bindings_generator/{}/test".format(self.getObjcTarget(target[1])))
|
||||
if self.build_docs:
|
||||
check_call([sys.argv[0].replace("build_framework", "build_docs"), dirs[0] + "/modules/objc/framework_build"])
|
||||
doc_path = os.path.join(dirs[0], "modules", "objc", "doc_build", "docs")
|
||||
@ -147,9 +151,7 @@ class Builder:
|
||||
try:
|
||||
self._build(outdir)
|
||||
except Exception as e:
|
||||
print("="*60, file=sys.stderr)
|
||||
print("ERROR: %s" % e, file=sys.stderr)
|
||||
print("="*60, file=sys.stderr)
|
||||
print_error(e)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
@ -170,17 +172,19 @@ class Builder:
|
||||
"-DOPENCV_INCLUDE_INSTALL_PATH=include",
|
||||
"-DOPENCV_3P_LIB_INSTALL_PATH=lib/3rdparty",
|
||||
"-DFRAMEWORK_NAME=%s" % self.framework_name,
|
||||
] + ([
|
||||
"-DBUILD_SHARED_LIBS=ON",
|
||||
"-DCMAKE_MACOSX_BUNDLE=ON",
|
||||
"-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=NO",
|
||||
] if self.dynamic and not self.build_objc_wrapper else []) + ([
|
||||
"-DDYNAMIC_PLIST=ON"
|
||||
] if self.dynamic else []) + ([
|
||||
"-DOPENCV_ENABLE_NONFREE=ON"
|
||||
] if self.enablenonfree else []) + ([
|
||||
"-DBUILD_WITH_DEBUG_INFO=ON"
|
||||
] if self.debug_info else [])
|
||||
]
|
||||
if self.dynamic:
|
||||
args += [
|
||||
"-DDYNAMIC_PLIST=ON"
|
||||
]
|
||||
if self.enablenonfree:
|
||||
args += [
|
||||
"-DOPENCV_ENABLE_NONFREE=ON"
|
||||
]
|
||||
if self.debug_info:
|
||||
args += [
|
||||
"-DBUILD_WITH_DEBUG_INFO=ON"
|
||||
]
|
||||
|
||||
if len(self.exclude) > 0:
|
||||
args += ["-DBUILD_opencv_%s=OFF" % m for m in self.exclude]
|
||||
@ -202,21 +206,18 @@ class Builder:
|
||||
buildcmd += [
|
||||
"IPHONEOS_DEPLOYMENT_TARGET=" + os.environ['IPHONEOS_DEPLOYMENT_TARGET'],
|
||||
"ARCHS=%s" % arch,
|
||||
"-sdk", target.lower(),
|
||||
"-configuration", self.getConfiguration(),
|
||||
"-parallelizeTargets",
|
||||
"-jobs", str(multiprocessing.cpu_count()),
|
||||
]
|
||||
|
||||
buildcmd += [
|
||||
"-sdk", target.lower(),
|
||||
"-configuration", self.getConfiguration(),
|
||||
"-parallelizeTargets",
|
||||
"-jobs", str(multiprocessing.cpu_count()),
|
||||
]
|
||||
|
||||
return buildcmd
|
||||
|
||||
def getInfoPlist(self, builddirs):
|
||||
return os.path.join(builddirs[0], "ios", "Info.plist")
|
||||
|
||||
def getObjcTarget(self):
|
||||
def getObjcTarget(self, target):
|
||||
# Obj-C generation target
|
||||
return 'ios'
|
||||
|
||||
@ -226,9 +227,28 @@ class Builder:
|
||||
(["-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain] if toolchain is not None else [])
|
||||
if target.lower().startswith("iphoneos"):
|
||||
cmakecmd.append("-DCPU_BASELINE=DETECT")
|
||||
if target.lower() == "macosx":
|
||||
build_arch = check_output(["uname", "-m"]).rstrip()
|
||||
if target.lower().startswith("iphonesimulator"):
|
||||
build_arch = check_output(["uname", "-m"]).decode('utf-8').rstrip()
|
||||
if build_arch != arch:
|
||||
print("build_arch (%s) != arch (%s)" % (build_arch, arch))
|
||||
cmakecmd.append("-DCMAKE_SYSTEM_PROCESSOR=" + arch)
|
||||
cmakecmd.append("-DCMAKE_OSX_ARCHITECTURES=" + arch)
|
||||
cmakecmd.append("-DCPU_BASELINE=DETECT")
|
||||
cmakecmd.append("-DCMAKE_CROSSCOMPILING=ON")
|
||||
cmakecmd.append("-DOPENCV_WORKAROUND_CMAKE_20989=ON")
|
||||
if target.lower() == "catalyst":
|
||||
build_arch = check_output(["uname", "-m"]).decode('utf-8').rstrip()
|
||||
if build_arch != arch:
|
||||
print("build_arch (%s) != arch (%s)" % (build_arch, arch))
|
||||
cmakecmd.append("-DCMAKE_SYSTEM_PROCESSOR=" + arch)
|
||||
cmakecmd.append("-DCMAKE_OSX_ARCHITECTURES=" + arch)
|
||||
cmakecmd.append("-DCPU_BASELINE=DETECT")
|
||||
cmakecmd.append("-DCMAKE_CROSSCOMPILING=ON")
|
||||
cmakecmd.append("-DOPENCV_WORKAROUND_CMAKE_20989=ON")
|
||||
if target.lower() == "macosx":
|
||||
build_arch = check_output(["uname", "-m"]).decode('utf-8').rstrip()
|
||||
if build_arch != arch:
|
||||
print("build_arch (%s) != arch (%s)" % (build_arch, arch))
|
||||
cmakecmd.append("-DCMAKE_SYSTEM_PROCESSOR=" + arch)
|
||||
cmakecmd.append("-DCMAKE_OSX_ARCHITECTURES=" + arch)
|
||||
cmakecmd.append("-DCPU_BASELINE=DETECT")
|
||||
@ -249,7 +269,17 @@ class Builder:
|
||||
#cmakecmd.append(self.opencv)
|
||||
#cmakecmd.extend(cmakeargs)
|
||||
cmakecmd = self.makeCMakeCmd(arch, target, self.opencv, cmakeargs)
|
||||
print("")
|
||||
print("=================================")
|
||||
print("CMake")
|
||||
print("=================================")
|
||||
print("")
|
||||
execute(cmakecmd, cwd = builddir)
|
||||
print("")
|
||||
print("=================================")
|
||||
print("Xcodebuild")
|
||||
print("=================================")
|
||||
print("")
|
||||
|
||||
# Clean and build
|
||||
clean_dir = os.path.join(builddir, "install")
|
||||
@ -259,7 +289,9 @@ class Builder:
|
||||
execute(buildcmd + ["-target", "ALL_BUILD", "build"], cwd = builddir)
|
||||
execute(["cmake", "-DBUILD_TYPE=%s" % self.getConfiguration(), "-P", "cmake_install.cmake"], cwd = builddir)
|
||||
if self.build_objc_wrapper:
|
||||
cmakecmd = self.makeCMakeCmd(arch, target, builddir + "/modules/objc_bindings_generator/{}/gen".format(self.getObjcTarget()), cmakeargs)
|
||||
cmakecmd = self.makeCMakeCmd(arch, target, builddir + "/modules/objc_bindings_generator/{}/gen".format(self.getObjcTarget(target)), cmakeargs)
|
||||
# cmakecmd.append("-DCMAKE_Swift_FLAGS=" + "-target x86_64-apple-ios13.0-macabi")
|
||||
# cmakecmd.append("-DCMAKE_EXE_LINKER_FLAGS=" + "-target x86_64-apple-ios13.0-macabi")
|
||||
cmakecmd.append("-DBUILD_ROOT=%s" % builddir)
|
||||
cmakecmd.append("-DCMAKE_INSTALL_NAME_TOOL=install_name_tool")
|
||||
cmakecmd.append("--no-warn-unused-cli")
|
||||
@ -280,24 +312,51 @@ class Builder:
|
||||
def makeDynamicLib(self, builddir):
|
||||
target = builddir[(builddir.rfind("build-") + 6):]
|
||||
target_platform = target[(target.rfind("-") + 1):]
|
||||
is_device = target_platform == "iphoneos"
|
||||
res = os.path.join(builddir, "install", "lib", self.framework_name + ".framework", self.framework_name)
|
||||
is_device = target_platform == "iphoneos" or target_platform == "catalyst"
|
||||
framework_dir = os.path.join(builddir, "install", "lib", self.framework_name + ".framework")
|
||||
if not os.path.exists(framework_dir):
|
||||
os.makedirs(framework_dir)
|
||||
res = os.path.join(framework_dir, self.framework_name)
|
||||
libs = glob.glob(os.path.join(builddir, "install", "lib", "*.a"))
|
||||
module = [os.path.join(builddir, "lib", self.getConfiguration(), self.framework_name + ".framework", self.framework_name)]
|
||||
if self.build_objc_wrapper:
|
||||
module = [os.path.join(builddir, "lib", self.getConfiguration(), self.framework_name + ".framework", self.framework_name)]
|
||||
else:
|
||||
module = []
|
||||
|
||||
libs3 = glob.glob(os.path.join(builddir, "install", "lib", "3rdparty", "*.a"))
|
||||
|
||||
link_target = target[:target.find("-")] + "-apple-ios" + os.environ['IPHONEOS_DEPLOYMENT_TARGET'] + ("-simulator" if target.endswith("simulator") else "")
|
||||
if os.environ.get('IPHONEOS_DEPLOYMENT_TARGET'):
|
||||
link_target = target[:target.find("-")] + "-apple-ios" + os.environ['IPHONEOS_DEPLOYMENT_TARGET'] + ("-simulator" if target.endswith("simulator") else "")
|
||||
else:
|
||||
if target_platform == "catalyst":
|
||||
link_target = "%s-apple-ios13.0-macabi" % target[:target.find("-")]
|
||||
else:
|
||||
link_target = "%s-apple-darwin" % target[:target.find("-")]
|
||||
bitcode_flags = ["-fembed-bitcode", "-Xlinker", "-bitcode_verify"] if is_device and not self.bitcodedisabled else []
|
||||
toolchain_dir = getXCodeSetting("TOOLCHAIN_DIR", builddir)
|
||||
toolchain_dir = get_xcode_setting("TOOLCHAIN_DIR", builddir)
|
||||
sdk_dir = get_xcode_setting("SDK_DIR", builddir)
|
||||
framework_options = []
|
||||
swift_link_dirs = ["-L" + toolchain_dir + "/usr/lib/swift/" + target_platform, "-L/usr/lib/swift"]
|
||||
sdk_dir = getXCodeSetting("SDK_DIR", builddir)
|
||||
if target_platform == "catalyst":
|
||||
swift_link_dirs = ["-L" + toolchain_dir + "/usr/lib/swift/" + "maccatalyst", "-L/usr/lib/swift"]
|
||||
framework_options = [
|
||||
"-iframework", "%s/System/iOSSupport/System/Library/Frameworks" % sdk_dir,
|
||||
"-framework", "AVFoundation", "-framework", "UIKit", "-framework", "CoreGraphics",
|
||||
"-framework", "CoreImage", "-framework", "CoreMedia", "-framework", "QuartzCore",
|
||||
]
|
||||
elif target_platform == "macosx":
|
||||
framework_options = [
|
||||
"-framework", "AVFoundation", "-framework", "AppKit", "-framework", "CoreGraphics",
|
||||
"-framework", "CoreImage", "-framework", "CoreMedia", "-framework", "QuartzCore",
|
||||
"-framework", "Accelerate", "-framework", "OpenCL",
|
||||
]
|
||||
execute([
|
||||
"clang++",
|
||||
"-Xlinker", "-rpath",
|
||||
"-Xlinker", "/usr/lib/swift",
|
||||
"-target", link_target,
|
||||
"-isysroot", sdk_dir,
|
||||
"-isysroot", sdk_dir,] +
|
||||
framework_options + [
|
||||
"-install_name", "@rpath/" + self.framework_name + ".framework/" + self.framework_name,
|
||||
"-dynamiclib", "-dead_strip", "-fobjc-link-runtime", "-all_load",
|
||||
"-o", res
|
||||
@ -402,6 +461,8 @@ class iOSBuilder(Builder):
|
||||
def copy_samples(self, outdir):
|
||||
print('Copying samples to: ' + outdir)
|
||||
samples_dir = os.path.join(outdir, "samples")
|
||||
if os.path.exists(samples_dir):
|
||||
shutil.rmtree(samples_dir)
|
||||
shutil.copytree(os.path.join(self.opencv, "samples", "swift", "ios"), samples_dir)
|
||||
if self.framework_name != "OpenCV":
|
||||
for dirname, dirs, files in os.walk(samples_dir):
|
||||
@ -430,8 +491,9 @@ if __name__ == "__main__":
|
||||
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('--build_only_specified_archs', default=False, action='store_true', help='if enabled, only directly specified archs are built and defaults are ignored')
|
||||
parser.add_argument('--iphoneos_archs', default=None, help='select iPhoneOS target ARCHS. Default is "armv7,armv7s,arm64"')
|
||||
parser.add_argument('--iphonesimulator_archs', default=None, help='select iPhoneSimulator target ARCHS. Default is "i386,x86_64"')
|
||||
parser.add_argument('--enable_nonfree', default=False, dest='enablenonfree', action='store_true', help='enable non-free modules (disabled by default)')
|
||||
parser.add_argument('--debug', default=False, dest='debug', action='store_true', help='Build "Debug" binaries (disabled by default)')
|
||||
parser.add_argument('--debug_info', default=False, dest='debug_info', action='store_true', help='Build with debug information (useful for Release mode: BUILD_WITH_DEBUG_INFO=ON)')
|
||||
@ -440,26 +502,58 @@ if __name__ == "__main__":
|
||||
parser.add_argument('--run_tests', default=False, dest='run_tests', action='store_true', help='Run tests')
|
||||
parser.add_argument('--build_docs', default=False, dest='build_docs', action='store_true', help='Build docs')
|
||||
|
||||
args = parser.parse_args()
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
if unknown_args:
|
||||
print("The following args are not recognized and will not be used: %s" % unknown_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(',')
|
||||
|
||||
iphoneos_archs = None
|
||||
if args.iphoneos_archs:
|
||||
iphoneos_archs = args.iphoneos_archs.split(',')
|
||||
elif not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
iphoneos_archs = ["armv7", "armv7s", "arm64"]
|
||||
print('Using iPhoneOS ARCHS=' + str(iphoneos_archs))
|
||||
iphonesimulator_archs = args.iphonesimulator_archs.split(',')
|
||||
|
||||
iphonesimulator_archs = None
|
||||
if args.iphonesimulator_archs:
|
||||
iphonesimulator_archs = args.iphonesimulator_archs.split(',')
|
||||
elif not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
iphonesimulator_archs = ["i386", "x86_64"]
|
||||
print('Using iPhoneSimulator ARCHS=' + str(iphonesimulator_archs))
|
||||
|
||||
# Prevent the build from happening if the same architecture is specified for multiple platforms.
|
||||
# When `lipo` is run to stitch the frameworks together into a fat framework, it'll fail, so it's
|
||||
# better to stop here while we're ahead.
|
||||
if iphoneos_archs and iphonesimulator_archs:
|
||||
duplicate_archs = set(iphoneos_archs).intersection(iphonesimulator_archs)
|
||||
if duplicate_archs:
|
||||
print_error("Cannot have the same architecture for multiple platforms in a fat framework! Consider using build_xcframework.py in the apple platform folder instead. Duplicate archs are %s" % duplicate_archs)
|
||||
exit(1)
|
||||
|
||||
if args.legacy_build:
|
||||
args.framework_name = "opencv2"
|
||||
if not "objc" in args.without:
|
||||
args.without.append("objc")
|
||||
|
||||
b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.disable, args.enablenonfree,
|
||||
[
|
||||
(iphoneos_archs, "iPhoneOS"),
|
||||
] if os.environ.get('BUILD_PRECOMMIT', None) else
|
||||
[
|
||||
(iphoneos_archs, "iPhoneOS"),
|
||||
(iphonesimulator_archs, "iPhoneSimulator"),
|
||||
], args.debug, args.debug_info, args.framework_name, args.run_tests, args.build_docs)
|
||||
targets = []
|
||||
if os.environ.get('BUILD_PRECOMMIT', None):
|
||||
if not iphoneos_archs:
|
||||
print_error("--iphoneos_archs must have at least one value")
|
||||
sys.exit(1)
|
||||
targets.append((iphoneos_archs, "iPhoneOS"))
|
||||
else:
|
||||
if not iphoneos_archs and not iphonesimulator_archs:
|
||||
print_error("--iphoneos_archs and --iphonesimulator_archs are undefined; nothing will be built.")
|
||||
sys.exit(1)
|
||||
if iphoneos_archs:
|
||||
targets.append((iphoneos_archs, "iPhoneOS"))
|
||||
if iphonesimulator_archs:
|
||||
targets.append((iphonesimulator_archs, "iPhoneSimulator"))
|
||||
|
||||
b = iOSBuilder(args.opencv, args.contrib, args.dynamic, args.bitcodedisabled, args.without, args.disable, args.enablenonfree, targets, args.debug, args.debug_info, args.framework_name, args.run_tests, args.build_docs)
|
||||
|
||||
b.build(args.out)
|
||||
|
@ -0,0 +1,4 @@
|
||||
set(MAC_CATALYST TRUE)
|
||||
message(STATUS "Setting up Catalyst toolchain for IOS_ARCH='${IOS_ARCH}'")
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/common-ios-toolchain.cmake)
|
||||
message(STATUS "Catalyst toolchain loaded")
|
@ -79,8 +79,11 @@ endif()
|
||||
if(NOT DEFINED CMAKE_OSX_SYSROOT)
|
||||
if(IPHONEOS)
|
||||
set(CMAKE_OSX_SYSROOT "iphoneos")
|
||||
else()
|
||||
elseif(IPHONESIMULATOR)
|
||||
set(CMAKE_OSX_SYSROOT "iphonesimulator")
|
||||
elseif(MAC_CATALYST)
|
||||
# Use MacOS SDK for Catalyst builds
|
||||
set(CMAKE_OSX_SYSROOT "macosx")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_MACOSX_BUNDLE YES)
|
||||
@ -90,7 +93,7 @@ if(APPLE_FRAMEWORK AND NOT BUILD_SHARED_LIBS)
|
||||
set(CMAKE_OSX_ARCHITECTURES "${IOS_ARCH}" CACHE INTERNAL "Build architecture for iOS" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED IPHONEOS_DEPLOYMENT_TARGET)
|
||||
if(NOT DEFINED IPHONEOS_DEPLOYMENT_TARGET AND NOT MAC_CATALYST)
|
||||
if(NOT DEFINED ENV{IPHONEOS_DEPLOYMENT_TARGET})
|
||||
message(FATAL_ERROR "IPHONEOS_DEPLOYMENT_TARGET is not specified")
|
||||
endif()
|
||||
|
0
platforms/osx/__init__.py
Normal file
0
platforms/osx/__init__.py
Normal file
@ -9,14 +9,19 @@ import os, os.path, sys, argparse, traceback, multiprocessing
|
||||
# import common code
|
||||
sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios'))
|
||||
from build_framework import Builder
|
||||
sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../apple'))
|
||||
from cv_build_utils import print_error
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET='10.12' # default, can be changed via command line options or environment variable
|
||||
|
||||
class OSXBuilder(Builder):
|
||||
|
||||
def getObjcTarget(self):
|
||||
def getObjcTarget(self, target):
|
||||
# Obj-C generation target
|
||||
return 'osx'
|
||||
if target == "Catalyst":
|
||||
return 'ios'
|
||||
else:
|
||||
return 'osx'
|
||||
|
||||
def getToolchain(self, arch, target):
|
||||
return None
|
||||
@ -26,11 +31,21 @@ class OSXBuilder(Builder):
|
||||
"xcodebuild",
|
||||
"MACOSX_DEPLOYMENT_TARGET=" + os.environ['MACOSX_DEPLOYMENT_TARGET'],
|
||||
"ARCHS=%s" % arch,
|
||||
"-sdk", target.lower(),
|
||||
"-sdk", "macosx" if target == "Catalyst" else target.lower(),
|
||||
"-configuration", "Debug" if self.debug else "Release",
|
||||
"-parallelizeTargets",
|
||||
"-jobs", str(multiprocessing.cpu_count())
|
||||
]
|
||||
|
||||
if target == "Catalyst":
|
||||
buildcmd.append("-destination 'platform=macOS,arch=%s,variant=Mac Catalyst'" % arch)
|
||||
buildcmd.append("-UseModernBuildSystem=YES")
|
||||
buildcmd.append("SKIP_INSTALL=NO")
|
||||
buildcmd.append("BUILD_LIBRARY_FOR_DISTRIBUTION=YES")
|
||||
buildcmd.append("TARGETED_DEVICE_FAMILY=\"1,2\"")
|
||||
buildcmd.append("SDKROOT=iphoneos")
|
||||
buildcmd.append("SUPPORTS_MAC_CATALYST=YES")
|
||||
|
||||
return buildcmd
|
||||
|
||||
def getInfoPlist(self, builddirs):
|
||||
@ -45,30 +60,68 @@ if __name__ == "__main__":
|
||||
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('--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')
|
||||
parser.add_argument('--archs', default='x86_64', help='Select target ARCHS (set to "x86_64,arm64" to build Universal Binary for Big Sur and later)')
|
||||
parser.add_argument('--build_only_specified_archs', default=False, action='store_true', help='if enabled, only directly specified archs are built and defaults are ignored')
|
||||
parser.add_argument('--archs', default=None, help='(Deprecated! Prefer --macos_archs instead.) Select target ARCHS (set to "x86_64,arm64" to build Universal Binary for Big Sur and later). Default is "x86_64".')
|
||||
parser.add_argument('--macos_archs', default=None, help='Select target ARCHS (set to "x86_64,arm64" to build Universal Binary for Big Sur and later). Default is "x86_64"')
|
||||
parser.add_argument('--catalyst_archs', default=None, help='Select target ARCHS (set to "x86_64,arm64" to build Universal Binary for Big Sur and later). Default is None')
|
||||
parser.add_argument('--debug', action='store_true', help='Build "Debug" binaries (CMAKE_BUILD_TYPE=Debug)')
|
||||
parser.add_argument('--debug_info', action='store_true', help='Build with debug information (useful for Release mode: BUILD_WITH_DEBUG_INFO=ON)')
|
||||
parser.add_argument('--framework_name', default='opencv2', dest='framework_name', action='store_true', help='Name of OpenCV framework (default: opencv2, will change to OpenCV in future version)')
|
||||
parser.add_argument('--framework_name', default='opencv2', dest='framework_name', help='Name of OpenCV framework (default: opencv2, will change to OpenCV in future version)')
|
||||
parser.add_argument('--legacy_build', default=False, dest='legacy_build', action='store_true', help='Build legacy framework (default: False, equivalent to "--framework_name=opencv2 --without=objc")')
|
||||
parser.add_argument('--run_tests', default=False, dest='run_tests', action='store_true', help='Run tests')
|
||||
parser.add_argument('--build_docs', default=False, dest='build_docs', action='store_true', help='Build docs')
|
||||
|
||||
args = parser.parse_args()
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
if unknown_args:
|
||||
print("The following args are not recognized and will not be used: %s" % unknown_args)
|
||||
|
||||
os.environ['MACOSX_DEPLOYMENT_TARGET'] = args.macosx_deployment_target
|
||||
print('Using MACOSX_DEPLOYMENT_TARGET=' + os.environ['MACOSX_DEPLOYMENT_TARGET'])
|
||||
archs = args.archs.split(',')
|
||||
print('Using ARCHS=' + str(archs))
|
||||
|
||||
macos_archs = None
|
||||
if args.archs:
|
||||
# The archs flag is replaced by macos_archs. If the user specifies archs,
|
||||
# treat it as if the user specified the macos_archs flag instead.
|
||||
args.macos_archs = args.archs
|
||||
print("--archs is deprecated! Prefer --macos_archs instead.")
|
||||
if args.macos_archs:
|
||||
macos_archs = args.macos_archs.split(',')
|
||||
elif not args.build_only_specified_archs:
|
||||
# Supply defaults
|
||||
macos_archs = ["x86_64"]
|
||||
print('Using MacOS ARCHS=' + str(macos_archs))
|
||||
|
||||
catalyst_archs = None
|
||||
if args.catalyst_archs:
|
||||
catalyst_archs = args.catalyst_archs.split(',')
|
||||
# TODO: To avoid breaking existing CI, catalyst_archs has no defaults. When we can make a breaking change, this should specify a default arch.
|
||||
print('Using Catalyst ARCHS=' + str(catalyst_archs))
|
||||
|
||||
# Prevent the build from happening if the same architecture is specified for multiple platforms.
|
||||
# When `lipo` is run to stitch the frameworks together into a fat framework, it'll fail, so it's
|
||||
# better to stop here while we're ahead.
|
||||
if macos_archs and catalyst_archs:
|
||||
duplicate_archs = set(macos_archs).intersection(catalyst_archs)
|
||||
if duplicate_archs:
|
||||
print_error("Cannot have the same architecture for multiple platforms in a fat framework! Consider using build_xcframework.py in the apple platform folder instead. Duplicate archs are %s" % duplicate_archs)
|
||||
exit(1)
|
||||
|
||||
if args.legacy_build:
|
||||
args.framework_name = "opencv2"
|
||||
if not "objc" in args.without:
|
||||
args.without.append("objc")
|
||||
|
||||
b = OSXBuilder(args.opencv, args.contrib, False, False, args.without, args.disable, args.enablenonfree,
|
||||
[
|
||||
(archs, "MacOSX")
|
||||
], args.debug, args.debug_info, args.framework_name, args.run_tests, args.build_docs)
|
||||
targets = []
|
||||
if not macos_archs and not catalyst_archs:
|
||||
print_error("--macos_archs and --catalyst_archs are undefined; nothing will be built.")
|
||||
sys.exit(1)
|
||||
if macos_archs:
|
||||
targets.append((macos_archs, "MacOSX"))
|
||||
if catalyst_archs:
|
||||
targets.append((catalyst_archs, "Catalyst")),
|
||||
|
||||
b = OSXBuilder(args.opencv, args.contrib, args.dynamic, True, args.without, args.disable, args.enablenonfree, targets, args.debug, args.debug_info, args.framework_name, args.run_tests, args.build_docs)
|
||||
b.build(args.out)
|
||||
|
Loading…
Reference in New Issue
Block a user