Skip to content

[LIBS - PART I] Initial refactor of library recipes #1944

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 24 commits into from
Aug 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
72aef93
[recipe-lib] Add attribute Recipe.built_libraries
opacam Jul 26, 2019
f7aeb75
[recipe-lib] Add method Recipe.get_libraries
opacam Jul 26, 2019
c62813e
[recipe-lib] Make `Recipe.should_build` decide the library build
opacam Jul 26, 2019
47cba1b
[recipe-lib] Add method `Recipe.install_libraries`
opacam Jul 26, 2019
b7bf34a
[recipe-lib] Make libffi a library recipe
opacam Jul 26, 2019
bbb84ab
[recipe-lib] Make openssl a library recipe and ...
opacam Jul 26, 2019
0aa7083
[recipe-lib] Make png a library recipe
opacam Jul 26, 2019
5342814
[recipe-lib] Make jpeg a library recipe
opacam Jul 26, 2019
ce035b0
[recipe-lib] Make freetype a library recipe and ...
opacam Jul 26, 2019
644682f
[recipe-lib] Make harfbuzz a library recipe and ...
opacam Jul 26, 2019
158b1c0
[recipe-lib] Make libcurl a library recipe and ...
opacam Jul 26, 2019
e2fc6ea
[recipe-lib] Make libzbar a library recipe and ...
opacam Jul 26, 2019
8829783
[recipe-lib] Make libiconv a library recipe and ...
opacam Jul 26, 2019
7124f52
[recipe-lib] Make libexpat a library recipe and ...
opacam Jul 26, 2019
1be2cba
[recipe-lib] Make libogg a library recipe
opacam Jul 26, 2019
723cf9d
[recipe-lib] Make libxml2 a library recipe and ...
opacam Jul 26, 2019
2482bcb
[recipe-lib] Make libxslt a library recipe and ...
opacam Jul 26, 2019
42f69fb
[recipe-lib] Make libshine a library recipe and ...
opacam Jul 26, 2019
ccc960d
[recipe-lib] Make libx264 a library recipe and ...
opacam Jul 26, 2019
64c609c
[recipe-lib] Make libglob a library recipe
opacam Jul 26, 2019
0ac8c9d
[recipe-lib] Make libsodium a library recipe and ...
opacam Jul 26, 2019
5919a32
[recipe-lib] Make libsecp256k1 a library recipe and ...
opacam Jul 26, 2019
de76939
[tests] Add tests for library recipe
opacam Jul 31, 2019
2c2cd3b
[NDK19] Fix libglob for android NDK r19
opacam Aug 25, 2019
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
1 change: 1 addition & 0 deletions pythonforandroid/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ def build_recipes(build_order, python_modules, ctx, project_dir,
info_main('Building {} for {}'.format(recipe.name, arch.arch))
if recipe.should_build(arch):
recipe.build_arch(arch)
recipe.install_libraries(arch)
else:
info('{} said it is already built, skipping'
.format(recipe.name))
Expand Down
60 changes: 59 additions & 1 deletion pythonforandroid/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ class Recipe(with_metaclass(RecipeMeta)):

archs = ['armeabi'] # Not currently implemented properly

built_libraries = {}
"""Each recipe that builds a system library (e.g.:libffi, openssl, etc...)
should contain a dict holding the relevant information of the library. The
keys should be the generated libraries and the values the relative path of
the library inside his build folder. This dict will be used to perform
different operations:
- copy the library into the right location, depending on if it's shared
or static)
- check if we have to rebuild the library

Here an example of how it would look like for `libffi` recipe:

- `built_libraries = {'libffi.so': '.libs'}`

.. note:: in case that the built library resides in recipe's build
directory, you can set the following values for the relative
path: `'.', None or ''`
"""

@property
def version(self):
key = 'VERSION_' + self.name
Expand Down Expand Up @@ -479,9 +498,14 @@ def apply_patches(self, arch, build_dir=None):

def should_build(self, arch):
'''Should perform any necessary test and return True only if it needs
building again.
building again. Per default we implement a library test, in case that
we detect so.

'''
if self.built_libraries:
return not all(
exists(lib) for lib in self.get_libraries(arch.arch)
)
return True

def build_arch(self, arch):
Expand All @@ -492,6 +516,19 @@ def build_arch(self, arch):
if hasattr(self, build):
getattr(self, build)()

def install_libraries(self, arch):
'''This method is always called after `build_arch`. In case that we
detect a library recipe, defined by the class attribute
`built_libraries`, we will copy all defined libraries into the
right location.
'''
if not self.built_libraries:
return
shared_libs = [
lib for lib in self.get_libraries(arch) if lib.endswith(".so")
]
self.install_libs(arch, *shared_libs)

def postbuild_arch(self, arch):
'''Run any post-build tasks for the Recipe. By default, this checks if
any postbuild_archname methods exist for the archname of the
Expand Down Expand Up @@ -554,6 +591,27 @@ def install_libs(self, arch, *libs):
def has_libs(self, arch, *libs):
return all(map(lambda l: self.ctx.has_lib(arch.arch, l), libs))

def get_libraries(self, arch_name, in_context=False):
"""Return the full path of the library depending on the architecture.
Per default, the build library path it will be returned, unless
`get_libraries` has been called with kwarg `in_context` set to
True.

.. note:: this method should be used for library recipes only
"""
recipe_libs = set()
if not self.built_libraries:
return recipe_libs
for lib, rel_path in self.built_libraries.items():
if not in_context:
abs_path = join(self.get_build_dir(arch_name), rel_path, lib)
if rel_path in {".", "", None}:
abs_path = join(self.get_build_dir(arch_name), lib)
else:
abs_path = join(self.ctx.get_libs_dir(arch_name), lib)
recipe_libs.add(abs_path)
return recipe_libs

@classmethod
def recipe_dirs(cls, ctx):
recipe_dirs = []
Expand Down
28 changes: 11 additions & 17 deletions pythonforandroid/recipes/freetype/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pythonforandroid.toolchain import Recipe
from pythonforandroid.recipe import Recipe
from pythonforandroid.logger import shprint, info
from pythonforandroid.util import current_directory
from os.path import exists, join
from os.path import join, exists
from multiprocessing import cpu_count
import sh

Expand All @@ -26,16 +26,7 @@ class FreetypeRecipe(Recipe):

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

def should_build(self, arch):
return not exists(
join(
self.get_build_dir(arch.arch),
'objs',
'.libs',
'libfreetype.so',
)
)
built_libraries = {'libfreetype.so': 'objs/.libs'}

def get_recipe_env(self, arch=None, with_harfbuzz=False):
env = super(FreetypeRecipe, self).get_recipe_env(arch)
Expand Down Expand Up @@ -111,11 +102,14 @@ def build_arch(self, arch, with_harfbuzz=False):
# 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')

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


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


Expand All @@ -23,13 +23,7 @@ class HarfbuzzRecipe(Recipe):
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):
return not exists(
join(
self.get_build_dir(arch.arch), 'src', '.libs', 'libharfbuzz.so'
)
)
built_libraries = {'libharfbuzz.so': 'src/.libs'}

def get_recipe_env(self, arch=None):
env = super(HarfbuzzRecipe, self).get_recipe_env(arch)
Expand Down Expand Up @@ -68,12 +62,12 @@ def build_arch(self, arch):
_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
# Rebuild/install freetype with harfbuzz support
freetype = self.get_recipe('freetype', self.ctx)
freetype.build_arch(arch, with_harfbuzz=True)
freetype.install_libraries(arch)


recipe = HarfbuzzRecipe()
13 changes: 2 additions & 11 deletions pythonforandroid/recipes/jpeg/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from pythonforandroid.recipe import Recipe
from pythonforandroid.logger import shprint
from pythonforandroid.util import current_directory
from os.path import join, exists
from os.path import join
from os import environ, uname
from glob import glob
import sh


Expand All @@ -16,15 +15,11 @@ class JpegRecipe(Recipe):
name = 'jpeg'
version = '2.0.1'
url = 'https://github.com/libjpeg-turbo/libjpeg-turbo/archive/{version}.tar.gz' # noqa
built_libraries = {'libjpeg.a': '.', 'libturbojpeg.a': '.'}
# we will require this below patch to build the shared library
# patches = ['remove-version.patch']

def should_build(self, arch):
return not exists(join(self.get_build_dir(arch.arch),
'libturbojpeg.a'))

def build_arch(self, arch):
super(JpegRecipe, self).build_arch(arch)
build_dir = self.get_build_dir(arch.arch)

# TODO: Fix simd/neon
Expand Down Expand Up @@ -59,10 +54,6 @@ def build_arch(self, arch):
_env=env)
shprint(sh.make, _env=env)

# copy static libs to libs collection
for lib in glob(join(build_dir, '*.a')):
shprint(sh.cp, '-L', lib, self.ctx.libs_dir)

def get_recipe_env(self, arch=None, with_flags_in_cc=False):
env = environ.copy()

Expand Down
16 changes: 5 additions & 11 deletions pythonforandroid/recipes/libcurl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import sh
from pythonforandroid.toolchain import Recipe, shprint, shutil, current_directory
from os.path import exists, join
from pythonforandroid.recipe import Recipe
from pythonforandroid.util import current_directory
from pythonforandroid.logger import shprint
from os.path import join
from multiprocessing import cpu_count


class LibcurlRecipe(Recipe):
version = '7.55.1'
url = 'https://curl.haxx.se/download/curl-7.55.1.tar.gz'
built_libraries = {'libcurl.so': 'dist/lib'}
depends = ['openssl']

def should_build(self, arch):
super(LibcurlRecipe, self).should_build(arch)
return not exists(join(self.ctx.get_libs_dir(arch.arch), 'libcurl.so'))

def build_arch(self, arch):
super(LibcurlRecipe, self).build_arch(arch)
env = self.get_recipe_env(arch)

r = self.get_recipe('openssl', self.ctx)
Expand All @@ -31,10 +29,6 @@ def build_arch(self, arch):
_env=env)
shprint(sh.make, '-j', str(cpu_count()), _env=env)
shprint(sh.make, 'install', _env=env)
shutil.copyfile('{}/lib/libcurl.so'.format(dst_dir),
join(
self.ctx.get_libs_dir(arch.arch),
'libcurl.so'))


recipe = LibcurlRecipe()
18 changes: 6 additions & 12 deletions pythonforandroid/recipes/libexpat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@

import sh
from pythonforandroid.toolchain import Recipe, shprint, shutil, current_directory
from os.path import exists, join
from pythonforandroid.recipe import Recipe
from pythonforandroid.util import current_directory
from pythonforandroid.logger import shprint
from os.path import join
from multiprocessing import cpu_count


class LibexpatRecipe(Recipe):
version = 'master'
url = 'https://github.com/libexpat/libexpat/archive/{version}.zip'
built_libraries = {'libexpat.so': 'dist/lib'}
depends = []

def should_build(self, arch):
super(LibexpatRecipe, self).should_build(arch)
return not exists(
join(self.ctx.get_libs_dir(arch.arch), 'libexpat.so'))

def build_arch(self, arch):
super(LibexpatRecipe, self).build_arch(arch)
env = self.get_recipe_env(arch)
with current_directory(join(self.get_build_dir(arch.arch), 'expat')):
dst_dir = join(self.get_build_dir(arch.arch), 'dist')
shprint(sh.Command('./buildconf.sh'), _env=env)
shprint(
sh.Command('./configure'),
'--host=arm-linux-androideabi',
'--host={}'.format(arch.command_prefix),
'--enable-shared',
'--without-xmlwf',
'--prefix={}'.format(dst_dir),
_env=env)
shprint(sh.make, '-j', str(cpu_count()), _env=env)
shprint(sh.make, 'install', _env=env)
shutil.copyfile(
'{}/lib/libexpat.so'.format(dst_dir),
join(self.ctx.get_libs_dir(arch.arch), 'libexpat.so'))


recipe = LibexpatRecipe()
9 changes: 2 additions & 7 deletions pythonforandroid/recipes/libffi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from multiprocessing import cpu_count
from pythonforandroid.recipe import Recipe
from pythonforandroid.logger import shprint
from pythonforandroid.util import current_directory, ensure_dir
from pythonforandroid.util import current_directory
import sh


Expand Down Expand Up @@ -31,8 +31,7 @@ class LibffiRecipe(Recipe):

patches = ['remove-version-info.patch']

def should_build(self, arch):
return not exists(join(self.ctx.get_libs_dir(arch.arch), 'libffi.so'))
built_libraries = {'libffi.so': '.libs'}

def build_arch(self, arch):
env = self.get_recipe_env(arch)
Expand All @@ -46,10 +45,6 @@ def build_arch(self, arch):
'--disable-builddir',
'--enable-shared', _env=env)
shprint(sh.make, '-j', str(cpu_count()), 'libffi.la', _env=env)
ensure_dir(self.ctx.get_libs_dir(arch.arch))
self.install_libs(
arch, join(self.get_build_dir(arch.arch), '.libs', 'libffi.so')
)

def get_include_dirs(self, arch):
return [join(self.get_build_dir(arch.arch), 'include')]
Expand Down
6 changes: 3 additions & 3 deletions pythonforandroid/recipes/libglob/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
available via '-lglob' LDFLAG
"""
from os.path import exists, join
from pythonforandroid.recipe import CompiledComponentsPythonRecipe
from pythonforandroid.recipe import Recipe
from pythonforandroid.toolchain import current_directory
from pythonforandroid.logger import info, shprint
import sh


class LibGlobRecipe(CompiledComponentsPythonRecipe):
class LibGlobRecipe(Recipe):
"""Make a glob.h and glob.so for the python_install_dir()"""
version = '0.0.1'
url = None
Expand All @@ -20,6 +20,7 @@ class LibGlobRecipe(CompiledComponentsPythonRecipe):
# https://raw.githubusercontent.com/white-gecko/TokyoCabinet/master/glob.c
# and pushed in via patch
name = 'libglob'
built_libraries = {'libglob.so': '.'}

depends = [('hostpython2', 'hostpython3')]
patches = ['glob.patch']
Expand Down Expand Up @@ -60,7 +61,6 @@ def build_arch(self, arch):
cflags.extend(['-shared', '-I.', 'glob.o', '-o', 'libglob.so'])
cflags.extend(env['LDFLAGS'].split())
shprint(cc, *cflags, _env=env)
shprint(sh.cp, 'libglob.so', join(self.ctx.libs_dir, arch.arch))


recipe = LibGlobRecipe()
6 changes: 4 additions & 2 deletions pythonforandroid/recipes/libglob/glob.patch
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ diff -Nur /tmp/x/glob.c libglob/glob.c
diff -Nur /tmp/x/glob.h libglob/glob.h
--- /tmp/x/glob.h 1969-12-31 19:00:00.000000000 -0500
+++ libglob/glob.h 2017-08-19 15:22:18.367109399 -0400
@@ -0,0 +1,102 @@
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
Expand Down Expand Up @@ -952,10 +952,12 @@ diff -Nur /tmp/x/glob.h libglob/glob.h
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#ifndef ARG_MAX
+#define ARG_MAX 6553
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#include <stddef.h>
+#define _SIZE_T_DECLARED
+#endif
+
Expand Down
Loading