Skip to content

Rework of freetype/harfbuzz recipes #1825

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 101 additions & 25 deletions pythonforandroid/recipes/freetype/__init__.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,120 @@
from pythonforandroid.toolchain import Recipe
from pythonforandroid.logger import shprint, info
from pythonforandroid.util import current_directory
from pythonforandroid.logger import shprint
from os.path import exists, join, realpath
from os.path import exists, join
from multiprocessing import cpu_count
import sh


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

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

.. seealso::
https://sourceforge.net/projects/freetype/files/freetype2/2.5.3/
"""

version = '2.5.5'
url = 'http://download.savannah.gnu.org/releases/freetype/freetype-{version}.tar.gz' # noqa

depends = ['harfbuzz']

def should_build(self, arch):
if exists(join(self.get_build_dir(arch.arch),
'objs', '.libs', 'libfreetype.a')):
return False
return True
return not exists(
join(
self.get_build_dir(arch.arch),
'objs',
'.libs',
'libfreetype.so',
)
)

def get_recipe_env(self, arch=None, with_harfbuzz=False):
env = super(FreetypeRecipe, self).get_recipe_env(arch)
if with_harfbuzz:
harfbuzz_build = self.get_recipe(
'harfbuzz', self.ctx
).get_build_dir(arch.arch)
freetype_install = join(self.get_build_dir(arch.arch), 'install')
env['CFLAGS'] = ' '.join(
[env['CFLAGS'], '-DFT_CONFIG_OPTION_USE_HARFBUZZ']
)

def build_arch(self, arch):
env = self.get_recipe_env(arch)
env['HARFBUZZ_CFLAGS'] = '-I{harfbuzz} -I{harfbuzz}/src'.format(
harfbuzz=harfbuzz_build
)
env['HARFBUZZ_LIBS'] = (
'-L{freetype}/lib -lfreetype '
'-L{harfbuzz}/src/.libs -lharfbuzz'.format(
freetype=freetype_install, harfbuzz=harfbuzz_build
)
)
return env

harfbuzz_recipe = Recipe.get_recipe('harfbuzz', self.ctx)
env['LDFLAGS'] = ' '.join(
[env['LDFLAGS'],
'-L{}'.format(join(harfbuzz_recipe.get_build_dir(arch.arch),
'src', '.libs'))])
def build_arch(self, arch, with_harfbuzz=False):
env = self.get_recipe_env(arch, with_harfbuzz=with_harfbuzz)

harfbuzz_in_recipes = 'harfbuzz' in self.ctx.recipe_build_order
prefix_path = self.get_build_dir(arch.arch)
if harfbuzz_in_recipes and not with_harfbuzz:
# This is the first time we build freetype and we modify `prefix`,
# because we will install the compiled library so later we can
# build harfbuzz (with freetype support) using this freetype
# installation
prefix_path = join(prefix_path, 'install')

# Configure freetype library
config_args = {
'--host={}'.format(arch.command_prefix),
'--prefix={}'.format(prefix_path),
'--without-zlib',
'--with-png=no',
}
if not harfbuzz_in_recipes:
info('Build freetype (without harfbuzz)')
config_args = config_args.union(
{'--disable-static', '--enable-shared', '--with-harfbuzz=no'}
)
elif not with_harfbuzz:
info('Build freetype for First time (without harfbuzz)')
# This time we will build our freetype library as static because we
# want that the harfbuzz library to have the necessary freetype
# symbols/functions, so we avoid to have two freetype shared
# libraries which will be confusing and harder to link with them
config_args = config_args.union(
{'--disable-shared', '--with-harfbuzz=no'}
)
else:
info('Build freetype for Second time (with harfbuzz)')
config_args = config_args.union(
{'--disable-static', '--enable-shared', '--with-harfbuzz=yes'}
)
info('Configure args are:\n\t-{}'.format('\n\t-'.join(config_args)))

# Build freetype library
with current_directory(self.get_build_dir(arch.arch)):
configure = sh.Command('./configure')
shprint(configure,
'--host=arm-linux-androideabi',
'--prefix={}'.format(realpath('.')),
'--without-zlib',
'--with-png=no',
'--disable-shared',
_env=env)
shprint(sh.make, '-j5', _env=env)

shprint(sh.cp, 'objs/.libs/libfreetype.a', self.ctx.libs_dir)
shprint(configure, *config_args, _env=env)
shprint(sh.make, '-j', str(cpu_count()), _env=env)

if not with_harfbuzz and harfbuzz_in_recipes:
info('Installing freetype (first time build without harfbuzz)')
# First build, install the compiled lib, and clean build env
shprint(sh.make, 'install', _env=env)
shprint(sh.make, 'distclean', _env=env)
else:
# Second build (or the first if harfbuzz not enabled), now we
# copy definitive libs to libs collection. Be sure to link your
# recipes to the definitive library, located at: objs/.libs
self.install_libs(arch, 'objs/.libs/libfreetype.so')


recipe = FreetypeRecipe()
76 changes: 58 additions & 18 deletions pythonforandroid/recipes/harfbuzz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,79 @@
from pythonforandroid.toolchain import Recipe
from pythonforandroid.util import current_directory
from pythonforandroid.logger import shprint
from multiprocessing import cpu_count
from os.path import exists, join
import sh


class HarfbuzzRecipe(Recipe):
"""The harfbuzz library it's special, because has cyclic dependencies with
freetype library, so freetype can be build with harfbuzz support, and
harfbuzz can be build with freetype support. This complicates the build of
both recipes because in order to get the full set we need to compile those
recipes several times:
- build freetype without harfbuzz
- build harfbuzz with freetype
- build freetype with harfbuzz support

