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

kivy / python-for-android / 15970879696

30 Jun 2025 10:49AM UTC coverage: 59.171%. Remained the same
15970879696

Pull #3167

github

web-flow
Merge d06eae9ee into be3de2e28
Pull Request #3167: Update broadcast.py

1054 of 2377 branches covered (44.34%)

Branch coverage included in aggregate %.

4956 of 7780 relevant lines covered (63.7%)

2.54 hits per line

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

23.81
/pythonforandroid/recipes/protobuf_cpp/__init__.py
1
from multiprocessing import cpu_count
4✔
2
import os
4✔
3
from os.path import exists, join
4✔
4
from pythonforandroid.toolchain import info
4✔
5
import sh
4✔
6
import sys
4✔
7

8
from pythonforandroid.recipe import CppCompiledComponentsPythonRecipe
4✔
9
from pythonforandroid.logger import shprint, info_notify
4✔
10
from pythonforandroid.util import current_directory, touch
4✔
11

12

13
class ProtobufCppRecipe(CppCompiledComponentsPythonRecipe):
4✔
14
    """This is a two-in-one recipe:
15
      - build labraru `libprotobuf.so`
16
      - build and install python binding for protobuf_cpp
17
    """
18
    name = 'protobuf_cpp'
4✔
19
    version = '3.6.1'
4✔
20
    url = 'https://github.com/google/protobuf/releases/download/v{version}/protobuf-python-{version}.tar.gz'
4✔
21
    call_hostpython_via_targetpython = False
4✔
22
    depends = ['cffi', 'setuptools']
4✔
23
    site_packages_name = 'google/protobuf/pyext'
4✔
24
    setup_extra_args = ['--cpp_implementation']
4✔
25
    built_libraries = {'libprotobuf.so': 'src/.libs'}
4✔
26
    protoc_dir = None
4✔
27

28
    def prebuild_arch(self, arch):
4✔
29
        super().prebuild_arch(arch)
×
30

31
        patch_mark = join(self.get_build_dir(arch.arch), '.protobuf-patched')
×
32
        if self.ctx.python_recipe.name == 'python3' and not exists(patch_mark):
×
33
            self.apply_patch('fix-python3-compatibility.patch', arch.arch)
×
34
            touch(patch_mark)
×
35

36
        # During building, host needs to transpile .proto files to .py
37
        # ideally with the same version as protobuf runtime, or with an older one.
38
        # Because protoc is compiled for target (i.e. Android), we need an other binary
39
        # which can be run by host.
40
        # To make it easier, we download prebuild protoc binary adapted to the platform
41

42
        info_notify("Downloading protoc compiler for your platform")
×
43
        url_prefix = "https://github.com/protocolbuffers/protobuf/releases/download/v{version}".format(version=self.version)
×
44
        if sys.platform.startswith('linux'):
×
45
            info_notify("GNU/Linux detected")
×
46
            filename = "protoc-{version}-linux-x86_64.zip".format(version=self.version)
×
47
        elif sys.platform.startswith('darwin'):
×
48
            info_notify("Mac OS X detected")
×
49
            filename = "protoc-{version}-osx-x86_64.zip".format(version=self.version)
×
50
        else:
51
            info_notify("Your platform is not supported, but recipe can still "
×
52
                        "be built if you have a valid protoc (<={version}) in "
53
                        "your path".format(version=self.version))
54
            return
×
55

56
        protoc_url = join(url_prefix, filename)
×
57
        self.protoc_dir = join(self.ctx.build_dir, "tools", "protoc")
×
58
        if os.path.exists(join(self.protoc_dir, "bin", "protoc")):
×
59
            info_notify("protoc found, no download needed")
×
60
            return
×
61
        try:
×
62
            os.makedirs(self.protoc_dir)
×
63
        except OSError as e:
×
64
            # if dir already exists (errno 17), we ignore the error
65
            if e.errno != 17:
×
66
                raise e
×
67
        info_notify("Will download into {dest_dir}".format(dest_dir=self.protoc_dir))
×
68
        self.download_file(protoc_url, join(self.protoc_dir, filename))
×
69
        with current_directory(self.protoc_dir):
×
70
            shprint(sh.unzip, join(self.protoc_dir, filename))
×
71

72
    def build_arch(self, arch):
4✔
73
        env = self.get_recipe_env(arch)
×
74

75
        # Build libproto.so
76
        with current_directory(self.get_build_dir(arch.arch)):
×
77
            build_arch = (
×
78
                shprint(sh.gcc, '-dumpmachine')
79
                .stdout.decode('utf-8')
80
                .split('\n')[0]
81
            )
82

83
            if not exists('configure'):
×
84
                shprint(sh.Command('./autogen.sh'), _env=env)
×
85

86
            shprint(sh.Command('./configure'),
×
87
                    '--build={}'.format(build_arch),
88
                    '--host={}'.format(arch.command_prefix),
89
                    '--target={}'.format(arch.command_prefix),
90
                    '--disable-static',
91
                    '--enable-shared',
92
                    _env=env)
93

94
            with current_directory(join(self.get_build_dir(arch.arch), 'src')):
×
95
                shprint(sh.make, 'libprotobuf.la', '-j'+str(cpu_count()), _env=env)
×
96

97
        self.install_python_package(arch)
×
98

99
    def build_compiled_components(self, arch):
4✔
100
        # Build python bindings and _message.so
101
        env = self.get_recipe_env(arch)
×
102
        with current_directory(join(self.get_build_dir(arch.arch), 'python')):
×
103
            hostpython = sh.Command(self.hostpython_location)
×
104
            shprint(hostpython,
×
105
                    'setup.py',
106
                    'build_ext',
107
                    _env=env, *self.setup_extra_args)
108

109
    def install_python_package(self, arch):
4✔
110
        env = self.get_recipe_env(arch)
×
111

112
        info('Installing {} into site-packages'.format(self.name))
×
113

114
        with current_directory(join(self.get_build_dir(arch.arch), 'python')):
×
115
            hostpython = sh.Command(self.hostpython_location)
×
116

117
            hpenv = env.copy()
×
118
            shprint(hostpython, 'setup.py', 'install', '-O2',
×
119
                    '--root={}'.format(self.ctx.get_python_install_dir(arch.arch)),
120
                    '--install-lib=.',
121
                    _env=hpenv, *self.setup_extra_args)
122

123
        # Create __init__.py which is missing, see also:
124
        #   - https://github.com/protocolbuffers/protobuf/issues/1296
125
        #   - https://stackoverflow.com/questions/13862562/
126
        #   google-protocol-buffers-not-found-when-trying-to-freeze-python-app
127
        open(
×
128
            join(self.ctx.get_site_packages_dir(arch), 'google', '__init__.py'),
129
            'a',
130
        ).close()
131

132
    def get_recipe_env(self, arch):
4✔
133
        env = super().get_recipe_env(arch)
×
134
        if self.protoc_dir is not None:
×
135
            # we need protoc with binary for host platform
136
            env['PROTOC'] = join(self.protoc_dir, 'bin', 'protoc')
×
137
        env['TARGET_OS'] = 'OS_ANDROID_CROSSCOMPILE'
×
138
        env['CXXFLAGS'] += ' -std=c++11'
×
139
        env['LDFLAGS'] += ' -lm -landroid -llog'
×
140
        return env
×
141

142

143
recipe = ProtobufCppRecipe()
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

© 2025 Coveralls, Inc