|
1 |
| -import os |
| 1 | +from os.path import join |
2 | 2 | import sh
|
3 | 3 | from pythonforandroid.recipe import NDKRecipe
|
4 | 4 | from pythonforandroid.toolchain import (
|
|
9 | 9 |
|
10 | 10 |
|
11 | 11 | class OpenCVRecipe(NDKRecipe):
|
| 12 | + ''' |
| 13 | + .. versionchanged:: 0.7.1 |
| 14 | + rewrote recipe to support the python bindings (cv2.so) and enable the |
| 15 | + build of most of the libraries of the opencv's package, so we can |
| 16 | + process images, videos, objects, photos... |
| 17 | + ''' |
12 | 18 | version = '4.0.1'
|
13 | 19 | url = 'https://github.com/opencv/opencv/archive/{version}.zip'
|
14 | 20 | depends = ['numpy']
|
| 21 | + patches = ['patches/p4a_build.patch'] |
| 22 | + generated_libraries = [ |
| 23 | + 'libopencv_features2d.so', |
| 24 | + 'libopencv_imgproc.so', |
| 25 | + 'libopencv_stitching.so', |
| 26 | + 'libopencv_calib3d.so', |
| 27 | + 'libopencv_flann.so', |
| 28 | + 'libopencv_ml.so', |
| 29 | + 'libopencv_videoio.so', |
| 30 | + 'libopencv_core.so', |
| 31 | + 'libopencv_highgui.so', |
| 32 | + 'libopencv_objdetect.so', |
| 33 | + 'libopencv_video.so', |
| 34 | + 'libopencv_dnn.so', |
| 35 | + 'libopencv_imgcodecs.so', |
| 36 | + 'libopencv_photo.so' |
| 37 | + ] |
| 38 | + |
| 39 | + def get_lib_dir(self, arch): |
| 40 | + return join(self.get_build_dir(arch.arch), 'build', 'lib', arch.arch) |
15 | 41 |
|
16 | 42 | def get_recipe_env(self, arch):
|
17 | 43 | env = super(OpenCVRecipe, self).get_recipe_env(arch)
|
18 | 44 | env['ANDROID_NDK'] = self.ctx.ndk_dir
|
19 | 45 | env['ANDROID_SDK'] = self.ctx.sdk_dir
|
20 | 46 | return env
|
21 | 47 |
|
22 |
| - def should_build(self, arch): |
23 |
| - return True |
24 |
| - |
25 | 48 | def build_arch(self, arch):
|
26 |
| - build_dir = os.path.join(self.get_build_dir(arch.arch), 'build') |
| 49 | + build_dir = join(self.get_build_dir(arch.arch), 'build') |
27 | 50 | shprint(sh.mkdir, '-p', build_dir)
|
28 | 51 | with current_directory(build_dir):
|
29 | 52 | env = self.get_recipe_env(arch)
|
| 53 | + |
| 54 | + python_major = self.ctx.python_recipe.version[0] |
| 55 | + python_include_root = self.ctx.python_recipe.include_root(arch.arch) |
| 56 | + python_site_packages = self.ctx.get_site_packages_dir() |
| 57 | + python_link_root = self.ctx.python_recipe.link_root(arch.arch) |
| 58 | + python_link_version = self.ctx.python_recipe.major_minor_version_string |
| 59 | + if 'python3' in self.ctx.python_recipe.name: |
| 60 | + python_link_version += 'm' |
| 61 | + python_library = join(python_link_root, |
| 62 | + 'libpython{}.so'.format(python_link_version)) |
| 63 | + python_include_numpy = join(python_site_packages, |
| 64 | + 'numpy', 'core', 'include') |
| 65 | + |
30 | 66 | shprint(sh.cmake,
|
| 67 | + '-DP4A=ON', |
31 | 68 | '-DANDROID_ABI={}'.format(arch.arch),
|
32 |
| - '-DCMAKE_TOOLCHAIN_FILE={}/build/cmake/android.toolchain.cmake'.format(self.ctx.ndk_dir), |
33 |
| - '-DPYTHON_NUMPY_INCLUDE_DIR={}/numpy/core/include'.format(self.ctx.get_site_packages_dir()), |
| 69 | + '-DANDROID_STANDALONE_TOOLCHAIN={}'.format(self.ctx.ndk_dir), |
| 70 | + '-DANDROID_NATIVE_API_LEVEL={}'.format(self.ctx.ndk_api), |
34 | 71 | '-DANDROID_EXECUTABLE={}/tools/android'.format(env['ANDROID_SDK']),
|
35 |
| - '-DBUILD_TESTS=OFF', '-DBUILD_PERF_TESTS=OFF', '-DENABLE_TESTING=OFF', |
36 |
| - '-DBUILD_EXAMPLES=OFF', '-DBUILD_ANDROID_EXAMPLES=OFF', |
37 |
| - '-DBUILD_opencv_imgproc=OFF', '-DBUILD_opencv_flann=OFF', |
38 |
| - '-DBUILD_opencv_python3=ON', |
| 72 | + |
| 73 | + '-DCMAKE_TOOLCHAIN_FILE={}'.format( |
| 74 | + join(self.ctx.ndk_dir, 'build', 'cmake', |
| 75 | + 'android.toolchain.cmake')), |
| 76 | + # Make the linkage with our python library, otherwise we |
| 77 | + # will get dlopen error when trying to import cv2's module. |
| 78 | + '-DCMAKE_SHARED_LINKER_FLAGS=-L{path} -lpython{version}'.format( |
| 79 | + path=python_link_root, |
| 80 | + version=python_link_version), |
| 81 | + |
39 | 82 | '-DBUILD_WITH_STANDALONE_TOOLCHAIN=ON',
|
40 |
| - '-DPYTHON_PACKAGES_PATH={}'.format(self.ctx.get_site_packages_dir()), |
41 |
| - '-DANDROID_STANDALONE_TOOLCHAIN={}'.format(self.ctx.ndk_dir), |
42 |
| - '-DANDROID_NATIVE_API_LEVEL={}'.format(self.ctx.android_api), |
| 83 | + # Force to build as shared libraries the cv2's dependant |
| 84 | + # libs or we will not be able to link with our python |
| 85 | + '-DBUILD_SHARED_LIBS=ON', |
| 86 | + '-DBUILD_STATIC_LIBS=OFF', |
| 87 | + |
| 88 | + # Disable some opencv's features |
| 89 | + '-DBUILD_opencv_java=OFF', |
| 90 | + '-DBUILD_opencv_java_bindings_generator=OFF', |
| 91 | + # '-DBUILD_opencv_highgui=OFF', |
| 92 | + # '-DBUILD_opencv_imgproc=OFF', |
| 93 | + # '-DBUILD_opencv_flann=OFF', |
| 94 | + '-DBUILD_TESTS=OFF', |
| 95 | + '-DBUILD_PERF_TESTS=OFF', |
| 96 | + '-DENABLE_TESTING=OFF', |
| 97 | + '-DBUILD_EXAMPLES=OFF', |
| 98 | + '-DBUILD_ANDROID_EXAMPLES=OFF', |
| 99 | + |
| 100 | + # Force to only build our version of python |
| 101 | + '-DBUILD_OPENCV_PYTHON{major}=ON'.format(major=python_major), |
| 102 | + '-DBUILD_OPENCV_PYTHON{major}=OFF'.format( |
| 103 | + major='2' if python_major == '3' else '3'), |
| 104 | + |
| 105 | + # Force to install the `cv2.so` library directly into |
| 106 | + # python's site packages (otherwise the cv2's loader fails |
| 107 | + # on finding the cv2.so library) |
| 108 | + '-DOPENCV_SKIP_PYTHON_LOADER=ON', |
| 109 | + '-DOPENCV_PYTHON{major}_INSTALL_PATH={site_packages}'.format( |
| 110 | + major=python_major, site_packages=python_site_packages), |
| 111 | + |
| 112 | + # Define python's paths for: exe, lib, includes, numpy... |
| 113 | + '-DPYTHON_DEFAULT_EXECUTABLE={}'.format(self.ctx.hostpython), |
| 114 | + '-DPYTHON{major}_EXECUTABLE={host_python}'.format( |
| 115 | + major=python_major, host_python=self.ctx.hostpython), |
| 116 | + '-DPYTHON{major}_INCLUDE_PATH={include_path}'.format( |
| 117 | + major=python_major, include_path=python_include_root), |
| 118 | + '-DPYTHON{major}_LIBRARIES={python_lib}'.format( |
| 119 | + major=python_major, python_lib=python_library), |
| 120 | + '-DPYTHON{major}_NUMPY_INCLUDE_DIRS={numpy_include}'.format( |
| 121 | + major=python_major, numpy_include=python_include_numpy), |
| 122 | + '-DPYTHON{major}_PACKAGES_PATH={site_packages}'.format( |
| 123 | + major=python_major, site_packages=python_site_packages), |
| 124 | + |
43 | 125 | self.get_build_dir(arch.arch),
|
44 | 126 | _env=env)
|
45 |
| - shprint(sh.make, '-j', str(cpu_count())) |
| 127 | + shprint(sh.make, '-j' + str(cpu_count()), 'opencv_python' + python_major) |
| 128 | + # Install python bindings (cv2.so) |
46 | 129 | shprint(sh.cmake, '-DCOMPONENT=python', '-P', './cmake_install.cmake')
|
47 |
| - sh.cp('-a', sh.glob('./lib/{}/lib*.a'.format(arch.arch)), self.ctx.get_libs_dir(arch.arch)) |
48 |
| - self.ctx.get_libs_dir(arch.arch) |
| 130 | + # Copy third party shared libs that we need in our final apk |
| 131 | + sh.cp('-a', sh.glob('./lib/{}/lib*.so'.format(arch.arch)), |
| 132 | + self.ctx.get_libs_dir(arch.arch)) |
49 | 133 |
|
50 | 134 |
|
51 | 135 | recipe = OpenCVRecipe()
|
0 commit comments