.. seealso::
https://sourceforge.net/projects/freetype/files/freetype2/2.5.3/
"""

version = '0.9.40'
url = 'http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-{version}.tar.bz2' # noqa
opt_depends = ['freetype']

def should_build(self, arch):
if exists(join(self.get_build_dir(arch.arch),
'src', '.libs', 'libharfbuzz.a')):
return False
return True
return not exists(
join(
self.get_build_dir(arch.arch), 'src', '.libs', 'libharfbuzz.so'
)
)

def get_recipe_env(self, arch=None):
env = super(HarfbuzzRecipe, self).get_recipe_env(arch)
if 'freetype' in self.ctx.recipe_build_order:
freetype = self.get_recipe('freetype', self.ctx)
freetype_install = join(
freetype.get_build_dir(arch.arch), 'install'
)
# Explicitly tell harfbuzz's configure script that we want to
# use our freetype library or it won't be correctly detected
env['FREETYPE_CFLAGS'] = '-I{}/include/freetype2'.format(
freetype_install
)
env['FREETYPE_LIBS'] = ' '.join(
['-L{}/lib'.format(freetype_install), '-lfreetype']
)
return env

def build_arch(self, arch):

env = self.get_recipe_env(arch)
env['LDFLAGS'] = env['LDFLAGS'] + ' -L{}'.format(
self.ctx.get_libs_dir(arch.arch) +
'-L{}'.format(self.ctx.libs_dir))

with current_directory(self.get_build_dir(arch.arch)):
configure = sh.Command('./configure')
shprint(configure, '--without-icu', '--host=arm-linux=androideabi',
'--prefix={}'.format(
join(self.ctx.build_dir, 'python-install')),
'--without-freetype',
'--without-glib',
'--disable-shared',
_env=env)
shprint(sh.make, '-j5', _env=env)

shprint(sh.cp, '-L', join('src', '.libs', 'libharfbuzz.a'),
self.ctx.libs_dir)
shprint(
configure,
'--without-icu',
'--host={}'.format(arch.command_prefix),
'--prefix={}'.format(self.get_build_dir(arch.arch)),
'--with-freetype={}'.format(
'yes'
if 'freetype' in self.ctx.recipe_build_order
else 'no'
),
'--without-glib',
_env=env,
)
shprint(sh.make, '-j', str(cpu_count()), _env=env)
self.install_libs(arch, join('src', '.libs', 'libharfbuzz.so'))

if 'freetype' in self.ctx.recipe_build_order:
# Rebuild freetype with harfbuzz support
freetype = self.get_recipe('freetype', self.ctx)
freetype.build_arch(arch, with_harfbuzz=True)


recipe = HarfbuzzRecipe()