[opencv] 68/71: android: backport Android SDK build script

Nobuhiro Iwamatsu iwamatsu at moszumanska.debian.org
Mon Oct 17 20:16:31 UTC 2016


This is an automated email from the git hooks/post-receive script.

iwamatsu pushed a commit to annotated tag 2.4.13.1
in repository opencv.

commit 4d17051f14bda835c463ddd80215c29b307d2a21
Author: Alexander Alekhin <alexander.alekhin at intel.com>
Date:   Fri Sep 16 16:14:54 2016 +0300

    android: backport Android SDK build script
---
 cmake/OpenCVDetectAndroidSDK.cmake                 |  12 ++
 cmake/templates/OpenCV.mk.in                       |   4 +
 .../generator/src/java/android+OpenCVLoader.java   |  13 ++
 platforms/android/build_sdk.py                     | 157 +++++----------------
 platforms/android/service/CMakeLists.txt           |   2 -
 platforms/android/service/doc/JavaHelper.rst       |   8 ++
 platforms/android/service/readme.txt               |   2 +
 samples/android/face-detection/jni/Android.mk      |   1 -
 8 files changed, 77 insertions(+), 122 deletions(-)

diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake
index 38430e2..4f26a78 100644
--- a/cmake/OpenCVDetectAndroidSDK.cmake
+++ b/cmake/OpenCVDetectAndroidSDK.cmake
@@ -274,6 +274,17 @@ macro(add_android_project target path)
     file(GLOB_RECURSE android_proj_jni_files "${path}/jni/*.c" "${path}/jni/*.h" "${path}/jni/*.cpp" "${path}/jni/*.hpp")
     ocv_list_filterout(android_proj_jni_files "\\\\.svn")
 
+    foreach(lib "opencv_java")
+      get_property(f TARGET ${lib} PROPERTY LOCATION)
+      get_filename_component(f_name ${f} NAME)
+      add_custom_command(
+        OUTPUT "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}"
+        COMMAND ${CMAKE_COMMAND} -E copy "${f}" "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}"
+        DEPENDS "${lib}" VERBATIM
+        COMMENT "Embedding ${f}")
+        list(APPEND android_proj_file_deps "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}")
+    endforeach()
+
     if(android_proj_jni_files AND EXISTS ${path}/jni/Android.mk AND NOT DEFINED JNI_LIB_NAME)
       # find local module name in Android.mk file to build native lib
       file(STRINGS "${path}/jni/Android.mk" JNI_LIB_NAME REGEX "LOCAL_MODULE[ ]*:=[ ]*.*" )
@@ -307,6 +318,7 @@ macro(add_android_project target path)
       # copy opencv_java, tbb if it is shared and dynamicuda if present if FORCE_EMBED_OPENCV flag is set
       if(android_proj_FORCE_EMBED_OPENCV)
         set(native_deps ${android_proj_NATIVE_DEPS})
+        list(REMOVE_ITEM native_deps "opencv_java")
         # filter out gpu module as it is always static library on Android
         list(REMOVE_ITEM native_deps "opencv_gpu")
         if(ENABLE_DYNAMIC_CUDA)
diff --git a/cmake/templates/OpenCV.mk.in b/cmake/templates/OpenCV.mk.in
index 66d476b..d85ed2b 100644
--- a/cmake/templates/OpenCV.mk.in
+++ b/cmake/templates/OpenCV.mk.in
@@ -110,6 +110,10 @@ else
     OPENCV_INSTALL_MODULES:=on
 endif
 
+ifeq ($(OPENCV_INSTALL_MODULES),)
+    OPENCV_INSTALL_MODULES:=on
+endif
+
 define add_opencv_module
     include $(CLEAR_VARS)
     LOCAL_MODULE:=opencv_$1
