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

kivy / python-for-android / 18811993594

26 Oct 2025 02:55AM UTC coverage: 58.913% (+0.1%) from 58.803%
18811993594

Pull #3242

github

web-flow
Merge 1adc8ca94 into 7593f9d62
Pull Request #3242: Update to Python 3.14, remove distutils

1079 of 2442 branches covered (44.19%)

Branch coverage included in aggregate %.

13 of 16 new or added lines in 8 files covered. (81.25%)

103 existing lines in 6 files now uncovered.

5048 of 7958 relevant lines covered (63.43%)

5.06 hits per line

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

65.28
/pythonforandroid/recipes/freetype/__init__.py
1
from pythonforandroid.recipe import Recipe
8✔
2
from pythonforandroid.logger import shprint, info
8✔
3
from pythonforandroid.util import current_directory
8✔
4
from os.path import join, exists
8✔
5
from multiprocessing import cpu_count
8✔
6
import sh
8✔
7

8

9
class FreetypeRecipe(Recipe):
8✔
10
    """The freetype library it's special, because has cyclic dependencies with
11
    harfbuzz library, so freetype can be build with harfbuzz support, and
12
    harfbuzz can be build with freetype support. This complicates the build of
13
    both recipes because in order to get the full set we need to compile those
14
    recipes several times:
15
        - build freetype without harfbuzz
16
        - build harfbuzz with freetype
17
        - build freetype with harfbuzz support
18

19
    .. note::
20
        To build freetype with harfbuzz support you must add `harfbuzz` to your
21
        requirements, otherwise freetype will be build without harfbuzz
22

23
    .. seealso::
24
        https://sourceforge.net/projects/freetype/files/freetype2/2.5.3/
25
    """
26

27
    version = '2.14.1'
8✔
28
    url = 'https://download.savannah.gnu.org/releases/freetype/freetype-{version}.tar.gz'  # noqa
8✔
29
    built_libraries = {'libfreetype.so': 'objs/.libs'}
8✔
30

31
    def get_recipe_env(self, arch=None, with_harfbuzz=False):
8✔
32
        env = super().get_recipe_env(arch)
8✔
33
        if with_harfbuzz:
8!
34
            harfbuzz_build = self.get_recipe(
×
35
                'harfbuzz', self.ctx
36
            ).get_build_dir(arch.arch)
37
            freetype_install = join(self.get_build_dir(arch.arch), 'install')
×
38

39
            env['HARFBUZZ_CFLAGS'] = '-I{harfbuzz} -I{harfbuzz}/src'.format(
×
40
                harfbuzz=harfbuzz_build
41
            )
42
            env['HARFBUZZ_LIBS'] = (
×
43
                '-L{freetype}/lib -lfreetype '
44
                '-L{harfbuzz}/src/.libs -lharfbuzz'.format(
45
                    freetype=freetype_install, harfbuzz=harfbuzz_build
46
                )
47
            )
48

49
        # android's zlib support
50
        zlib_lib_path = arch.ndk_lib_dir_versioned
8✔
51
        zlib_includes = self.ctx.ndk.sysroot_include_dir
8✔
52

53
        def add_flag_if_not_added(flag, env_key):
8✔
54
            if flag not in env[env_key]:
8!
55
                env[env_key] += flag
8✔
56

57
        add_flag_if_not_added(' -I' + zlib_includes, 'CFLAGS')
8✔
58
        add_flag_if_not_added(' -L' + zlib_lib_path, 'LDFLAGS')
8✔
59
        add_flag_if_not_added(' -lz', 'LDLIBS')
8✔
60

61
        return env
8✔
62

63
    def build_arch(self, arch, with_harfbuzz=False):
8✔
64
        env = self.get_recipe_env(arch, with_harfbuzz=with_harfbuzz)
8✔
65

66
        harfbuzz_in_recipes = 'harfbuzz' in self.ctx.recipe_build_order
8✔
67
        prefix_path = self.get_build_dir(arch.arch)
8✔
68
        if harfbuzz_in_recipes and not with_harfbuzz:
8!
69
            # This is the first time we build freetype and we modify `prefix`,
70
            # because we will install the compiled library so later we can
71
            # build harfbuzz (with freetype support) using this freetype
72
            # installation
73
            prefix_path = join(prefix_path, 'install')
×
74

75
        # Configure freetype library
76
        config_args = {
8✔
77
            '--host={}'.format(arch.command_prefix),
78
            '--prefix={}'.format(prefix_path),
79
            '--without-bzip2',
80
            '--with-png=no',
81
        }
82
        if not harfbuzz_in_recipes:
8!
83
            info('Build freetype (without harfbuzz)')
8✔
84
            config_args = config_args.union(
8✔
85
                {'--disable-static',
86
                 '--enable-shared',
87
                 '--with-harfbuzz=no',
88
                 '--with-zlib=yes',
89
                 }
90
            )
UNCOV
91
        elif not with_harfbuzz:
×
92
            info('Build freetype for First time (without harfbuzz)')
×
93
            # This time we will build our freetype library as static because we
94
            # want that the harfbuzz library to have the necessary freetype
95
            # symbols/functions, so we avoid to have two freetype shared
96
            # libraries which will be confusing and harder to link with them
UNCOV
97
            config_args = config_args.union(
×
98
                {'--disable-shared', '--with-harfbuzz=no', '--with-zlib=no'}
99
            )
100
        else:
UNCOV
101
            info('Build freetype for Second time (with harfbuzz)')
×
102
            config_args = config_args.union(
×
103
                {'--disable-static',
104
                 '--enable-shared',
105
                 '--with-harfbuzz=yes',
106
                 '--with-zlib=yes',
107
                 }
108
            )
109
        info('Configure args are:\n\t-{}'.format('\n\t-'.join(config_args)))
8✔
110

111
        # Build freetype library
112
        with current_directory(self.get_build_dir(arch.arch)):
8✔
113
            configure = sh.Command('./configure')
8✔
114
            shprint(configure, *config_args, _env=env)
8✔
115
            shprint(sh.make, '-j', str(cpu_count()), _env=env)
8✔
116

117
            if not with_harfbuzz and harfbuzz_in_recipes:
8!
UNCOV
118
                info('Installing freetype (first time build without harfbuzz)')
×
119
                # First build, install the compiled lib, and clean build env
UNCOV
120
                shprint(sh.make, 'install', _env=env)
×
121
                shprint(sh.make, 'distclean', _env=env)
×
122

123
    def install_libraries(self, arch):
8✔
124
        # This library it's special because the first time we built it may not
125
        # generate the expected library, because it can depend on harfbuzz, so
126
        # we will make sure to only install it when the library exists
UNCOV
127
        if not exists(list(self.get_libraries(arch))[0]):
×
128
            return
×
129
        self.install_libs(arch, *self.get_libraries(arch))
×
130

131

132
recipe = FreetypeRecipe()
8✔
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