feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake

1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试
2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程
3.重整权利声明文件,重整代码工程,确保最小化侵权风险

Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake
Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
wangzhengyang
2022-05-10 09:54:44 +08:00
parent ecdd171c6f
commit 718c41634f
10018 changed files with 3593797 additions and 186748 deletions

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${FRAMEWORK_NAME}</string>
<key>CFBundleName</key>
<string>${OPENCV_APPLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${OPENCV_APPLE_BUNDLE_ID}</string>
<key>CFBundleVersion</key>
<string>${OPENCV_LIBVERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${OPENCV_LIBVERSION}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>MinimumOSVersion</key>
<string>8.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
</dict>
</plist>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>${OPENCV_APPLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${OPENCV_APPLE_BUNDLE_ID}</string>
<key>CFBundleVersion</key>
<string>${OPENCV_LIBVERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${OPENCV_LIBVERSION}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>
</plist>

View File

View File

@ -0,0 +1,87 @@
#!/usr/bin/env python
"""
This script builds OpenCV docs for iOS.
"""
from __future__ import print_function
import os, sys, multiprocessing, argparse, traceback
from subprocess import check_call, check_output, CalledProcessError, Popen
def execute(cmd, cwd = None, output = None):
if not output:
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)
else:
with open(output, "a") as f:
f.flush()
p = Popen(cmd, cwd = cwd, stdout = f)
os.waitpid(p.pid, 0)
class DocBuilder:
def __init__(self, script_dir, framework_dir, output_dir, framework_header, framework_name, arch, target):
self.script_dir = script_dir
self.framework_dir = framework_dir
self.output_dir = output_dir
self.framework_header = framework_header
self.framework_name = framework_name
self.arch = arch
self.target = target
def _build(self):
if not os.path.isdir(self.output_dir):
os.makedirs(self.output_dir)
self.buildDocs()
def build(self):
try:
self._build()
except Exception as e:
print("="*60, file=sys.stderr)
print("ERROR: %s" % e, file=sys.stderr)
print("="*60, file=sys.stderr)
traceback.print_exc(file=sys.stderr)
sys.exit(1)
def getToolchain(self):
return None
def getSourceKitten(self):
ret = check_output(["gem", "which", "jazzy"])
if ret.find('ERROR:') == 0:
raise Exception("Failed to find jazzy")
else:
return os.path.join(ret[0:ret.rfind('/')], '../bin/sourcekitten')
def buildDocs(self):
sourceKitten = self.getSourceKitten()
sourceKittenSwiftDoc = [sourceKitten, "doc", "--module-name", self.framework_name, "--", "-project", self.framework_name + ".xcodeproj", "ARCHS=" + self.arch, "-sdk", self.target, "-configuration", "Release", "-parallelizeTargets", "-jobs", str(multiprocessing.cpu_count()), "-target", "opencv_objc_framework"]
execute(sourceKittenSwiftDoc, cwd = self.framework_dir, output = os.path.join(self.output_dir, "swiftDoc.json"))
sdk_dir = check_output(["xcrun", "--show-sdk-path", "--sdk", self.target]).rstrip()
sourceKittenObjcDoc = [sourceKitten, "doc", "--objc", self.framework_header, "--", "-x", "objective-c", "-isysroot", sdk_dir, "-fmodules"]
print(sourceKittenObjcDoc)
execute(sourceKittenObjcDoc, cwd = self.framework_dir, output = os.path.join(self.output_dir, "objcDoc.json"))
execute(["jazzy", "--author", "OpenCV", "--author_url", "http://opencv.org", "--github_url", "https://github.com/opencv/opencv", "--module", self.framework_name, "--undocumented-text", "\"\"", "--sourcekitten-sourcefile", "swiftDoc.json,objcDoc.json"], cwd = self.output_dir)
class iOSDocBuilder(DocBuilder):
def getToolchain(self):
return None
if __name__ == "__main__":
script_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
parser = argparse.ArgumentParser(description='The script builds OpenCV docs for iOS.')
parser.add_argument('framework_dir', metavar='FRAMEWORK_DIR', help='folder where framework build files are located')
parser.add_argument('--output_dir', default=None, help='folder where docs will be built (default is "../doc_build" relative to framework_dir)')
parser.add_argument('--framework_header', default=None, help='umbrella header for OpenCV framework (default is "../../../lib/Release/{framework_name}.framework/Headers/{framework_name}.h")')
parser.add_argument('--framework_name', default='opencv2', help='Name of OpenCV framework (default: opencv2, will change to OpenCV in future version)')
args = parser.parse_args()
arch = "x86_64"
target = "iphonesimulator"
b = iOSDocBuilder(script_dir, args.framework_dir, args.output_dir if args.output_dir else os.path.join(args.framework_dir, "../doc_build"), args.framework_header if args.framework_header else os.path.join(args.framework_dir, "../../../lib/Release/" + args.framework_name + ".framework/Headers/" + args.framework_name + ".h"), args.framework_name, arch, target)
b.build()

View File

@ -0,0 +1,585 @@
#!/usr/bin/env python
"""
The script builds OpenCV.framework for iOS.
The built framework is universal, it can be used to build app and run it on either iOS simulator or real device.
Usage:
./build_framework.py <outputdir>
By cmake conventions (and especially if you work with OpenCV repository),
the output dir should not be a subdirectory of OpenCV source tree.
Script will create <outputdir>, if it's missing, and a few its subdirectories:
<outputdir>
build/
iPhoneOS-*/
[cmake-generated build tree for an iOS device target]
iPhoneSimulator-*/
[cmake-generated build tree for iOS simulator]
{framework_name}.framework/
[the framework content]
samples/
[sample projects]
docs/
[documentation]
The script should handle minor OpenCV updates efficiently
- it does not recompile the library from scratch each time.
However, {framework_name}.framework directory is erased and recreated on each run.
Adding --dynamic parameter will build {framework_name}.framework as App Store dynamic framework. Only iOS 8+ versions are supported.
"""
from __future__ import print_function, unicode_literals
import glob, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing, codecs, io
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, get_xcode_version, get_cmake_version
IPHONEOS_DEPLOYMENT_TARGET='9.0' # default, can be changed via command line options or environment variable
class Builder:
def __init__(self, opencv, contrib, dynamic, bitcodedisabled, exclude, disable, enablenonfree, targets, debug, debug_info, framework_name, run_tests, build_docs, swiftdisabled):
self.opencv = os.path.abspath(opencv)
self.contrib = None
if contrib:
modpath = os.path.join(contrib, "modules")
if os.path.isdir(modpath):
self.contrib = os.path.abspath(modpath)
else:
print("Note: contrib repository is bad - modules subfolder not found", file=sys.stderr)
self.dynamic = dynamic
self.bitcodedisabled = bitcodedisabled
self.exclude = exclude
self.build_objc_wrapper = not "objc" in self.exclude
self.disable = disable
self.enablenonfree = enablenonfree
self.targets = targets
self.debug = debug
self.debug_info = debug_info
self.framework_name = framework_name
self.run_tests = run_tests
self.build_docs = build_docs
self.swiftdisabled = swiftdisabled
def checkCMakeVersion(self):
if get_xcode_version() >= (12, 2):
assert get_cmake_version() >= (3, 19), "CMake 3.19 or later is required when building with Xcode 12.2 or greater. Current version is {}".format(get_cmake_version())
else:
assert get_cmake_version() >= (3, 17), "CMake 3.17 or later is required. Current version is {}".format(get_cmake_version())
def getBuildDir(self, parent, target):
res = os.path.join(parent, 'build-%s-%s' % (target[0].lower(), target[1].lower()))
if not os.path.isdir(res):
os.makedirs(res)
return os.path.abspath(res)
def _build(self, outdir):
self.checkCMakeVersion()
outdir = os.path.abspath(outdir)
if not os.path.isdir(outdir):
os.makedirs(outdir)
main_working_dir = os.path.join(outdir, "build")
dirs = []
xcode_ver = get_xcode_major()
# build each architecture separately
alltargets = []
for target_group in self.targets:
for arch in target_group[0]:
current = ( arch, target_group[1] )
alltargets.append(current)
for target in alltargets:
main_build_dir = self.getBuildDir(main_working_dir, target)
dirs.append(main_build_dir)
cmake_flags = []
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:
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 cannot 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:
self.mergeLibs(main_build_dir)
else:
self.makeDynamicLib(main_build_dir)
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(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(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")
if os.path.exists(doc_path):
shutil.copytree(doc_path, os.path.join(outdir, "docs"))
shutil.copyfile(os.path.join(self.opencv, "doc", "opencv.ico"), os.path.join(outdir, "docs", "favicon.ico"))
else:
print("To build docs call:")
print(sys.argv[0].replace("build_framework", "build_docs") + " " + dirs[0] + "/modules/objc/framework_build")
self.copy_samples(outdir)
if self.swiftdisabled:
swift_sources_dir = os.path.join(outdir, "SwiftSources")
if not os.path.exists(swift_sources_dir):
os.makedirs(swift_sources_dir)
for root, dirs, files in os.walk(dirs[0]):
for file in files:
if file.endswith(".swift") and file.find("Test") == -1:
with io.open(os.path.join(root, file), encoding="utf-8", errors="ignore") as file_in:
body = file_in.read()
if body.find("import Foundation") != -1:
insert_pos = body.find("import Foundation") + len("import Foundation") + 1
body = body[:insert_pos] + "import " + self.framework_name + "\n" + body[insert_pos:]
else:
body = "import " + self.framework_name + "\n\n" + body
with codecs.open(os.path.join(swift_sources_dir, file), "w", "utf-8") as file_out:
file_out.write(body)
def build(self, outdir):
try:
self._build(outdir)
except Exception as e:
print_error(e)
traceback.print_exc(file=sys.stderr)
sys.exit(1)
def getToolchain(self, arch, target):
return None
def getConfiguration(self):
return "Debug" if self.debug else "Release"
def getCMakeArgs(self, arch, target):
args = [
"cmake",
"-GXcode",
"-DAPPLE_FRAMEWORK=ON",
"-DCMAKE_INSTALL_PREFIX=install",
"-DCMAKE_BUILD_TYPE=%s" % self.getConfiguration(),
"-DOPENCV_INCLUDE_INSTALL_PATH=include",
"-DOPENCV_3P_LIB_INSTALL_PATH=lib/3rdparty",
"-DFRAMEWORK_NAME=%s" % self.framework_name,
]
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]
if len(self.disable) > 0:
args += ["-DWITH_%s=OFF" % f for f in self.disable]
return args
def getBuildCommand(self, arch, target):
buildcmd = [
"xcodebuild",
]
if (self.dynamic or self.build_objc_wrapper) and not self.bitcodedisabled and target == "iPhoneOS":
buildcmd.append("BITCODE_GENERATION_MODE=bitcode")
buildcmd += [
"IPHONEOS_DEPLOYMENT_TARGET=" + os.environ['IPHONEOS_DEPLOYMENT_TARGET'],
"ARCHS=%s" % arch,
"-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, target):
# Obj-C generation target
return 'ios'
def makeCMakeCmd(self, arch, target, dir, cmakeargs = []):
toolchain = self.getToolchain(arch, target)
cmakecmd = self.getCMakeArgs(arch, target) + \
(["-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain] if toolchain is not None else [])
if target.lower().startswith("iphoneos"):
cmakecmd.append("-DCPU_BASELINE=DETECT")
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")
cmakecmd.append("-DCMAKE_CROSSCOMPILING=ON")
cmakecmd.append("-DOPENCV_WORKAROUND_CMAKE_20989=ON")
cmakecmd.append(dir)
cmakecmd.extend(cmakeargs)
return cmakecmd
def buildOne(self, arch, target, builddir, cmakeargs = []):
# Run cmake
#toolchain = self.getToolchain(arch, target)
#cmakecmd = self.getCMakeArgs(arch, target) + \
# (["-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain] if toolchain is not None else [])
#if target.lower().startswith("iphoneos"):
# cmakecmd.append("-DCPU_BASELINE=DETECT")
#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")
if os.path.isdir(clean_dir):
shutil.rmtree(clean_dir)
buildcmd = self.getBuildCommand(arch, target)
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(target)), cmakeargs)
if self.swiftdisabled:
cmakecmd.append("-DSWIFT_DISABLED=1")
cmakecmd.append("-DBUILD_ROOT=%s" % builddir)
cmakecmd.append("-DCMAKE_INSTALL_NAME_TOOL=install_name_tool")
cmakecmd.append("--no-warn-unused-cli")
execute(cmakecmd, cwd = builddir + "/modules/objc/framework_build")
execute(buildcmd + ["-target", "ALL_BUILD", "build"], cwd = builddir + "/modules/objc/framework_build")
execute(["cmake", "-DBUILD_TYPE=%s" % self.getConfiguration(), "-DCMAKE_INSTALL_PREFIX=%s" % (builddir + "/install"), "-P", "cmake_install.cmake"], cwd = builddir + "/modules/objc/framework_build")
def mergeLibs(self, builddir):
res = os.path.join(builddir, "lib", self.getConfiguration(), "libopencv_merged.a")
libs = glob.glob(os.path.join(builddir, "install", "lib", "*.a"))
module = [os.path.join(builddir, "install", "lib", self.framework_name + ".framework", self.framework_name)] if self.build_objc_wrapper else []
libs3 = glob.glob(os.path.join(builddir, "install", "lib", "3rdparty", "*.a"))
print("Merging libraries:\n\t%s" % "\n\t".join(libs + libs3 + module), file=sys.stderr)
execute(["libtool", "-static", "-o", res] + libs + libs3 + module)
def makeDynamicLib(self, builddir):
target = builddir[(builddir.rfind("build-") + 6):]
target_platform = target[(target.rfind("-") + 1):]
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"))
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"))
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 = 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"]
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,] +
framework_options + [
"-install_name", "@rpath/" + self.framework_name + ".framework/" + self.framework_name,
"-dynamiclib", "-dead_strip", "-fobjc-link-runtime", "-all_load",
"-o", res
] + swift_link_dirs + bitcode_flags + module + libs + libs3)
def makeFramework(self, outdir, builddirs):
name = self.framework_name
# set the current dir to the dst root
framework_dir = os.path.join(outdir, "%s.framework" % name)
if os.path.isdir(framework_dir):
shutil.rmtree(framework_dir)
os.makedirs(framework_dir)
if self.dynamic:
dstdir = framework_dir
else:
dstdir = os.path.join(framework_dir, "Versions", "A")
# copy headers from one of build folders
shutil.copytree(os.path.join(builddirs[0], "install", "include", "opencv2"), os.path.join(dstdir, "Headers"))
if name != "opencv2":
for dirname, dirs, files in os.walk(os.path.join(dstdir, "Headers")):
for filename in files:
filepath = os.path.join(dirname, filename)
with open(filepath) as file:
body = file.read()
body = body.replace("include \"opencv2/", "include \"" + name + "/")
body = body.replace("include <opencv2/", "include <" + name + "/")
with open(filepath, "w") as file:
file.write(body)
if self.build_objc_wrapper:
copy_tree(os.path.join(builddirs[0], "install", "lib", name + ".framework", "Headers"), os.path.join(dstdir, "Headers"))
platform_name_map = {
"arm": "armv7-apple-ios",
"arm64": "arm64-apple-ios",
"i386": "i386-apple-ios-simulator",
"x86_64": "x86_64-apple-ios-simulator",
} if builddirs[0].find("iphone") != -1 else {
"x86_64": "x86_64-apple-macos",
"arm64": "arm64-apple-macos",
}
for d in builddirs:
copy_tree(os.path.join(d, "install", "lib", name + ".framework", "Modules"), os.path.join(dstdir, "Modules"))
for dirname, dirs, files in os.walk(os.path.join(dstdir, "Modules")):
for filename in files:
filestem = os.path.splitext(filename)[0]
fileext = os.path.splitext(filename)[1]
if filestem in platform_name_map:
os.rename(os.path.join(dirname, filename), os.path.join(dirname, platform_name_map[filestem] + fileext))
# make universal static lib
if self.dynamic:
libs = [os.path.join(d, "install", "lib", name + ".framework", name) for d in builddirs]
else:
libs = [os.path.join(d, "lib", self.getConfiguration(), "libopencv_merged.a") for d in builddirs]
lipocmd = ["lipo", "-create"]
lipocmd.extend(libs)
lipocmd.extend(["-o", os.path.join(dstdir, name)])
print("Creating universal library from:\n\t%s" % "\n\t".join(libs), file=sys.stderr)
execute(lipocmd)
# dynamic framework has different structure, just copy the Plist directly
if self.dynamic:
resdir = dstdir
shutil.copyfile(self.getInfoPlist(builddirs), os.path.join(resdir, "Info.plist"))
else:
# copy Info.plist
resdir = os.path.join(dstdir, "Resources")
os.makedirs(resdir)
shutil.copyfile(self.getInfoPlist(builddirs), os.path.join(resdir, "Info.plist"))
# make symbolic links
links = [
(["A"], ["Versions", "Current"]),
(["Versions", "Current", "Headers"], ["Headers"]),
(["Versions", "Current", "Resources"], ["Resources"]),
(["Versions", "Current", "Modules"], ["Modules"]),
(["Versions", "Current", name], [name])
]
for l in links:
s = os.path.join(*l[0])
d = os.path.join(framework_dir, *l[1])
os.symlink(s, d)
def copy_samples(self, outdir):
return
class iOSBuilder(Builder):
def getToolchain(self, arch, target):
toolchain = os.path.join(self.opencv, "platforms", "ios", "cmake", "Toolchains", "Toolchain-%s_Xcode.cmake" % target)
return toolchain
def getCMakeArgs(self, arch, target):
args = Builder.getCMakeArgs(self, arch, target)
args = args + [
'-DIOS_ARCH=%s' % arch
]
return args
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):
for filename in files:
if not filename.endswith((".h", ".swift", ".pbxproj")):
continue
filepath = os.path.join(dirname, filename)
with open(filepath) as file:
body = file.read()
body = body.replace("import OpenCV", "import " + self.framework_name)
body = body.replace("#import <OpenCV/OpenCV.h>", "#import <" + self.framework_name + "/" + self.framework_name + ".h>")
body = body.replace("OpenCV.framework", self.framework_name + ".framework")
body = body.replace("../../OpenCV/**", "../../" + self.framework_name + "/**")
with open(filepath, "w") as file:
file.write(body)
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. 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')
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)')
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 opencv2 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')
parser.add_argument('--disable-swift', default=False, dest='swiftdisabled', action='store_true', help='Disable building of Swift extensions')
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 = 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 = 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")
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, args.swiftdisabled)
b.build(args.out)