diff --git a/modules/java/generator/src/java/android+OpenCVLoader.java b/modules/java/generator/src/java/android+OpenCVLoader.java
index 2c05272..c220f19 100644
--- a/modules/java/generator/src/java/android+OpenCVLoader.java
+++ b/modules/java/generator/src/java/android+OpenCVLoader.java
@@ -1,12 +1,15 @@
 package org.opencv.android;
 
 import android.content.Context;
+import android.util.Log;
 
 /**
  * Helper class provides common initialization methods for OpenCV library.
  */
 public class OpenCVLoader
 {
+    private static final String TAG = "OpenCVLoader";
+
     /**
      * OpenCV Library version 2.4.2.
      */
@@ -63,6 +66,11 @@ public class OpenCVLoader
     public static final String OPENCV_VERSION_2_4_12 = "2.4.12";
 
     /**
+     * OpenCV Library version 2.4.13.
+     */
+    public static final String OPENCV_VERSION_2_4_13 = "2.4.13";
+
+    /**
      * Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").
      * @return Returns true is initialization of OpenCV was successful.
      */
@@ -91,6 +99,11 @@ public class OpenCVLoader
     public static boolean initAsync(String Version, Context AppContext,
             LoaderCallbackInterface Callback)
     {
+        if (initDebug()) {
+            Callback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
+            return true;
+        }
+        Log.w(TAG, "OpenCV binaries are not packaged with application. Trying to use OpenCV Manager...");
         return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback);
     }
 }
diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py
old mode 100755
new mode 100644
index 7d52eab..7251948
--- a/platforms/android/build_sdk.py
+++ b/platforms/android/build_sdk.py
@@ -10,13 +10,13 @@ class Fail(Exception):
     def __str__(self):
         return "ERROR" if self.t is None else self.t
 
-def execute(cmd, shell=False):
+def execute(cmd, shell=False, allowFail=False):
     try:
         log.info("Executing: %s" % cmd)
         retcode = subprocess.call(cmd, shell=shell)
         if retcode < 0:
             raise Fail("Child was terminated by signal:" %s -retcode)
-        elif retcode > 0:
+        elif retcode > 0 and not allowFail:
             raise Fail("Child returned: %s" % retcode)
     except OSError as e:
         raise Fail("Execution failed: %d / %s" % (e.errno, e.strerror))
@@ -45,44 +45,37 @@ def check_dir(d, create=False, clean=False):
             os.makedirs(d)
     return d
 
-def determine_engine_version(manifest_path):
-    with open(manifest_path, "rt") as f:
-        return re.search(r'android:versionName="(\d+\.\d+)"', f.read(), re.MULTILINE).group(1)
-
 def determine_opencv_version(version_hpp_path):
     # version in 2.4 - CV_VERSION_EPOCH.CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION
     # version in master - CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION-CV_VERSION_STATUS
     with open(version_hpp_path, "rt") as f:
         data = f.read()
+        epoch = re.search(r'^#define\W+CV_VERSION_EPOCH\W+(\d+)$', data, re.MULTILINE).group(1)
         major = re.search(r'^#define\W+CV_VERSION_MAJOR\W+(\d+)$', data, re.MULTILINE).group(1)
         minor = re.search(r'^#define\W+CV_VERSION_MINOR\W+(\d+)$', data, re.MULTILINE).group(1)
         revision = re.search(r'^#define\W+CV_VERSION_REVISION\W+(\d+)$', data, re.MULTILINE).group(1)
-        version_status = re.search(r'^#define\W+CV_VERSION_STATUS\W+"([^"]*)"$', data, re.MULTILINE).group(1)
-        return "%(major)s.%(minor)s.%(revision)s%(version_status)s" % locals()
+        revision = '' if revision == '0' else '.' + revision
+        return "%(epoch)s.%(major)s.%(minor)s%(revision)s" % locals()
 
 #===================================================================================================
 
 class ABI:
-    def __init__(self, platform_id, name, toolchain, cmake_name=None):
+    def __init__(self, platform_id, name, toolchain, api_level=8, cmake_name=None):
         self.platform_id = platform_id # platform code to add to apk version (for cmake)
         self.name = name # general name (official Android ABI identifier)
         self.toolchain = toolchain # toolchain identifier (for cmake)
