From 76f49f307829a6424160b88575ed41225b7fe72e Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Sat, 9 Jun 2012 16:18:39 +0000 Subject: [PATCH] added script to build the universal opencv2.framework for iOS device and simulator. fixed opencv_world cmake script to create static libopencv_world.a for iOS. temporarily disable compressed file storages in the case of iOS (to avoid dependency of zlib) --- ios/Info.plist.in | 18 +++++ ios/build_framework.py | 120 +++++++++++++++++++++++++++++++ modules/core/src/persistence.cpp | 28 ++++++++ modules/world/CMakeLists.txt | 27 +++++-- 4 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 ios/Info.plist.in create mode 100755 ios/build_framework.py diff --git a/ios/Info.plist.in b/ios/Info.plist.in new file mode 100644 index 0000000000..9b3d882a77 --- /dev/null +++ b/ios/Info.plist.in @@ -0,0 +1,18 @@ + + + + + CFBundleName + OpenCV + CFBundleIdentifier + com.itseez.opencv + CFBundleVersion + ${VERSION} + CFBundleShortVersionString + ${VERSION} + CFBundleSignature + ???? + CFBundlePackageType + FMWK + + diff --git a/ios/build_framework.py b/ios/build_framework.py new file mode 100755 index 0000000000..f6a6970abf --- /dev/null +++ b/ios/build_framework.py @@ -0,0 +1,120 @@ +#!/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 + +By cmake conventions (and especially if you work with OpenCV SVN repository), +the output dir should not be a subdirectory of OpenCV source tree. + +Script will create , if it's missing, and a few its subdirectories: + + + 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" + + 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)) + 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) + +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) + + # 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() + + # form the directory tree + dstdir = "Versions/A" + os.makedirs(dstdir + "/Resources") + + # 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") + + # 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() + + # copy cascades + # TODO ... + + # make symbolic links + os.symlink(dstdir + "/Headers", "Headers") + os.symlink(dstdir + "/Resources", "Resources") + os.symlink(dstdir + "/opencv2", "opencv2") + os.symlink("A", "Versions/Current") + + +def build_framework(srcroot, dstroot): + "main function to do all the work" + + for target in ["iPhoneOS", "iPhoneSimulator"]: + build_opencv(srcroot, os.path.join(dstroot, "build"), target) + + put_framework_together(srcroot, dstroot) + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print "Usage:\n\t./build_framework.py \n\n" + sys.exit(0) + + build_framework(os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")), os.path.abspath(sys.argv[1])) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 2c1432b4ef..3f605f3a51 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -46,7 +46,21 @@ #include #include #include + +#define USE_ZLIB 1 + +#ifdef __APPLE__ +#include "TargetConditionals.h" +#if defined TARGET_OS_IPHONE || defined TARGET_IPHONE_SIMULATOR +#undef USE_ZLIB +#define USE_ZLIB 0 +typedef void* gzFile; +#endif +#endif + +#if USE_ZLIB #include +#endif /****************************************************************************************\ * Common macros and type definitions * @@ -258,8 +272,10 @@ static void icvPuts( CvFileStorage* fs, const char* str ) std::copy(str, str + strlen(str), std::back_inserter(*fs->outbuf)); else if( fs->file ) fputs( str, fs->file ); +#if USE_ZLIB else if( fs->gzfile ) gzputs( fs->gzfile, str ); +#endif else CV_Error( CV_StsError, "The storage is not opened" ); } @@ -286,8 +302,10 @@ static char* icvGets( CvFileStorage* fs, char* str, int maxCount ) } if( fs->file ) return fgets( str, maxCount, fs->file ); +#if USE_ZLIB if( fs->gzfile ) return gzgets( fs->gzfile, str, maxCount ); +#endif CV_Error( CV_StsError, "The storage is not opened" ); return 0; } @@ -298,8 +316,10 @@ static int icvEof( CvFileStorage* fs ) return fs->strbufpos >= fs->strbufsize; if( fs->file ) return feof(fs->file); +#if USE_ZLIB if( fs->gzfile ) return gzeof(fs->gzfile); +#endif return false; } @@ -307,8 +327,10 @@ static void icvCloseFile( CvFileStorage* fs ) { if( fs->file ) fclose( fs->file ); +#if USE_ZLIB else if( fs->gzfile ) gzclose( fs->gzfile ); +#endif fs->file = 0; fs->gzfile = 0; fs->strbuf = 0; @@ -320,8 +342,10 @@ static void icvRewind( CvFileStorage* fs ) { if( fs->file ) rewind(fs->file); +#if USE_ZLIB else if( fs->gzfile ) gzrewind(fs->gzfile); +#endif fs->strbufpos = 0; } @@ -2713,10 +2737,14 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co } else { + #if USE_ZLIB char mode[] = { fs->write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0' }; fs->gzfile = gzopen(fs->filename, mode); if( !fs->gzfile ) goto _exit_; + #else + CV_Error(CV_StsNotImplemented, "There is no compressed file storage support in this configuration"); + #endif } } diff --git a/modules/world/CMakeLists.txt b/modules/world/CMakeLists.txt index 9d626e8fe8..1530cc8d9d 100644 --- a/modules/world/CMakeLists.txt +++ b/modules/world/CMakeLists.txt @@ -1,7 +1,13 @@ set(the_description "All the selected OpenCV modules in a single binary") set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE) set(BUILD_opencv_world_INIT OFF) +if(IOS) +set(BUILD_WORLD_AS_STATIC 1) +endif() + +if(NOT BUILD_WORLD_AS_STATIC) set(OPENCV_MODULE_TYPE SHARED) +endif() ocv_add_module(world opencv_core) @@ -79,14 +85,25 @@ string(REPLACE ";" " " objlist "${objlist}") if(have_cfg) string(REGEX REPLACE "" "Debug" objlist_dbg "${objlist}") string(REGEX REPLACE "" "Release" objlist_rls "${objlist}") - set_target_properties(${the_module} PROPERTIES - LINK_FLAGS_DEBUG ${objlist_dbg} - LINK_FLAGS_RELEASE ${objlist_rls}) + if(BUILD_WORLD_AS_STATIC) + set_target_properties(${the_module} PROPERTIES + STATIC_LIBRARY_FLAGS_DEBUG ${objlist_dbg} + STATIC_LIBRARY_FLAGS_RELEASE ${objlist_rls}) + else() + set_target_properties(${the_module} PROPERTIES + LINK_FLAGS_DEBUG ${objlist_dbg} + LINK_FLAGS_RELEASE ${objlist_rls}) + endif() else() file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/world_objects.list" "${objlist}") execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/world_objects.list" "${CMAKE_CURRENT_BINARY_DIR}/world_objects.rsp" OUTPUT_QUIET) - set_target_properties(${the_module} PROPERTIES - LINK_FLAGS "@${CMAKE_CURRENT_BINARY_DIR}/world_objects.rsp") + if(BUILD_WORLD_AS_STATIC) + set_target_properties(${the_module} PROPERTIES + STATIC_LIBRARY_FLAGS "@${CMAKE_CURRENT_BINARY_DIR}/world_objects.rsp") + else() + set_target_properties(${the_module} PROPERTIES + LINK_FLAGS "@${CMAKE_CURRENT_BINARY_DIR}/world_objects.rsp") + endif() endif() ocv_add_precompiled_headers(${the_module})