• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kivy / python-for-android / 17897834877

21 Sep 2025 07:12PM UTC coverage: 59.104% (-0.06%) from 59.168%
17897834877

Pull #3218

github

web-flow
Merge 2fd6f02d6 into 17e16d46d
Pull Request #3218: `opencv`: fix build

1060 of 2389 branches covered (44.37%)

Branch coverage included in aggregate %.

1 of 12 new or added lines in 1 file covered. (8.33%)

4 existing lines in 1 file now uncovered.

4958 of 7793 relevant lines covered (63.62%)

2.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

29.09
/pythonforandroid/recipes/opencv/__init__.py
1
from multiprocessing import cpu_count
4✔
2
from os.path import join
4✔
3

4
import sh
4✔
5

6
from pythonforandroid.logger import shprint
4✔
7
from pythonforandroid.recipe import NDKRecipe
4✔
8
from pythonforandroid.util import current_directory, ensure_dir
4✔
9

10

11
class OpenCVRecipe(NDKRecipe):
4✔
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
    '''
18
    version = '4.12.0'
4✔
19
    url = 'https://github.com/opencv/opencv/archive/{version}.zip'
4✔
20
    depends = ['numpy']
4✔
21
    patches = ['patches/p4a_build.patch']
4✔
22
    generated_libraries = [
4✔
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):
4✔
40
        return join(self.get_build_dir(arch.arch), 'build', 'lib', arch.arch)
×
41

42
    def get_recipe_env(self, arch):
4✔
43
        env = super().get_recipe_env(arch)
×
44
        env['ANDROID_NDK'] = self.ctx.ndk_dir
×
45
        env['ANDROID_SDK'] = self.ctx.sdk_dir
×
46
        return env
×
47

48
    def build_arch(self, arch):
4✔
49
        build_dir = join(self.get_build_dir(arch.arch), 'build')
×
50
        ensure_dir(build_dir)
×
51

52
        opencv_extras = []
×
53
        if 'opencv_extras' in self.ctx.recipe_build_order:
×
54
            opencv_extras_dir = self.get_recipe(
×
55
                'opencv_extras', self.ctx).get_build_dir(arch.arch)
56
            opencv_extras = [
×
57
                f'-DOPENCV_EXTRA_MODULES_PATH={opencv_extras_dir}/modules',
58
                '-DBUILD_opencv_legacy=OFF',
59
            ]
60

61
        with current_directory(build_dir):
×
62
            env = self.get_recipe_env(arch)
×
63

64
            python_major = self.ctx.python_recipe.version[0]
×
65
            python_include_root = self.ctx.python_recipe.include_root(arch.arch)
×
66
            python_site_packages = self.ctx.get_site_packages_dir(arch)
×
67
            python_link_root = self.ctx.python_recipe.link_root(arch.arch)
×
68
            python_link_version = self.ctx.python_recipe.link_version
×
69
            python_library = join(python_link_root,
×
70
                                  'libpython{}.so'.format(python_link_version))
NEW
71
            python_include_numpy = join(
×
72
                self.ctx.get_python_install_dir(arch.arch), "numpy/_core/include",
73
            )
74

75
            shprint(sh.cmake,
×
76
                    '-DP4A=ON',
77
                    '-DANDROID_ABI={}'.format(arch.arch),
78
                    '-DANDROID_STANDALONE_TOOLCHAIN={}'.format(self.ctx.ndk_dir),
79
                    '-DANDROID_NATIVE_API_LEVEL={}'.format(self.ctx.ndk_api),
80
                    '-DANDROID_EXECUTABLE={}/tools/android'.format(env['ANDROID_SDK']),
81
                    '-DANDROID_SDK_TOOLS_VERSION=6514223',
82
                    '-DANDROID_PROJECTS_SUPPORT_GRADLE=ON',
83

84
                    '-DCMAKE_TOOLCHAIN_FILE={}'.format(
85
                        join(self.ctx.ndk_dir, 'build', 'cmake',
86
                             'android.toolchain.cmake')),
87
                    # Make the linkage with our python library, otherwise we
88
                    # will get dlopen error when trying to import cv2's module.
89
                    '-DCMAKE_SHARED_LINKER_FLAGS=-L{path} -lpython{version}'.format(
90
                        path=python_link_root,
91
                        version=python_link_version),
92

93
                    '-DBUILD_WITH_STANDALONE_TOOLCHAIN=ON',
94
                    # Force to build as shared libraries the cv2's dependent
95
                    # libs or we will not be able to link with our python
96
                    '-DBUILD_SHARED_LIBS=ON',
97
                    '-DBUILD_STATIC_LIBS=OFF',
98

99
                    # Disable some opencv's features
100
                    '-DBUILD_opencv_java=OFF',
101
                    '-DBUILD_opencv_java_bindings_generator=OFF',
102
                    # '-DBUILD_opencv_highgui=OFF',
103
                    # '-DBUILD_opencv_imgproc=OFF',
104
                    # '-DBUILD_opencv_flann=OFF',
105
                    '-DBUILD_TESTS=OFF',
106
                    '-DBUILD_PERF_TESTS=OFF',
107
                    '-DENABLE_TESTING=OFF',
108
                    '-DBUILD_EXAMPLES=OFF',
109
                    '-DBUILD_ANDROID_EXAMPLES=OFF',
110

111
                    # Force to only build our version of python
112
                    '-DBUILD_OPENCV_PYTHON{major}=ON'.format(major=python_major),
113
                    '-DBUILD_OPENCV_PYTHON{major}=OFF'.format(
114
                        major='2' if python_major == '3' else '3'),
115

116
                    # Force to install the `cv2.so` library directly into
117
                    # python's site packages (otherwise the cv2's loader fails
118
                    # on finding the cv2.so library)
119
                    '-DOPENCV_SKIP_PYTHON_LOADER=ON',
120
                    '-DOPENCV_PYTHON{major}_INSTALL_PATH={site_packages}'.format(
121
                        major=python_major, site_packages=python_site_packages),
122

123
                    # Define python's paths for: exe, lib, includes, numpy...
124
                    '-DPYTHON_DEFAULT_EXECUTABLE={}'.format(self.ctx.hostpython),
125
                    '-DPYTHON{major}_EXECUTABLE={host_python}'.format(
126
                        major=python_major, host_python=self.ctx.hostpython),
127
                    '-DPYTHON{major}_INCLUDE_PATH={include_path}'.format(
128
                        major=python_major, include_path=python_include_root),
129
                    '-DPYTHON{major}_LIBRARIES={python_lib}'.format(
130
                        major=python_major, python_lib=python_library),
131
                    '-DPYTHON{major}_NUMPY_INCLUDE_DIRS={numpy_include}'.format(
132
                        major=python_major, numpy_include=python_include_numpy),
133
                    '-DPYTHON{major}_PACKAGES_PATH={site_packages}'.format(
134
                        major=python_major, site_packages=python_site_packages),
135

136
                    *opencv_extras,
137

138
                    self.get_build_dir(arch.arch),
139
                    _env=env)
140

NEW
141
            try:
×
NEW
142
                shprint(sh.make, '-j' + str(cpu_count()), 'VERBOSE=1', 'opencv_python' + python_major)
×
NEW
143
            except Exception:
×
144
                # Patch link.txt and retry
NEW
145
                link_txt = 'modules/python3/CMakeFiles/opencv_python3.dir/link.txt'
×
NEW
146
                with open(link_txt, 'r+') as f:
×
NEW
147
                    content = f.read().replace('-version', '--version')
×
NEW
148
                    f.seek(0)
×
NEW
UNCOV
149
                    f.write(content)
×
NEW
UNCOV
150
                    f.truncate()
×
NEW
151
                shprint(sh.make, '-j' + str(cpu_count()), 'opencv_python' + python_major)
×
152

153
            # Install python bindings (cv2.so)
UNCOV
154
            shprint(sh.cmake, '-DCOMPONENT=python', '-P', './cmake_install.cmake')
×
155
            # Copy third party shared libs that we need in our final apk
UNCOV
156
            sh.cp('-a', sh.glob('./lib/{}/lib*.so'.format(arch.arch)),
×
157
                  self.ctx.get_libs_dir(arch.arch))
158

159

160
recipe = OpenCVRecipe()
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc