Skip to content

Commit 3ecbe4d

Browse files
authored
Merge pull request kivy#1661 from opacam/opencv-cv2-and-extras
Rework opencv's recipe (enable cv2.so and the extra opencv libraries)
2 parents 78645ea + dd28a0b commit 3ecbe4d

File tree

3 files changed

+142
-17
lines changed

3 files changed

+142
-17
lines changed

ci/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class TargetPython(Enum):
4444
'pyleveldb',
4545
'pynacl',
4646
'doubleratchet',
47+
# The opencv recipe fails to pass travis tests due to the long processing
48+
# when building it and the lack of console output, so, it's only broken
49+
# for travis, see: https://github.com/kivy/python-for-android/pull/1661
50+
'opencv',
4751
'omemo',
4852
# requires `libpq-dev` system dependency e.g. for `pg_config` binary
4953
'psycopg2',
@@ -77,6 +81,10 @@ class TargetPython(Enum):
7781
'icu',
7882
# https://github.com/kivy/python-for-android/issues/1354
7983
'kivent_core', 'kivent_cymunk', 'kivent_particles', 'kivent_polygen',
84+
# The opencv recipe fails to pass travis tests due to the long processing
85+
# when building it and the lack of console output, so, it's only broken
86+
# for travis, see: https://github.com/kivy/python-for-android/pull/1661
87+
'opencv',
8088
# requires `libpq-dev` system dependency e.g. for `pg_config` binary
8189
'psycopg2',
8290
# fatal error: crypt.h: No such file or directory
Lines changed: 101 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os
1+
from os.path import join
22
import sh
33
from pythonforandroid.recipe import NDKRecipe
44
from pythonforandroid.toolchain import (
@@ -9,43 +9,127 @@
99

1010

1111
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+
'''
1218
version = '4.0.1'
1319
url = 'https://github.com/opencv/opencv/archive/{version}.zip'
1420
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)
1541

1642
def get_recipe_env(self, arch):
1743
env = super(OpenCVRecipe, self).get_recipe_env(arch)
1844
env['ANDROID_NDK'] = self.ctx.ndk_dir
1945
env['ANDROID_SDK'] = self.ctx.sdk_dir
2046
return env
2147

22-
def should_build(self, arch):
23-
return True
24-
2548
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')
2750
shprint(sh.mkdir, '-p', build_dir)
2851
with current_directory(build_dir):
2952
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+
3066
shprint(sh.cmake,
67+
'-DP4A=ON',
3168
'-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),
3471
'-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+
3982
'-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+
43125
self.get_build_dir(arch.arch),
44126
_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)
46129
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))
49133

50134

51135
recipe = OpenCVRecipe()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
This patch allow that the opencv's build command correctly detects our version
2+
of python, so we can successfully build the python bindings (cv2.so)
3+
--- opencv-4.0.1/cmake/OpenCVDetectPython.cmake.orig 2018-12-22 08:03:30.000000000 +0100
4+
+++ opencv-4.0.1/cmake/OpenCVDetectPython.cmake 2019-01-31 11:33:10.896502978 +0100
5+
@@ -175,7 +175,7 @@ if(NOT ${found})
6+
endif()
7+
endif()
8+
9+
- if(NOT ANDROID AND NOT IOS)
10+
+ if(P4A OR NOT ANDROID AND NOT IOS)
11+
if(CMAKE_HOST_UNIX)
12+
execute_process(COMMAND ${_executable} -c "from distutils.sysconfig import *; print(get_python_lib())"
13+
RESULT_VARIABLE _cvpy_process
14+
@@ -244,7 +244,7 @@ if(NOT ${found})
15+
OUTPUT_STRIP_TRAILING_WHITESPACE)
16+
endif()
17+
endif()
18+
- endif(NOT ANDROID AND NOT IOS)
19+
+ endif(P4A OR NOT ANDROID AND NOT IOS)
20+
endif()
21+
22+
# Export return values
23+
--- opencv-4.0.1/modules/python/CMakeLists.txt.orig 2018-12-22 08:03:30.000000000 +0100
24+
+++ opencv-4.0.1/modules/python/CMakeLists.txt 2019-01-31 11:47:17.100494908 +0100
25+
@@ -3,7 +3,7 @@
26+
# ----------------------------------------------------------------------------
27+
if(DEFINED OPENCV_INITIAL_PASS) # OpenCV build
28+
29+
-if(ANDROID OR APPLE_FRAMEWORK OR WINRT)
30+
+if(ANDROID AND NOT P4A OR APPLE_FRAMEWORK OR WINRT)
31+
ocv_module_disable_(python2)
32+
ocv_module_disable_(python3)
33+
return()

0 commit comments

Comments
 (0)