Home | History | Annotate | Download | only in osx
      1 #!/usr/bin/env python
      2 """
      3 The script builds OpenCV.framework for iOS.
      4 The built framework is universal, it can be used to build app and run it on either iOS simulator or real device.
      5 
      6 Usage:
      7     ./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     <outputdir>
     15         build/
     16             iPhoneOS-*/
     17                [cmake-generated build tree for an iOS device target]
     18             iPhoneSimulator/
     19                [cmake-generated build tree for iOS simulator]
     20         opencv2.framework/
     21             [the framework content]
     22 
     23 The script should handle minor OpenCV updates efficiently
     24 - it does not recompile the library from scratch each time.
     25 However, opencv2.framework directory is erased and recreated on each run.
     26 """
     27 
     28 import glob, re, os, os.path, shutil, string, sys
     29 
     30 def build_opencv(srcroot, buildroot, target, arch):
     31     "builds OpenCV for device or simulator"
     32 
     33     builddir = os.path.join(buildroot, target + '-' + arch)
     34     if not os.path.isdir(builddir):
     35         os.makedirs(builddir)
     36     currdir = os.getcwd()
     37     os.chdir(builddir)
     38     # for some reason, if you do not specify CMAKE_BUILD_TYPE, it puts libs to "RELEASE" rather than "Release"
     39     cmakeargs = ("-GXcode " +
     40                 "-DCMAKE_BUILD_TYPE=Release " +
     41                 "-DBUILD_SHARED_LIBS=OFF " +
     42                 "-DBUILD_DOCS=OFF " +
     43                 "-DBUILD_EXAMPLES=OFF " +
     44                 "-DBUILD_TESTS=OFF " +
     45                 "-DBUILD_PERF_TESTS=OFF " +
     46                 "-DBUILD_opencv_apps=OFF " +
     47                 "-DBUILD_opencv_world=ON " +
     48                 "-DBUILD_opencv_matlab=OFF " +
     49                 "-DWITH_TIFF=OFF -DBUILD_TIFF=OFF " +
     50                 "-DWITH_JASPER=OFF -DBUILD_JASPER=OFF " +
     51                 "-DWITH_WEBP=OFF -DBUILD_WEBP=OFF " +
     52                 "-DWITH_OPENEXR=OFF -DBUILD_OPENEXR=OFF " +
     53                 "-DWITH_IPP=OFF -DWITH_IPP_A=OFF " +
     54                 "-DCMAKE_C_FLAGS=\"-Wno-implicit-function-declaration\" " +
     55                 "-DCMAKE_INSTALL_PREFIX=install")
     56     # if cmake cache exists, just rerun cmake to update OpenCV.xproj if necessary
     57     if os.path.isfile(os.path.join(builddir, "CMakeCache.txt")):
     58         os.system("cmake %s ." % (cmakeargs,))
     59     else:
     60         os.system("cmake %s %s" % (cmakeargs, srcroot))
     61 
     62     for wlib in [builddir + "/modules/world/UninstalledProducts/libopencv_world.a",
     63                  builddir + "/lib/Release/libopencv_world.a"]:
     64         if os.path.isfile(wlib):
     65             os.remove(wlib)
     66 
     67     os.system("xcodebuild -parallelizeTargets ARCHS=%s -jobs 2 -sdk %s -configuration Release -target ALL_BUILD" % (arch, target.lower()))
     68     os.system("xcodebuild ARCHS=%s -sdk %s -configuration Release -target install install" % (arch, target.lower()))
     69     os.chdir(currdir)
     70 
     71 def put_framework_together(srcroot, dstroot):
     72     "constructs the framework directory after all the targets are built"
     73 
     74     # find the list of targets (basically, ["iPhoneOS", "iPhoneSimulator"])
     75     targetlist = glob.glob(os.path.join(dstroot, "build", "*"))
     76     targetlist = [os.path.basename(t) for t in targetlist]
     77 
     78     # set the current dir to the dst root
     79     currdir = os.getcwd()
     80     framework_dir = dstroot + "/opencv2.framework"
     81     if os.path.isdir(framework_dir):
     82         shutil.rmtree(framework_dir)
     83     os.makedirs(framework_dir)
     84     os.chdir(framework_dir)
     85 
     86     # form the directory tree
     87     dstdir = "Versions/A"
     88     os.makedirs(dstdir + "/Resources")
     89 
     90     tdir0 = "../build/" + targetlist[0]
     91     # copy headers
     92     shutil.copytree(tdir0 + "/install/include/opencv2", dstdir + "/Headers")
     93 
     94     # make universal static lib
     95     wlist = " ".join(["../build/" + t + "/lib/Release/libopencv_world.a" for t in targetlist])
     96     os.system("lipo -create " + wlist + " -o " + dstdir + "/opencv2")
     97 
     98     # copy Info.plist
     99     shutil.copyfile(tdir0 + "/osx/Info.plist", dstdir + "/Resources/Info.plist")
    100 
    101     # make symbolic links
    102     os.symlink("A", "Versions/Current")
    103     os.symlink("Versions/Current/Headers", "Headers")
    104     os.symlink("Versions/Current/Resources", "Resources")
    105     os.symlink("Versions/Current/opencv2", "opencv2")
    106 
    107 
    108 def build_framework(srcroot, dstroot):
    109     "main function to do all the work"
    110 
    111     targets = ["MacOSX", "MacOSX" ]
    112     archs   = ["x86_64", "i386"   ]
    113     for i in range(len(targets)):
    114         build_opencv(srcroot, os.path.join(dstroot, "build"), targets[i], archs[i])
    115 
    116     put_framework_together(srcroot, dstroot)
    117 
    118 
    119 if __name__ == "__main__":
    120     if len(sys.argv) != 2:
    121         print "Usage:\n\t./build_framework.py <outputdir>\n\n"
    122         sys.exit(0)
    123 
    124     build_framework(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")), os.path.abspath(sys.argv[1]))
    125