+        self.api_level = api_level
         self.cmake_name = cmake_name # name of android toolchain (for cmake)
         if self.cmake_name is None:
             self.cmake_name = self.name
     def __str__(self):
         return "%s (%s)" % (self.name, self.toolchain)
-    def haveIPP(self):
-        return self.name == "x86" or self.name == "x86_64"
 
 ABIs = [
-    ABI("2", "armeabi-v7a", "arm-linux-androideabi-4.8", cmake_name="armeabi-v7a with NEON"),
-    ABI("1", "armeabi",     "arm-linux-androideabi-4.8"),
-    ABI("3", "arm64-v8a",   "aarch64-linux-android-4.9"),
-    ABI("5", "x86_64",      "x86_64-4.9"),
-    ABI("4", "x86",         "x86-4.8"),
-    ABI("7", "mips64",      "mips64el-linux-android-4.9"),
-    ABI("6", "mips",        "mipsel-linux-android-4.8")
+    ABI("2", "armeabi-v7a", "arm-linux-androideabi-4.6", cmake_name="armeabi-v7a with NEON"),
+    ABI("1", "armeabi",     "arm-linux-androideabi-4.6"),
+    ABI("4", "x86",         "x86-clang3.1", api_level=9),
+    ABI("6", "mips",        "mipsel-linux-android-4.6", api_level=9)
 ]
 
 #===================================================================================================
@@ -91,38 +84,30 @@ class Builder:
     def __init__(self, workdir, opencvdir):
         self.workdir = check_dir(workdir, create=True)
         self.opencvdir = check_dir(opencvdir)
-        self.extra_modules_path = None
         self.libdest = check_dir(os.path.join(self.workdir, "o4a"), create=True, clean=True)
         self.docdest = check_dir(os.path.join(self.workdir, "javadoc"), create=True, clean=True)
         self.resultdest = check_dir(os.path.join(self.workdir, "OpenCV-android-sdk"), create=True, clean=True)
-        self.extra_packs = []
         self.opencv_version = determine_opencv_version(os.path.join(self.opencvdir, "modules", "core", "include", "opencv2", "core", "version.hpp"))
-        self.engine_version = determine_engine_version(os.path.join(self.opencvdir, "platforms", "android", "service", "engine", "AndroidManifest.xml"))
         self.use_ccache = True
 
     def get_toolchain_file(self):
         return os.path.join(self.opencvdir, "platforms", "android", "android.toolchain.cmake")
 
-    def get_engine_apk_dest(self, engdest):
-        return os.path.join(engdest, "platforms", "android", "service", "engine", ".build")
-
-    def add_extra_pack(self, ver, path):
-        if path is None:
-            return
-        self.extra_packs.append((ver, check_dir(path)))
-
     def clean_library_build_dir(self):
         for d in ["CMakeCache.txt", "CMakeFiles/", "bin/", "libs/", "lib/", "package/", "install/samples/"]:
             rm_one(d)
 
-    def build_library(self, abi, do_install):
+    def build_library(self, abi, do_install, build_docs):
         cmd = [
             "cmake",
             "-GNinja",
             "-DCMAKE_TOOLCHAIN_FILE='%s'" % self.get_toolchain_file(),
-            "-DWITH_OPENCL=OFF",
-            "-DWITH_CUDA=OFF",
-            "-DWITH_IPP=%s" % ("ON" if abi.haveIPP() else "OFF"),
+            "-DINSTALL_CREATE_DISTRIB=ON",
+            #"-DWITH_OPENCL=OFF",
+            "-DWITH_CUDA=OFF", "-DBUILD_opencv_gpu=OFF",
+            "-DBUILD_opencv_nonfree=OFF",
+            "-DWITH_TBB=OFF",
+            "-DWITH_IPP=OFF",
             "-DBUILD_EXAMPLES=OFF",
             "-DBUILD_TESTS=OFF",
             "-DBUILD_PERF_TESTS=OFF",
@@ -130,68 +115,28 @@ class Builder:
             "-DBUILD_ANDROID_EXAMPLES=ON",
             "-DINSTALL_ANDROID_EXAMPLES=ON",
             "-DANDROID_STL=gnustl_static",
-            "-DANDROID_NATIVE_API_LEVEL=9",
+            "-DANDROID_NATIVE_API_LEVEL=%s" % abi.api_level,
             "-DANDROID_ABI='%s'" % abi.cmake_name,
-            "-DWITH_TBB=ON",
             "-DANDROID_TOOLCHAIN_NAME=%s" % abi.toolchain
         ]
 
-        if self.extra_modules_path is not None:
-            cmd.append("-DOPENCV_EXTRA_MODULES_PATH='%s'" % self.extra_modules_path)
-
         cmd.append(self.opencvdir)
 
         if self.use_ccache == True:
             cmd.append("-DNDK_CCACHE=ccache")
         if do_install:
             cmd.extend(["-DBUILD_TESTS=ON", "-DINSTALL_TESTS=ON"])
+        if do_install and build_docs:
+            cmd.extend(["-DBUILD_DOCS=ON"])
         execute(cmd)
         if do_install:
-            execute(["ninja"])
-            for c in ["libs", "dev", "java", "samples"]:
+            execute(["cmake", "--build", "."])
+            if do_install and build_docs:
+                execute(["cmake", "--build", ".", "--target", "docs"])
+            for c in ["libs", "dev", "java", "samples"] + (["docs"] if do_install and build_docs else []):
                 execute(["cmake", "-DCOMPONENT=%s" % c, "-P", "cmake_install.cmake"])
         else:
-            execute(["ninja", "install/strip"])
-
-    def build_engine(self, abi, engdest):
-        cmd = [
-            "cmake",
-            "-GNinja",
-            "-DCMAKE_TOOLCHAIN_FILE='%s'" % self.get_toolchain_file(),
-            "-DANDROID_ABI='%s'" % abi.cmake_name,
-            "-DBUILD_ANDROID_SERVICE=ON",
-            "-DANDROID_PLATFORM_ID=%s" % abi.platform_id,
-            "-DWITH_CUDA=OFF",
-            "-DWITH_OPENCL=OFF",
-            "-DWITH_IPP=OFF",
-            self.opencvdir
-        ]
-        execute(cmd)
-        apkdest = self.get_engine_apk_dest(engdest)
-        # Add extra data
-        apkxmldest = check_dir(os.path.join(apkdest, "res", "xml"), create=True)
-        apklibdest = check_dir(os.path.join(apkdest, "libs", abi.name), create=True)
-        for ver, d in self.extra_packs + [("3.1.0", os.path.join(self.libdest, "lib"))]:
-            r = ET.Element("library", attrib={"version": ver})
-            log.info("Adding libraries from %s", d)
-
-            for f in glob.glob(os.path.join(d, abi.name, "*.so")):
-                log.info("Copy file: %s", f)
-                shutil.copy2(f, apklibdest)
-                if "libnative_camera" in f:
-                    continue
-                log.info("Register file: %s", os.path.basename(f))
-                n = ET.SubElement(r, "file", attrib={"name": os.path.basename(f)})
-
-            if len(list(r)) > 0:
-                xmlname = os.path.join(apkxmldest, "config%s.xml" % ver.replace(".", ""))
-                log.info("Generating XML config: %s", xmlname)
-                ET.ElementTree(r).write(xmlname, encoding="utf-8")
-
-        execute(["ninja", "opencv_engine"])
-        execute(["ant", "-f", os.path.join(apkdest, "build.xml"), "debug"],
-            shell=(sys.platform == 'win32'))
-        # TODO: Sign apk
+            execute(["cmake", "--build", ".", "--target", "install/strip"])
 
     def build_javadoc(self):
         classpaths = [os.path.join(self.libdest, "bin", "classes")]