View File

@ -0,0 +1,174 @@
# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
# files which are included with CMake 2.8.4
# It has been altered for iOS development
set (UNIX 1)
set (APPLE 1)
set (IOS 1)
# Darwin versions:
# 6.x == Mac OSX 10.2
# 7.x == Mac OSX 10.3
# 8.x == Mac OSX 10.4
# 9.x == Mac OSX 10.5
# 10.x == Mac OSX 10.6 (Snow Leopard)
string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_SYSTEM_VERSION}")
string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\2" DARWIN_MINOR_VERSION "${CMAKE_SYSTEM_VERSION}")
# Do not use the "-Wl,-search_paths_first" flag with the OSX 10.2 compiler.
# Done this way because it is too early to do a TRY_COMPILE.
if (NOT DEFINED HAVE_FLAG_SEARCH_PATHS_FIRST)
set (HAVE_FLAG_SEARCH_PATHS_FIRST 0)
if ("${DARWIN_MAJOR_VERSION}" GREATER 6)
set (HAVE_FLAG_SEARCH_PATHS_FIRST 1)
endif ("${DARWIN_MAJOR_VERSION}" GREATER 6)
endif (NOT DEFINED HAVE_FLAG_SEARCH_PATHS_FIRST)
# More desirable, but does not work:
#INCLUDE(CheckCXXCompilerFlag)
#CHECK_CXX_COMPILER_FLAG("-Wl,-search_paths_first" HAVE_FLAG_SEARCH_PATHS_FIRST)
set (CMAKE_SHARED_LIBRARY_PREFIX "lib")
set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
set (CMAKE_SHARED_MODULE_PREFIX "lib")
set (CMAKE_SHARED_MODULE_SUFFIX ".so")
set (CMAKE_MODULE_EXISTS 1)
set (CMAKE_DL_LIBS "")
set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
# Additional flags for dynamic framework
if (APPLE_FRAMEWORK AND BUILD_SHARED_LIBS)
set (CMAKE_MODULE_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks")
set (CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks")
set (CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG 1)
set (CMAKE_INSTALL_NAME_DIR "@rpath")
endif()
# Hidden visibility is required for cxx on iOS
set (no_warn "-Wno-unused-function -Wno-overloaded-virtual")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${no_warn}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fvisibility=hidden -fvisibility-inlines-hidden ${no_warn}")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -ffast-math")
if(NOT IOS_ARCH STREQUAL "armv7" AND NOT IOS_ARCH STREQUAL "armv7s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer")
endif()
if (HAVE_FLAG_SEARCH_PATHS_FIRST)
set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
endif (HAVE_FLAG_SEARCH_PATHS_FIRST)
set (CMAKE_PLATFORM_HAS_INSTALLNAME 1)
set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
# Setup iOS developer location
if (IPHONEOS)
set (_CMAKE_IOS_DEVELOPER_ROOT "/Developer/Platforms/iPhoneOS.platform/Developer")
else ()
if (IPHONESIMULATOR)
set (_CMAKE_IOS_DEVELOPER_ROOT "/Developer/Platforms/iPhoneSimulator.platform/Developer")
endif ()
endif ()
# Find installed iOS SDKs
file (GLOB _CMAKE_IOS_SDKS "${_CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
# Find and use the most recent iOS sdk
if (_CMAKE_IOS_SDKS)
list (SORT _CMAKE_IOS_SDKS)
list (REVERSE _CMAKE_IOS_SDKS)
list (GET _CMAKE_IOS_SDKS 0 _CMAKE_IOS_SDK_ROOT)
# Set the sysroot default to the most recent SDK
set (CMAKE_OSX_SYSROOT ${_CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
# set the architecture for iOS - this env var sets armv6,armv7 and appears to be XCode's standard. The other found is ARCHS_UNIVERSAL_IPHONE_OS but that is armv7 only
set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)" CACHE string "Build architecture for iOS")
# Set the default based on this file and not the environment variable
set (CMAKE_FIND_ROOT_PATH ${_CMAKE_IOS_DEVELOPER_ROOT} ${_CMAKE_IOS_SDK_ROOT} CACHE string "iOS library search path root")
# default to searching for frameworks first
set (CMAKE_FIND_FRAMEWORK FIRST)
# set up the default search directories for frameworks
set (CMAKE_SYSTEM_FRAMEWORK_PATH
${_CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
${_CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
${_CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
)
endif (_CMAKE_IOS_SDKS)
if ("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress")
endif ("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
if (NOT XCODE)
# Enable shared library versioning. This flag is not actually referenced
# but the fact that the setting exists will cause the generators to support
# soname computation.
set (CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name")
endif (NOT XCODE)
# Xcode does not support -isystem yet.
if (XCODE)
set (CMAKE_INCLUDE_SYSTEM_FLAG_C)
set (CMAKE_INCLUDE_SYSTEM_FLAG_CXX)
endif (XCODE)
# Need to list dependent shared libraries on link line. When building
# with -isysroot (for universal binaries), the linker always looks for
# dependent libraries under the sysroot. Listing them on the link
# line works around the problem.
set (CMAKE_LINK_DEPENDENT_LIBRARY_FILES 1)
set (CMAKE_C_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w)
set (CMAKE_CXX_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w)
set (CMAKE_C_CREATE_SHARED_LIBRARY
"<CMAKE_C_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
set (CMAKE_CXX_CREATE_SHARED_LIBRARY
"<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
set (CMAKE_CXX_CREATE_SHARED_MODULE
"<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
set (CMAKE_C_CREATE_SHARED_MODULE
"<CMAKE_C_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_MODULE_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
set (CMAKE_C_CREATE_MACOSX_FRAMEWORK
"<CMAKE_C_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
set (CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
"<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
# Add the install directory of the running cmake to the search directories
# CMAKE_ROOT is CMAKE_INSTALL_PREFIX/share/cmake, so we need to go two levels up
get_filename_component (_CMAKE_INSTALL_DIR "${CMAKE_ROOT}" PATH)
get_filename_component (_CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" PATH)
# List common installation prefixes. These will be used for all search types
list (APPEND CMAKE_SYSTEM_PREFIX_PATH
# Standard
${_CMAKE_IOS_DEVELOPER_ROOT}/usr
${_CMAKE_IOS_SDK_ROOT}/usr
# CMake install location
"${_CMAKE_INSTALL_DIR}"
# Project install destination.
"${CMAKE_INSTALL_PREFIX}"
)

View File

@ -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")

View File

@ -0,0 +1,4 @@
message(STATUS "Setting up iPhoneOS toolchain for IOS_ARCH='${IOS_ARCH}'")
set(IPHONEOS TRUE)
include(${CMAKE_CURRENT_LIST_DIR}/common-ios-toolchain.cmake)
message(STATUS "iPhoneOS toolchain loaded")

View File

@ -0,0 +1,4 @@
message(STATUS "Setting up iPhoneSimulator toolchain for IOS_ARCH='${IOS_ARCH}'")
set(IPHONESIMULATOR TRUE)
include(${CMAKE_CURRENT_LIST_DIR}/common-ios-toolchain.cmake)
message(STATUS "iPhoneSimulator toolchain loaded")

View File

@ -0,0 +1,182 @@
# load settings in case of "try compile"
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
get_property(__IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if(__IN_TRY_COMPILE)
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake")
if(NOT EXISTS "${TOOLCHAIN_CONFIG_FILE}")
# Hack for "try_compile" commands with other binary directory
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_PLATFORM_INFO_DIR}/../toolchain.config.cmake")
if(NOT EXISTS "${TOOLCHAIN_CONFIG_FILE}")
message(FATAL_ERROR "Current CMake version (${CMAKE_VERSION}) is not supported")
endif()
endif()
include("${TOOLCHAIN_CONFIG_FILE}")
macro(toolchain_save_config)
# nothing
endmacro()
else()
macro(toolchain_save_config)
set(__config "#message(\"Load TOOLCHAIN config...\")\n")
get_cmake_property(__variableNames VARIABLES)
set(__vars_list ${ARGN})
list(APPEND __vars_list
${TOOLCHAIN_CONFIG_VARS}
CMAKE_SYSTEM_NAME
CMAKE_SYSTEM_VERSION
CMAKE_SYSTEM_PROCESSOR
CMAKE_C_COMPILER
CMAKE_CXX_COMPILER
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS
CMAKE_SKIP_RPATH
CMAKE_FIND_ROOT_PATH
)
foreach(__var ${__variableNames})
foreach(_v ${__vars_list})
if("x${__var}" STREQUAL "x${_v}")
if(${__var} MATCHES " ")
set(__config "${__config}set(${__var} \"${${__var}}\")\n")
else()
set(__config "${__config}set(${__var} ${${__var}})\n")
endif()
endif()
endforeach()
endforeach()
if(EXISTS "${TOOLCHAIN_CONFIG_FILE}")
file(READ "${TOOLCHAIN_CONFIG_FILE}" __config_old)
endif()
if("${__config_old}" STREQUAL "${__config}")
# nothing
else()
#message("Update TOOLCHAIN config: ${__config}")
file(WRITE "${TOOLCHAIN_CONFIG_FILE}" "${__config}")
endif()
unset(__config)
unset(__config_old)
unset(__vars_list)
unset(__variableNames)
endmacro()
endif() # IN_TRY_COMPILE
if(NOT DEFINED IOS_ARCH)
message(FATAL_ERROR "iOS toolchain requires ARCH option for proper configuration of compiler flags")
endif()
if(IOS_ARCH MATCHES "^arm64")
set(AARCH64 1)
elseif(IOS_ARCH MATCHES "^armv")
set(ARM 1)
elseif(IOS_ARCH MATCHES "^x86_64")
set(X86_64 1)
elseif(IOS_ARCH MATCHES "^i386")
set(X86 1)
else()
message(FATAL_ERROR "iOS toolchain doesn't recognize ARCH='${IOS_ARCH}' value")
endif()
if(NOT DEFINED CMAKE_OSX_SYSROOT)
if(IPHONEOS)
set(CMAKE_OSX_SYSROOT "iphoneos")
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)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
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 AND NOT MAC_CATALYST)
if(NOT DEFINED ENV{IPHONEOS_DEPLOYMENT_TARGET})
message(FATAL_ERROR "IPHONEOS_DEPLOYMENT_TARGET is not specified")
endif()
set(IPHONEOS_DEPLOYMENT_TARGET "$ENV{IPHONEOS_DEPLOYMENT_TARGET}")
endif()
if(NOT __IN_TRY_COMPILE)
set(_xcodebuild_wrapper "${CMAKE_BINARY_DIR}/xcodebuild_wrapper")
if(NOT EXISTS "${_xcodebuild_wrapper}")
set(_xcodebuild_wrapper_tmp "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/xcodebuild_wrapper")
if(NOT DEFINED CMAKE_MAKE_PROGRAM) # empty since CMake 3.10
find_program(XCODEBUILD_PATH "xcodebuild")
if(NOT XCODEBUILD_PATH)
message(FATAL_ERROR "Specify CMAKE_MAKE_PROGRAM variable ('xcodebuild' absolute path)")
endif()
set(CMAKE_MAKE_PROGRAM "${XCODEBUILD_PATH}")
endif()
if(CMAKE_MAKE_PROGRAM STREQUAL _xcodebuild_wrapper)
message(FATAL_ERROR "Can't prepare xcodebuild_wrapper")
endif()
if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS)
set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO -sdk ${CMAKE_OSX_SYSROOT}")
else()
set(XCODEBUILD_EXTRA_ARGS "${XCODEBUILD_EXTRA_ARGS} IPHONEOS_DEPLOYMENT_TARGET=${IPHONEOS_DEPLOYMENT_TARGET} CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO ARCHS=${IOS_ARCH} -sdk ${CMAKE_OSX_SYSROOT}")
endif()
configure_file("${CMAKE_CURRENT_LIST_DIR}/xcodebuild_wrapper.in" "${_xcodebuild_wrapper_tmp}" @ONLY)
file(COPY "${_xcodebuild_wrapper_tmp}" DESTINATION ${CMAKE_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif()
set(CMAKE_MAKE_PROGRAM "${_xcodebuild_wrapper}" CACHE INTERNAL "" FORCE)
endif()
# Standard settings
set(CMAKE_SYSTEM_NAME iOS)
# Apple Framework settings
if(APPLE_FRAMEWORK AND BUILD_SHARED_LIBS)
set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}")
set(CMAKE_C_SIZEOF_DATA_PTR 4)
set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
else()
set(CMAKE_SYSTEM_VERSION "${IPHONEOS_DEPLOYMENT_TARGET}")
set(CMAKE_SYSTEM_PROCESSOR "${IOS_ARCH}")
if(AARCH64 OR X86_64)
set(CMAKE_C_SIZEOF_DATA_PTR 8)
set(CMAKE_CXX_SIZEOF_DATA_PTR 8)
else()
set(CMAKE_C_SIZEOF_DATA_PTR 4)
set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
endif()
endif()
# Include extra modules for the iOS platform files
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/cmake/Modules")
# Force the compilers to clang for iOS
include(CMakeForceCompiler)
#CMAKE_FORCE_C_COMPILER (clang GNU)
#CMAKE_FORCE_CXX_COMPILER (clang++ GNU)
set(CMAKE_C_HAS_ISYSROOT 1)
set(CMAKE_CXX_HAS_ISYSROOT 1)
set(CMAKE_C_COMPILER_ABI ELF)
set(CMAKE_CXX_COMPILER_ABI ELF)
# Skip the platform compiler checks for cross compiling
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_C_COMPILER_WORKS TRUE)
if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
endif()
toolchain_save_config(IOS_ARCH IPHONEOS_DEPLOYMENT_TARGET)

View File

@ -0,0 +1,19 @@
#!/bin/sh
# Force 'Debug' configuration
# Details: https://github.com/opencv/opencv/issues/13856
if [[ "$@" =~ "-project CMAKE_TRY_COMPILE.xcodeproj" && -z "${OPENCV_SKIP_XCODEBUILD_FORCE_TRYCOMPILE_DEBUG}" ]]; then
ARGS=()
for ((i=1; i<=$#; i++))
do
arg=${!i}
ARGS+=("$arg")
if [[ "$arg" == "-configuration" ]]; then
ARGS+=("Debug")
i=$(($i+1))
fi
done
set -- "${ARGS[@]}"
fi
@CMAKE_MAKE_PROGRAM@ @XCODEBUILD_EXTRA_ARGS@ $*

View File

@ -0,0 +1,7 @@
Building OpenCV from Source, using CMake and Command Line
=========================================================
cd ~/<my_working_directory>
python opencv/platforms/ios/build_framework.py ios
If everything's fine, a few minutes later you will get ~/<my_working_directory>/ios/opencv2.framework. You can add this framework to your Xcode projects.

View File

@ -0,0 +1,114 @@
#!/usr/bin/env python
"""
This script runs OpenCV.framework tests for iOS.
"""
from __future__ import print_function
import glob, re, os, os.path, shutil, string, sys, argparse, traceback, multiprocessing
from subprocess import check_call, check_output, CalledProcessError
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)
class TestRunner:
def __init__(self, script_dir, tests_dir, build_dir, framework_dir, framework_name, arch, target, platform):
self.script_dir = script_dir
self.tests_dir = tests_dir
self.build_dir = build_dir
self.framework_dir = framework_dir
self.framework_name = framework_name
self.arch = arch
self.target = target
self.platform = platform
def _run(self):
if not os.path.isdir(self.build_dir):
os.makedirs(self.build_dir)
self.runTest()
def run(self):
try:
self._run()
except Exception as e:
print("="*60, file=sys.stderr)
print("ERROR: %s" % e, file=sys.stderr)
print("="*60, file=sys.stderr)
traceback.print_exc(file=sys.stderr)
sys.exit(1)
def getToolchain(self):
return None
def getCMakeArgs(self):
args = [
"cmake",
"-GXcode",
"-DFRAMEWORK_DIR=%s" % self.framework_dir,
"-DFRAMEWORK_NAME=%s" % self.framework_name,
]
return args
def makeCMakeCmd(self):
toolchain = self.getToolchain()
cmakecmd = self.getCMakeArgs() + \
(["-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain] if toolchain is not None else []) + \
["-DCMAKE_INSTALL_NAME_TOOL=install_name_tool"]
cmakecmd.append(self.tests_dir)
return cmakecmd
def runTest(self):
cmakecmd = self.makeCMakeCmd()
execute(cmakecmd, cwd = self.build_dir)
buildcmd = self.getTestCommand()
execute(buildcmd, cwd = self.build_dir)
def getTestCommand(self):
testcmd = [
"xcodebuild",
"test",
"-project", "OpenCVTest.xcodeproj",
"-scheme", "OpenCVTestTests",
"-destination", "platform=%s" % self.platform
]
return testcmd
class iOSTestRunner(TestRunner):
def getToolchain(self):
toolchain = os.path.join(self.script_dir, "cmake", "Toolchains", "Toolchain-%s_Xcode.cmake" % self.target)
return toolchain
def getCMakeArgs(self):
args = TestRunner.getCMakeArgs(self)
args = args + [
"-DIOS_ARCH=%s" % self.arch,
"-DIPHONEOS_DEPLOYMENT_TARGET=%s" % os.environ['IPHONEOS_DEPLOYMENT_TARGET'],
]
return args
if __name__ == "__main__":
script_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
parser = argparse.ArgumentParser(description='The script builds OpenCV.framework for iOS.')
parser.add_argument('tests_dir', metavar='TEST_DIR', help='folder where test files are located')
parser.add_argument('--build_dir', default=None, help='folder where test will be built (default is "../test_build" relative to tests_dir)')
parser.add_argument('--framework_dir', default=None, help='folder where OpenCV framework is located')
parser.add_argument('--framework_name', default='opencv2', help='Name of OpenCV framework (default: opencv2, will change to OpenCV in future version)')
parser.add_argument('--iphoneos_deployment_target', default=os.environ.get('IPHONEOS_DEPLOYMENT_TARGET', IPHONEOS_DEPLOYMENT_TARGET), help='specify IPHONEOS_DEPLOYMENT_TARGET')
parser.add_argument('--platform', default='iOS Simulator,name=iPhone 11', help='xcodebuild platform parameter (default is iOS 11 simulator)')
args = parser.parse_args()
os.environ['IPHONEOS_DEPLOYMENT_TARGET'] = args.iphoneos_deployment_target
print('Using IPHONEOS_DEPLOYMENT_TARGET=' + os.environ['IPHONEOS_DEPLOYMENT_TARGET'])
arch = "x86_64"
target = "iPhoneSimulator"
print('Using iPhoneSimulator ARCH=' + arch)
r = iOSTestRunner(script_dir, args.tests_dir, args.build_dir if args.build_dir else os.path.join(args.tests_dir, "../test_build"), args.framework_dir, args.framework_name, arch, target, args.platform)
r.run()