mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
update osx and ios build_framework.py
This commit is contained in:
Executable → Regular
+58
-42
@@ -43,7 +43,7 @@ def getXCodeMajor():
|
||||
return 0
|
||||
|
||||
class Builder:
|
||||
def __init__(self, opencv, contrib):
|
||||
def __init__(self, opencv, contrib, targets):
|
||||
self.opencv = os.path.abspath(opencv)
|
||||
self.contrib = None
|
||||
if contrib:
|
||||
@@ -52,13 +52,7 @@ class Builder:
|
||||
self.contrib = os.path.abspath(modpath)
|
||||
else:
|
||||
print("Note: contrib repository is bad - modules subfolder not found", file=sys.stderr)
|
||||
self.targets = [
|
||||
("armv7", "iPhoneOS"),
|
||||
("armv7s", "iPhoneOS"),
|
||||
("arm64", "iPhoneOS"),
|
||||
("i386", "iPhoneSimulator"),
|
||||
("x86_64", "iPhoneSimulator")
|
||||
]
|
||||
self.targets = targets
|
||||
|
||||
def getBD(self, parent, t):
|
||||
res = os.path.join(parent, '%s-%s' % t)
|
||||
@@ -66,7 +60,7 @@ class Builder:
|
||||
os.makedirs(res)
|
||||
return os.path.abspath(res)
|
||||
|
||||
def build(self, outdir):
|
||||
def _build(self, outdir):
|
||||
outdir = os.path.abspath(outdir)
|
||||
if not os.path.isdir(outdir):
|
||||
os.makedirs(outdir)
|
||||
@@ -81,36 +75,38 @@ class Builder:
|
||||
cmake_flags = []
|
||||
if self.contrib:
|
||||
cmake_flags.append("-DOPENCV_EXTRA_MODULES_PATH=%s" % self.contrib)
|
||||
if xcode_ver >= 7 and not "Simulator" in t[1]:
|
||||
if xcode_ver >= 7 and t[1] == 'iPhoneOS':
|
||||
cmake_flags.append("-DCMAKE_C_FLAGS=-fembed-bitcode")
|
||||
cmake_flags.append("-DCMAKE_CXX_FLAGS=-fembed-bitcode")
|
||||
self.buildOne(t[0], t[1], mainBD, cmake_flags)
|
||||
self.mergeLibs(mainBD)
|
||||
self.makeFramework(outdir, dirs)
|
||||
|
||||
def buildOne(self, arch, target, builddir, cmakeargs = []):
|
||||
# Run cmake
|
||||
def build(self, outdir):
|
||||
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)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def getToolchain(self, arch, target):
|
||||
toolchain = os.path.join(self.opencv, "platforms", "ios", "cmake", "Toolchains", "Toolchain-%s_Xcode.cmake" % target)
|
||||
cmakecmd = [
|
||||
return toolchain
|
||||
|
||||
def getCMakeArgs(self, arch, target):
|
||||
args = [
|
||||
"cmake",
|
||||
"-GXcode",
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
"-DCMAKE_TOOLCHAIN_FILE=%s" % toolchain,
|
||||
"-DAPPLE_FRAMEWORK=ON",
|
||||
"-DCMAKE_INSTALL_PREFIX=install",
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
]
|
||||
if arch.startswith("armv"):
|
||||
cmakecmd.append("-DENABLE_NEON=ON")
|
||||
cmakecmd.append(self.opencv)
|
||||
cmakecmd.extend(cmakeargs)
|
||||
execute(cmakecmd, cwd = builddir)
|
||||
# Clean and build
|
||||
cleanlist = []
|
||||
cleanlist.extend(glob.glob(os.path.join(builddir, "lib", "Release", "*.a")))
|
||||
cleanlist.extend(glob.glob(os.path.join(builddir, "modules", "*", "UninstalledProducts", "*.a")))
|
||||
print("Cleaning files:\n\t%s" % "\n\t".join(cleanlist), file=sys.stderr)
|
||||
for f in cleanlist:
|
||||
if os.path.isfile(f):
|
||||
os.remove(f)
|
||||
return args
|
||||
|
||||
def getBuildCommand(self, arch, target):
|
||||
buildcmd = [
|
||||
"xcodebuild",
|
||||
"IPHONEOS_DEPLOYMENT_TARGET=6.0",
|
||||
@@ -118,15 +114,35 @@ class Builder:
|
||||
"-sdk", target.lower(),
|
||||
"-configuration", "Release",
|
||||
"-parallelizeTargets",
|
||||
"-jobs", "8",
|
||||
"-jobs", "4"
|
||||
]
|
||||
return buildcmd
|
||||
|
||||
def getInfoPlist(self, builddirs):
|
||||
return os.path.join(builddirs[0], "ios", "Info.plist")
|
||||
|
||||
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 arch.startswith("armv"):
|
||||
cmakecmd.append("-DENABLE_NEON=ON")
|
||||
cmakecmd.append(self.opencv)
|
||||
cmakecmd.extend(cmakeargs)
|
||||
execute(cmakecmd, cwd = builddir)
|
||||
# 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(buildcmd + ["-target", "install", "install"], cwd = builddir)
|
||||
execute(["cmake", "-P", "cmake_install.cmake"], cwd = builddir)
|
||||
|
||||
def mergeLibs(self, builddir):
|
||||
res = os.path.join(builddir, "lib", "Release", "libopencv_merged.a")
|
||||
libs = glob.glob(os.path.join(builddir, "lib", "Release", "*.a"))
|
||||
libs3 = glob.glob(os.path.join(builddir, "3rdparty", "lib", "Release", "*.a"))
|
||||
libs = glob.glob(os.path.join(builddir, "install", "lib", "*.a"))
|
||||
libs3 = glob.glob(os.path.join(builddir, "install", "share", "OpenCV", "3rdparty", "lib", "*.a"))
|
||||
print("Merging libraries:\n\t%s" % "\n\t".join(libs + libs3), file=sys.stderr)
|
||||
execute(["libtool", "-static", "-o", res] + libs + libs3)
|
||||
|
||||
@@ -156,7 +172,7 @@ class Builder:
|
||||
# copy Info.plist
|
||||
resdir = os.path.join(dstdir, "Resources")
|
||||
os.makedirs(resdir)
|
||||
shutil.copyfile(os.path.join(builddirs[0], "ios", "Info.plist"), os.path.join(resdir, "Info.plist"))
|
||||
shutil.copyfile(self.getInfoPlist(builddirs), os.path.join(resdir, "Info.plist"))
|
||||
|
||||
# make symbolic links
|
||||
links = [
|
||||
@@ -178,12 +194,12 @@ if __name__ == "__main__":
|
||||
parser.add_argument('--contrib', metavar='DIR', default=None, help='folder with opencv_contrib repository (default is "None" - build only main framework)')
|
||||
args = parser.parse_args()
|
||||
|
||||
b = Builder(args.opencv, args.contrib)
|
||||
try:
|
||||
b.build(args.out)
|
||||
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)
|
||||
b = Builder(args.opencv, args.contrib,
|
||||
[
|
||||
("armv7", "iPhoneOS"),
|
||||
("armv7s", "iPhoneOS"),
|
||||
("arm64", "iPhoneOS"),
|
||||
("i386", "iPhoneSimulator"),
|
||||
("x86_64", "iPhoneSimulator"),
|
||||
])
|
||||
b.build(args.out)
|
||||
|
||||
Executable → Regular
+32
-111
@@ -1,124 +1,45 @@
|
||||
#!/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.
|
||||
The script builds OpenCV.framework for OSX.
|
||||
"""
|
||||
|
||||
import glob, re, os, os.path, shutil, string, sys
|
||||
from __future__ import print_function
|
||||
import os, os.path, sys, argparse, traceback
|
||||
|
||||
def build_opencv(srcroot, buildroot, target, arch):
|
||||
"builds OpenCV for device or simulator"
|
||||
# import common code
|
||||
sys.path.insert(0, os.path.abspath(os.path.abspath(os.path.dirname(__file__))+'/../ios'))
|
||||
from build_framework import Builder
|
||||
|
||||
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 " +
|
||||
"-DBUILD_SHARED_LIBS=OFF " +
|
||||
"-DBUILD_DOCS=OFF " +
|
||||
"-DBUILD_EXAMPLES=OFF " +
|
||||
"-DBUILD_TESTS=OFF " +
|
||||
"-DBUILD_PERF_TESTS=OFF " +
|
||||
"-DBUILD_opencv_apps=OFF " +
|
||||
"-DBUILD_opencv_world=ON " +
|
||||
"-DBUILD_opencv_matlab=OFF " +
|
||||
"-DWITH_TIFF=OFF -DBUILD_TIFF=OFF " +
|
||||
"-DWITH_JASPER=OFF -DBUILD_JASPER=OFF " +
|
||||
"-DWITH_WEBP=OFF -DBUILD_WEBP=OFF " +
|
||||
"-DWITH_OPENEXR=OFF -DBUILD_OPENEXR=OFF " +
|
||||
"-DWITH_IPP=OFF -DWITH_IPP_A=OFF " +
|
||||
"-DCMAKE_C_FLAGS=\"-Wno-implicit-function-declaration\" " +
|
||||
"-DCMAKE_INSTALL_PREFIX=install")
|
||||
# if cmake cache exists, just rerun cmake to update OpenCV.xproj if necessary
|
||||
if os.path.isfile(os.path.join(builddir, "CMakeCache.txt")):
|
||||
os.system("cmake %s ." % (cmakeargs,))
|
||||
else:
|
||||
os.system("cmake %s %s" % (cmakeargs, srcroot))
|
||||
class OSXBuilder(Builder):
|
||||
|
||||
for wlib in [builddir + "/modules/world/UninstalledProducts/libopencv_world.a",
|
||||
builddir + "/lib/Release/libopencv_world.a"]:
|
||||
if os.path.isfile(wlib):
|
||||
os.remove(wlib)
|
||||
def getToolchain(self, arch, target):
|
||||
return None
|
||||
|
||||
os.system("xcodebuild -parallelizeTargets ARCHS=%s -jobs 2 -sdk %s -configuration Release -target ALL_BUILD" % (arch, target.lower()))
|
||||
os.system("xcodebuild ARCHS=%s -sdk %s -configuration Release -target install install" % (arch, target.lower()))
|
||||
os.chdir(currdir)
|
||||
def getBuildCommand(self, arch, target):
|
||||
buildcmd = [
|
||||
"xcodebuild",
|
||||
"ARCHS=%s" % arch,
|
||||
"-sdk", target.lower(),
|
||||
"-configuration", "Release",
|
||||
"-parallelizeTargets",
|
||||
"-jobs", "4"
|
||||
]
|
||||
return buildcmd
|
||||
|
||||
def put_framework_together(srcroot, dstroot):
|
||||
"constructs the framework directory after all the targets are built"
|
||||
|
||||
# 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 + "/opencv2.framework"
|
||||
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/libopencv_world.a" for t in targetlist])
|
||||
os.system("lipo -create " + wlist + " -o " + dstdir + "/opencv2")
|
||||
|
||||
# copy Info.plist
|
||||
shutil.copyfile(tdir0 + "/osx/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/opencv2", "opencv2")
|
||||
|
||||
|
||||
def build_framework(srcroot, dstroot):
|
||||
"main function to do all the work"
|
||||
|
||||
targets = ["MacOSX", "MacOSX" ]
|
||||
archs = ["x86_64", "i386" ]
|
||||
for i in range(len(targets)):
|
||||
build_opencv(srcroot, os.path.join(dstroot, "build"), targets[i], archs[i])
|
||||
|
||||
put_framework_together(srcroot, dstroot)
|
||||
def getInfoPlist(self, builddirs):
|
||||
return os.path.join(builddirs[0], "osx", "Info.plist")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print "Usage:\n\t./build_framework.py <outputdir>\n\n"
|
||||
sys.exit(0)
|
||||
folder = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../.."))
|
||||
parser = argparse.ArgumentParser(description='The script builds OpenCV.framework for OSX.')
|
||||
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)')
|
||||
args = parser.parse_args()
|
||||
|
||||
build_framework(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")), os.path.abspath(sys.argv[1]))
|
||||
b = OSXBuilder(args.opencv, args.contrib,
|
||||
[
|
||||
("x86_64", "MacOSX")
|
||||
])
|
||||
b.build(args.out)
|
||||
|
||||
Reference in New Issue
Block a user