@@ -201,6 +146,7 @@ class Builder:
                     classpaths.append(os.path.join(dir, f))
         cmd = [
             "javadoc",
+            "-encoding", "UTF-8",
             "-header", "OpenCV %s" % self.opencv_version,
             "-nodeprecated",
             "-footer", '<a href="http://docs.opencv.org">OpenCV %s Documentation</a>' % self.opencv_version,
@@ -211,9 +157,9 @@ class Builder:
         ]
         for _, dirs, _ in os.walk(os.path.join(self.libdest, "src", "org", "opencv")):
             cmd.extend(["org.opencv." + d for d in dirs])
-        execute(cmd)
+        execute(cmd, allowFail=True) # FIXIT javadoc currenly reports some errors
 
-    def gather_results(self, engines):
+    def gather_results(self, with_samples_apk):
         # Copy all files
         root = os.path.join(self.libdest, "install")
         for item in os.listdir(root):
@@ -226,13 +172,6 @@ class Builder:
                 log.info("Copy file: %s", item)
                 shutil.copy2(item, os.path.join(self.resultdest, name))
 
-        # Copy engines for all platforms
-        for abi, engdest in engines:
-            log.info("Copy engine: %s (%s)", abi, engdest)
-            f = os.path.join(self.get_engine_apk_dest(engdest), "bin", "opencv_engine-debug.apk")
-            resname = "OpenCV_%s_Manager_%s_%s.apk" % (self.opencv_version, self.engine_version, abi)
-            shutil.copy2(f, os.path.join(self.resultdest, "apk", resname))
-
         # Copy javadoc
         log.info("Copy docs: %s", self.docdest)
         shutil.copytree(self.docdest, os.path.join(self.resultdest, "sdk", "java", "javadoc"))
@@ -244,6 +183,9 @@ class Builder:
             if os.path.isdir(item):
                 for name in ["build.xml", "local.properties", "proguard-project.txt"]:
                     rm_one(os.path.join(item, name))
+            if not with_samples_apk:
+                if re.search(r'\.apk$', item):  # reduce size of SDK
+                    rm_one(item)
 
 
 #===================================================================================================
@@ -254,11 +196,10 @@ if __name__ == "__main__":
     parser.add_argument("opencv_dir", help="Path to OpenCV source dir")
     parser.add_argument('--ndk_path', help="Path to Android NDK to use for build")
     parser.add_argument('--sdk_path', help="Path to Android SDK to use for build")
-    parser.add_argument("--extra_modules_path", help="Path to extra modules to use for build")
-    parser.add_argument('--sign_with', help="Sertificate to sign the Manager apk")
-    parser.add_argument('--build_doc', action="store_true", help="Build javadoc")
+    parser.add_argument('--build_doc', action="store_true", help="Build documentation")
+    parser.add_argument('--build_javadoc', action="store_true", help="Build javadoc")
     parser.add_argument('--no_ccache', action="store_true", help="Do not use ccache during library build")
-    parser.add_argument('--extra_pack', action='append', help="provide extra OpenCV libraries for Manager apk in form <version>:<path-to-native-libs>, for example '2.4.11:unpacked/sdk/native/libs'")
+    parser.add_argument('--with_samples_apk', action="store_true", help="Include samples APKs")
     args = parser.parse_args()
 
     log.basicConfig(format='%(message)s', level=log.DEBUG)
@@ -274,27 +215,13 @@ if __name__ == "__main__":
 
     builder = Builder(args.work_dir, args.opencv_dir)
 
-    if args.extra_modules_path is not None:
-        builder.extra_modules_path = os.path.abspath(args.extra_modules_path)
-
     if args.no_ccache:
         builder.use_ccache = False
 
     log.info("Detected OpenCV version: %s", builder.opencv_version)
-    log.info("Detected Engine version: %s", builder.engine_version)
 
