Last active
April 22, 2021 09:51
-
-
Save atinfinity/ccf4fc657c7def583b8e to your computer and use it in GitHub Desktop.
opencv2.framework with opencv_contrib for OpenCV 3.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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] | |
opencv2.framework/ | |
[the framework content] | |
The script should handle minor OpenCV updates efficiently | |
- it does not recompile the library from scratch each time. | |
However, opencv2.framework directory is erased and recreated on each run. | |
""" | |
import glob, re, os, os.path, shutil, string, sys, exceptions, subprocess, argparse | |
opencv_contrib_path = None | |
def execute(cmd): | |
try: | |
print >>sys.stderr, "Executing:", cmd | |
retcode = subprocess.call(cmd, shell=True) | |
if retcode < 0: | |
raise Exception("Child was terminated by signal:", -retcode) | |
elif retcode > 0: | |
raise Exception("Child returned:", retcode) | |
except OSError as e: | |
raise Exception("Execution failed:", e) | |
def build_opencv(srcroot, buildroot, target, arch): | |
"builds OpenCV for device or simulator" | |
builddir = os.path.join(buildroot, target + '-' + arch) | |
if not os.path.isdir(builddir): | |
os.makedirs(builddir) | |
currdir = os.getcwd() | |
os.chdir(builddir) | |
# for some reason, if you do not specify CMAKE_BUILD_TYPE, it puts libs to "RELEASE" rather than "Release" | |
cmakeargs = ("-GXcode " + | |
"-DCMAKE_BUILD_TYPE=Release " + | |
"-DCMAKE_TOOLCHAIN_FILE=%s/platforms/ios/cmake/Toolchains/Toolchain-%s_Xcode.cmake " + | |
"-DCMAKE_C_FLAGS=\"-Wno-implicit-function-declaration\" " + | |
"-DCMAKE_INSTALL_PREFIX=install") % (srcroot, target) | |
if arch.startswith("armv"): | |
cmakeargs += " -DENABLE_NEON=ON" | |
if opencv_contrib_path is not None: | |
cmakeargs += " -DOPENCV_EXTRA_MODULES_PATH=%s -DBUILD_opencv_world=ON" % opencv_contrib_path | |
build_target = "ALL_BUILD" | |
libname = "libopencv_world.a" | |
else: | |
cmakeargs += " -DBUILD_opencv_world=ON" | |
build_target = "ALL_BUILD" | |
libname = "libopencv_world.a" | |
# if cmake cache exists, just rerun cmake to update OpenCV.xcodeproj if necessary | |
if os.path.isfile(os.path.join(builddir, "CMakeCache.txt")): | |
execute("cmake %s ." % (cmakeargs,)) | |
else: | |
execute("cmake %s %s" % (cmakeargs, srcroot)) | |
for wlib in [builddir + "/modules/world/UninstalledProducts/" + libname, | |
builddir + "/lib/Release/" + libname]: | |
if os.path.isfile(wlib): | |
os.remove(wlib) | |
execute("xcodebuild IPHONEOS_DEPLOYMENT_TARGET=6.0 -parallelizeTargets ARCHS=%s -jobs 8 -sdk %s -configuration Release -target %s" % (arch, target.lower(), build_target)) | |
execute("xcodebuild IPHONEOS_DEPLOYMENT_TARGET=6.0 ARCHS=%s -sdk %s -configuration Release -target install install" % (arch, target.lower())) | |
os.chdir(currdir) | |
def put_framework_together(srcroot, dstroot): | |
"constructs the framework directory after all the targets are built" | |
name = "opencv2" | |
libname = "libopencv_world.a" | |
# find the list of targets (basically, ["iPhoneOS", "iPhoneSimulator"]) | |
targetlist = glob.glob(os.path.join(dstroot, "build", "*")) | |
targetlist = [os.path.basename(t) for t in targetlist] | |
# set the current dir to the dst root | |
currdir = os.getcwd() | |
framework_dir = dstroot + "/%s.framework" % name | |
if os.path.isdir(framework_dir): | |
shutil.rmtree(framework_dir) | |
os.makedirs(framework_dir) | |
os.chdir(framework_dir) | |
# form the directory tree | |
dstdir = "Versions/A" | |
os.makedirs(dstdir + "/Resources") | |
tdir0 = "../build/" + targetlist[0] | |
# copy headers | |
shutil.copytree(tdir0 + "/install/include/opencv2", dstdir + "/Headers") | |
# make universal static lib | |
wlist = " ".join(["../build/" + t + "/lib/Release/" + libname for t in targetlist]) | |
execute("lipo -create " + wlist + " -o " + dstdir + "/%s" % name) | |
# copy Info.plist | |
shutil.copyfile(tdir0 + "/ios/Info.plist", dstdir + "/Resources/Info.plist") | |
# make symbolic links | |
os.symlink("A", "Versions/Current") | |
os.symlink("Versions/Current/Headers", "Headers") | |
os.symlink("Versions/Current/Resources", "Resources") | |
os.symlink("Versions/Current/%s" % name, name) | |
def build_framework(srcroot, dstroot): | |
"main function to do all the work" | |
targets = [("armv7", "iPhoneOS"), | |
("armv7s", "iPhoneOS"), | |
("arm64", "iPhoneOS"), | |
("i386", "iPhoneSimulator"), | |
("x86_64", "iPhoneSimulator")] | |
for t in targets: | |
build_opencv(srcroot, os.path.join(dstroot, "build"), t[1], t[0]) | |
put_framework_together(srcroot, dstroot) | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description='The script builds OpenCV.framework for iOS.') | |
parser.add_argument('outputdir', nargs=1, help='folder to put built framework') | |
parser.add_argument('--contrib', help="folder with opencv_contrib repository") | |
args = parser.parse_args() | |
# path to OpenCV main repository - hardcoded ../.. | |
opencv_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")) | |
print "OpenCV:", opencv_path | |
# path to OpenCV_contrib repository, can be empty - global variable | |
if hasattr(args, "contrib") and args.contrib is not None: | |
if os.path.isdir(args.contrib + "/modules"): | |
opencv_contrib_path = os.path.abspath(args.contrib + "/modules") | |
print "Contrib:", opencv_contrib_path | |
else: | |
print "Note: contrib repository is bad: modules subfolder not found" | |
# result path - folder where framework will be located | |
output_path = os.path.abspath(args.outputdir[0]) | |
print "Output:", output_path | |
try: | |
build_framework(opencv_path, output_path) | |
except Exception as e: | |
print >>sys.stderr, e | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment