build_framework.py 4.53 KB
Newer Older
1 2 3 4 5 6 7
#!/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>
8 9

By cmake conventions (and especially if you work with OpenCV repository),
10
the output dir should not be a subdirectory of OpenCV source tree.
11

12
Script will create <outputdir>, if it's missing, and a few its subdirectories:
13

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
    <outputdir>
        build/
            iPhoneOS/
               [cmake-generated build tree for an iOS device target]
            iPhoneSimulator/
               [cmake-generated build tree for iOS simulator]
        OpenCV.framework/
            [the framework content]

The script should handle minor OpenCV updates efficiently
- it does not recompile the library from scratch each time.
However, OpenCV.framework directory is erased and recreated on each run.
"""

import glob, re, os, os.path, shutil, string, sys

def build_opencv(srcroot, buildroot, target):
    "builds OpenCV for device or simulator"
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    builddir = os.path.join(buildroot, target)
    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/ios/cmake/Toolchains/Toolchain-%s_Xcode.cmake " +
                "-DBUILD_opencv_world=ON " +
                "-DCMAKE_INSTALL_PREFIX=install") % (srcroot, target)
    # 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))
49

50 51 52 53
    for wlib in [builddir + "/modules/world/UninstalledProducts/libopencv_world.a",
                 builddir + "/lib/Release/libopencv_world.a"]:
        if os.path.isfile(wlib):
            os.remove(wlib)
54

55 56 57
    os.system("xcodebuild -parallelizeTargets -jobs 8 -sdk %s -configuration Release -target ALL_BUILD" % target.lower())
    os.system("xcodebuild -sdk %s -configuration Release -target install install" % target.lower())
    os.chdir(currdir)
58

59 60
def put_framework_together(srcroot, dstroot):
    "constructs the framework directory after all the targets are built"
61

62 63 64
    # 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]
65

66 67 68 69 70 71 72
    # 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)
73

74 75 76 77 78 79 80 81
    # determine OpenCV version (without subminor part)
    tdir0 = "../build/" + targetlist[0]
    cfg = open(tdir0 + "/cvconfig.h", "rt")
    for l in cfg.readlines():
        if l.startswith("#define  VERSION"):
            opencv_version = l[l.find("\"")+1:l.rfind(".")]
            break
    cfg.close()
82

83 84 85 86 87 88
    # form the directory tree
    dstdir = "Versions/A"
    os.makedirs(dstdir + "/Resources")

    # copy headers
    shutil.copytree(tdir0 + "/install/include/opencv2", dstdir + "/Headers")
89

90 91 92
    # 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")
93

94 95 96 97 98 99 100
    # form Info.plist
    srcfile = open(srcroot + "/ios/Info.plist.in", "rt")
    dstfile = open(dstdir + "/Resources/Info.plist", "wt")
    for l in srcfile.readlines():
        dstfile.write(l.replace("${VERSION}", opencv_version))
    srcfile.close()
    dstfile.close()
101

102 103
    # copy cascades
    # TODO ...
104

105 106 107 108 109
    # make symbolic links
    os.symlink(dstdir + "/Headers", "Headers")
    os.symlink(dstdir + "/Resources", "Resources")
    os.symlink(dstdir + "/opencv2", "opencv2")
    os.symlink("A", "Versions/Current")
110 111


112 113
def build_framework(srcroot, dstroot):
    "main function to do all the work"
114

115 116
    for target in ["iPhoneOS", "iPhoneSimulator"]:
        build_opencv(srcroot, os.path.join(dstroot, "build"), target)
117

118
    put_framework_together(srcroot, dstroot)
119

120 121 122 123 124

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "Usage:\n\t./build_framework.py <outputdir>\n\n"
        sys.exit(0)
125

126
    build_framework(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")), os.path.abspath(sys.argv[1]))