Skip to content

Commit

Permalink
update osx and ios build_framework.py
Browse files Browse the repository at this point in the history
  • Loading branch information
alalek committed Dec 17, 2015
1 parent 3c6aa65 commit be23846
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 207 deletions.
20 changes: 11 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -214,20 +214,20 @@ OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON

# OpenCV build components
# ===================================================
OCV_OPTION(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" NOT (ANDROID OR IOS) )
OCV_OPTION(BUILD_opencv_apps "Build utility applications (used for example to train classifiers)" (NOT ANDROID AND NOT WINRT) IF (NOT IOS) )
OCV_OPTION(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" NOT (ANDROID OR APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_opencv_apps "Build utility applications (used for example to train classifiers)" (NOT ANDROID AND NOT WINRT) IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_ANDROID_EXAMPLES "Build examples for Android platform" ON IF ANDROID )
OCV_OPTION(BUILD_DOCS "Create build rules for OpenCV Documentation" ON IF NOT WINRT)
OCV_OPTION(BUILD_DOCS "Create build rules for OpenCV Documentation" ON IF (NOT WINRT OR APPLE_FRAMEWORK))
OCV_OPTION(BUILD_EXAMPLES "Build all examples" OFF )
OCV_OPTION(BUILD_PACKAGE "Enables 'make package_source' command" ON IF NOT WINRT)
OCV_OPTION(BUILD_PERF_TESTS "Build performance tests" ON IF (NOT IOS) )
OCV_OPTION(BUILD_TESTS "Build accuracy & regression tests" ON IF (NOT IOS) )
OCV_OPTION(BUILD_PERF_TESTS "Build performance tests" ON IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_TESTS "Build accuracy & regression tests" ON IF (NOT APPLE_FRAMEWORK) )
OCV_OPTION(BUILD_WITH_DEBUG_INFO "Include debug info into debug libs (not MSCV only)" ON )
OCV_OPTION(BUILD_WITH_STATIC_CRT "Enables use of staticaly linked CRT for staticaly linked OpenCV" ON IF MSVC )
OCV_OPTION(BUILD_WITH_DYNAMIC_IPP "Enables dynamic linking of IPP (only for standalone IPP)" OFF )
OCV_OPTION(BUILD_FAT_JAVA_LIB "Create fat java wrapper containing the whole OpenCV library" ON IF NOT BUILD_SHARED_LIBS AND CMAKE_COMPILER_IS_GNUCXX )
OCV_OPTION(BUILD_ANDROID_SERVICE "Build OpenCV Manager for Google Play" OFF IF ANDROID )
OCV_OPTION(BUILD_CUDA_STUBS "Build CUDA modules stubs when no CUDA SDK" OFF IF (NOT IOS) )
OCV_OPTION(BUILD_CUDA_STUBS "Build CUDA modules stubs when no CUDA SDK" OFF IF (NOT APPLE_FRAMEWORK) )

# 3rd party libs
OCV_OPTION(BUILD_ZLIB "Build zlib from source" WIN32 OR APPLE )
Expand All @@ -244,7 +244,7 @@ OCV_OPTION(INSTALL_CREATE_DISTRIB "Change install rules to build the distribut
OCV_OPTION(INSTALL_C_EXAMPLES "Install C examples" OFF )
OCV_OPTION(INSTALL_PYTHON_EXAMPLES "Install Python examples" OFF )
OCV_OPTION(INSTALL_ANDROID_EXAMPLES "Install Android examples" OFF IF ANDROID )
OCV_OPTION(INSTALL_TO_MANGLED_PATHS "Enables mangled install paths, that help with side by side installs." OFF IF (UNIX AND NOT ANDROID AND NOT IOS AND BUILD_SHARED_LIBS) )
OCV_OPTION(INSTALL_TO_MANGLED_PATHS "Enables mangled install paths, that help with side by side installs." OFF IF (UNIX AND NOT ANDROID AND NOT APPLE_FRAMEWORK AND BUILD_SHARED_LIBS) )
OCV_OPTION(INSTALL_TESTS "Install accuracy and performance test binaries and test data" OFF)

# OpenCV build options
Expand Down Expand Up @@ -422,7 +422,7 @@ if(DEFINED CMAKE_DEBUG_POSTFIX)
set(OPENCV_DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
endif()

if(INSTALL_CREATE_DISTRIB AND BUILD_SHARED_LIBS AND NOT DEFINED BUILD_opencv_world)
if((INSTALL_CREATE_DISTRIB AND BUILD_SHARED_LIBS AND NOT DEFINED BUILD_opencv_world) OR APPLE_FRAMEWORK)
set(BUILD_opencv_world ON CACHE INTERNAL "")
endif()

Expand Down Expand Up @@ -669,7 +669,9 @@ include(cmake/OpenCVGenAndroidMK.cmake)
include(cmake/OpenCVGenConfig.cmake)

# Generate Info.plist for the IOS framework
include(cmake/OpenCVGenInfoPlist.cmake)
if(APPLE_FRAMEWORK)
include(cmake/OpenCVGenInfoPlist.cmake)
endif()

# Generate ABI descriptor
include(cmake/OpenCVGenABI.cmake)
Expand Down
2 changes: 1 addition & 1 deletion cmake/OpenCVDetectPython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function(find_python preferred_version min_version library_env include_dir_env
if(_found)
set(_version_major_minor "${_version_major}.${_version_minor}")

if(NOT ANDROID AND NOT IOS)
if(NOT ANDROID AND NOT APPLE_FRAMEWORK)
ocv_check_environment_variables(${library_env} ${include_dir_env})
if(NOT ${${library_env}} EQUAL "")
set(PYTHON_LIBRARY "${${library_env}}")
Expand Down
9 changes: 2 additions & 7 deletions cmake/OpenCVGenInfoPlist.cmake
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
if(OPENCV_EXTRA_WORLD)
set(OPENCV_APPLE_BUNDLE_NAME "OpenCV_contrib")
set(OPENCV_APPLE_BUNDLE_ID "org.opencv_contrib")
else()
set(OPENCV_APPLE_BUNDLE_NAME "OpenCV")
set(OPENCV_APPLE_BUNDLE_ID "org.opencv")
endif()
set(OPENCV_APPLE_BUNDLE_NAME "OpenCV")
set(OPENCV_APPLE_BUNDLE_ID "org.opencv")

if(IOS)
configure_file("${OpenCV_SOURCE_DIR}/platforms/ios/Info.plist.in"
Expand Down
28 changes: 20 additions & 8 deletions cmake/OpenCVModule.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ function(__ocv_sort_modules_by_deps __lst)
ocv_list_sort(${__lst})
set(input ${${__lst}})
set(result "")
set(result_extra "")
while(input)
list(LENGTH input length_before)
foreach (m ${input})
Expand All @@ -376,16 +377,27 @@ function(__ocv_sort_modules_by_deps __lst)
list(LENGTH input length_after)
# check for infinite loop or unresolved dependencies
if (NOT length_after LESS length_before)
message(WARNING "Unresolved dependencies or loop in dependency graph (${length_after})\n"
"Processed ${__lst}: ${${__lst}}\n"
"Good modules: ${result}\n"
"Bad modules: ${input}"
)
list(APPEND result ${input})
break()
if(NOT BUILD_SHARED_LIBS)
if (";${input};" MATCHES ";opencv_world;")
list(REMOVE_ITEM input "opencv_world")
list(APPEND result_extra "opencv_world")
else()
# We can't do here something
list(APPEND result ${input})
break()
endif()
else()
message(FATAL_ERROR WARNING "Unresolved dependencies or loop in dependency graph (${length_after})\n"
"Processed ${__lst}: ${${__lst}}\n"
"Good modules: ${result}\n"
"Bad modules: ${input}"
)
list(APPEND result ${input})
break()
endif()
endif()
endwhile()
set(${__lst} "${result}" PARENT_SCOPE)
set(${__lst} "${result};${result_extra}" PARENT_SCOPE)
endfunction()

# resolve dependensies
Expand Down
3 changes: 3 additions & 0 deletions cmake/OpenCVUtils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,9 @@ function(ocv_target_link_libraries target)
endif()
endforeach()
endif()
if(";${LINK_DEPS};" MATCHES ";${target};")
list(REMOVE_ITEM LINK_DEPS "${target}") # prevent "link to itself" warning (world problem)
endif()
target_link_libraries(${target} ${LINK_DEPS})
endfunction()

Expand Down
1 change: 0 additions & 1 deletion modules/imgcodecs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ file(GLOB imgcodecs_ext_hdrs
)

if(IOS)
add_definitions(-DHAVE_IOS=1)
list(APPEND imgcodecs_srcs ${CMAKE_CURRENT_LIST_DIR}/src/ios_conversions.mm)
list(APPEND IMGCODECS_LIBRARIES "-framework Accelerate" "-framework CoreGraphics" "-framework CoreImage" "-framework QuartzCore" "-framework AssetsLibrary")
endif()
Expand Down
3 changes: 2 additions & 1 deletion modules/java/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# ----------------------------------------------------------------------------
# CMake file for java support
# ----------------------------------------------------------------------------
if(IOS OR WINRT OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT ANT_EXECUTABLE OR NOT (JNI_FOUND OR (ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER 7))
if(APPLE_FRAMEWORK OR WINRT OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT ANT_EXECUTABLE
OR NOT (JNI_FOUND OR (ANDROID AND ANDROID_NATIVE_API_LEVEL GREATER 7))
OR BUILD_opencv_world
)
ocv_module_disable(java)
Expand Down
2 changes: 1 addition & 1 deletion modules/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if((WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
ocv_module_disable(python3)
endif()

if(ANDROID OR IOS OR WINRT)
if(ANDROID OR APPLE_FRAMEWORK OR WINRT)
ocv_module_disable(python2)
ocv_module_disable(python3)
endif()
Expand Down
1 change: 0 additions & 1 deletion modules/videoio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ if(HAVE_GPHOTO2)
endif(HAVE_GPHOTO2)

if(IOS)
add_definitions(-DHAVE_IOS=1)
list(APPEND videoio_srcs
${CMAKE_CURRENT_LIST_DIR}/src/cap_ios_abstract_camera.mm
${CMAKE_CURRENT_LIST_DIR}/src/cap_ios_photo_camera.mm
Expand Down
25 changes: 1 addition & 24 deletions modules/world/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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 OR NOT BUILD_SHARED_LIBS)
if(APPLE_FRAMEWORK OR NOT BUILD_SHARED_LIBS)
set(OPENCV_MODULE_TYPE STATIC)
set(OPENCV_WORLD_FLAGS_PROPERTY STATIC_LIBRARY_FLAGS)
else()
Expand Down Expand Up @@ -59,26 +59,3 @@ endif()
if(BUILD_opencv_highgui AND OPENCV_MODULE_opencv_highgui_IS_PART_OF_WORLD)
ocv_highgui_configure_target()
endif()

if(IOS OR APPLE)
set(merge_libs "")
macro(ios_include_3party_libs)
foreach(l ${ARGN})
add_dependencies(${the_module} ${l})
list(APPEND merge_libs "$<TARGET_LINKER_FILE:${l}>")
endforeach()
endmacro()

if(WITH_PNG)
ios_include_3party_libs(zlib libpng)
endif()

if(WITH_JPEG)
ios_include_3party_libs(libjpeg)
endif()

add_custom_command(TARGET ${the_module} POST_BUILD
COMMAND /usr/bin/libtool -static -o ${CMAKE_CURRENT_BINARY_DIR}/${the_module}_fat.a $<TARGET_LINKER_FILE:${the_module}> ${merge_libs}
COMMAND mv ${CMAKE_CURRENT_BINARY_DIR}/${the_module}_fat.a $<TARGET_LINKER_FILE:${the_module}>
)
endif()
100 changes: 58 additions & 42 deletions platforms/ios/build_framework.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -52,21 +52,15 @@ def __init__(self, opencv, contrib):
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)
if not os.path.isdir(res):
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)
Expand All @@ -81,52 +75,74 @@ def build(self, outdir):
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",
"ARCHS=%s" % arch,
"-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)

Expand Down Expand Up @@ -156,7 +172,7 @@ def makeFramework(self, outdir, builddirs):
# 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 = [
Expand All @@ -178,12 +194,12 @@ def makeFramework(self, outdir, builddirs):
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)
Loading

0 comments on commit be23846

Please sign in to comment.