-    if args.extra_pack:
-        for one in args.extra_pack:
-            i = one.find(":")
-            if i > 0 and i < len(one) - 1:
-                builder.add_extra_pack(one[:i], one[i+1:])
-            else:
-                raise Fail("Bad extra pack provided: %s, should be in form '<version>:<path-to-native-libs>'" % one)
-
-    engines = []
     for i, abi in enumerate(ABIs):
         do_install = (i == 0)
-        engdest = check_dir(os.path.join(builder.workdir, "build_service_%s" % abi.name), create=True, clean=True)
 
         log.info("=====")
         log.info("===== Building library for %s", abi)
@@ -302,20 +229,12 @@ if __name__ == "__main__":
 
         os.chdir(builder.libdest)
         builder.clean_library_build_dir()
-        builder.build_library(abi, do_install)
-
-        log.info("=====")
-        log.info("===== Building engine for %s", abi)
-        log.info("=====")
-
-        os.chdir(engdest)
-        builder.build_engine(abi, engdest)
-        engines.append((abi.name, engdest))
+        builder.build_library(abi, do_install, build_docs=args.build_doc)
 
-    if args.build_doc:
+    if args.build_doc or args.build_javadoc:
         builder.build_javadoc()
 
-    builder.gather_results(engines)
+    builder.gather_results(with_samples_apk=args.with_samples_apk)
 
     log.info("=====")
     log.info("===== Build finished")
diff --git a/platforms/android/service/CMakeLists.txt b/platforms/android/service/CMakeLists.txt
index c99b713..7b1522b 100644
--- a/platforms/android/service/CMakeLists.txt
+++ b/platforms/android/service/CMakeLists.txt
@@ -2,5 +2,3 @@ if(BUILD_ANDROID_SERVICE)
   add_subdirectory(engine)
   #add_subdirectory(engine_test)
 endif()
-
-install(FILES "readme.txt" DESTINATION "apk/" COMPONENT libs)
diff --git a/platforms/android/service/doc/JavaHelper.rst b/platforms/android/service/doc/JavaHelper.rst
index 6be46d6..3c3762b 100644
--- a/platforms/android/service/doc/JavaHelper.rst
+++ b/platforms/android/service/doc/JavaHelper.rst
@@ -79,3 +79,11 @@ OpenCV version constants
 .. data:: OPENCV_VERSION_2_4_11
 
     OpenCV Library version 2.4.11
+
+.. data:: OPENCV_VERSION_2_4_12
+
+    OpenCV Library version 2.4.12
+
+.. data:: OPENCV_VERSION_2_4_13
+
+    OpenCV Library version 2.4.13
diff --git a/platforms/android/service/readme.txt b/platforms/android/service/readme.txt
index 51853c2..c8230e3 100644
--- a/platforms/android/service/readme.txt
+++ b/platforms/android/service/readme.txt
@@ -1,6 +1,8 @@
 How to select the proper version of OpenCV Manager
 --------------------------------------------------
 
+DEPRECATED: This information is outdated since OpenCV 2.4.12
+
 Since version 1.7 several packages of OpenCV Manager are built. Every package is targeted for some
 specific hardware platform and includes corresponding OpenCV binaries. So, in most cases OpenCV
 Manager uses built-in version of OpenCV. Separate package with OpenCV binaries is currently used in
diff --git a/samples/android/face-detection/jni/Android.mk b/samples/android/face-detection/jni/Android.mk
index 6b66426..cf20dff 100644
--- a/samples/android/face-detection/jni/Android.mk
+++ b/samples/android/face-detection/jni/Android.mk
@@ -3,7 +3,6 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 #OPENCV_CAMERA_MODULES:=off
-#OPENCV_INSTALL_MODULES:=off
 #OPENCV_LIB_TYPE:=SHARED
 include ../../sdk/native/jni/OpenCV.mk
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/opencv.git



More information about the debian-science-commits mailing list