|
| 1 | +from pythonforandroid.recipe import Recipe, MesonRecipe |
| 2 | +from os.path import join, exists |
| 3 | +from pythonforandroid.util import ensure_dir, current_directory |
| 4 | +from pythonforandroid.logger import shprint |
| 5 | +from multiprocessing import cpu_count |
| 6 | +import sh |
| 7 | + |
| 8 | + |
| 9 | +class LibCairoRecipe(MesonRecipe): |
| 10 | + name = 'libcairo' |
| 11 | + version = '1.18.4' |
| 12 | + url = 'https://gitlab.freedesktop.org/cairo/cairo/-/archive/{version}/cairo-{version}.tar.bz2' |
| 13 | + skip_python = True |
| 14 | + depends = ["png", "freetype"] |
| 15 | + patches = ["meson.patch"] |
| 16 | + built_libraries = { |
| 17 | + 'libcairo.so': 'install/lib', |
| 18 | + 'libpixman-1.so': 'install/lib', |
| 19 | + 'libcairo-script-interpreter.so': 'install/lib' |
| 20 | + } |
| 21 | + |
| 22 | + def get_recipe_env(self, arch, **kwargs): |
| 23 | + env = super().get_recipe_env(arch, **kwargs) |
| 24 | + cpufeatures = join(self.ctx.ndk.ndk_dir, "sources/android/cpufeatures") |
| 25 | + lib_dir = join(cpufeatures, "obj", "local", arch.arch) |
| 26 | + env["CFLAGS"] += f" -I{cpufeatures}" |
| 27 | + env["LDFLAGS"] += f" -L{lib_dir} -lcpufeatures" |
| 28 | + return env |
| 29 | + |
| 30 | + def should_build(self, arch): |
| 31 | + return Recipe.should_build(self, arch) |
| 32 | + |
| 33 | + def build_arch(self, arch): |
| 34 | + super().build_arch(arch) |
| 35 | + build_dir = self.get_build_dir(arch.arch) |
| 36 | + install_dir = join(build_dir, 'install') |
| 37 | + ensure_dir(install_dir) |
| 38 | + env = self.get_recipe_env(arch) |
| 39 | + |
| 40 | + lib_dir = self.ctx.get_libs_dir(arch.arch) |
| 41 | + png_include = self.get_recipe('png', self.ctx).get_build_dir(arch.arch) |
| 42 | + freetype_inc = join(self.get_recipe('freetype', self.ctx).get_build_dir(arch), "include") |
| 43 | + |
| 44 | + with current_directory(build_dir): |
| 45 | + |
| 46 | + cpufeatures_dir = join(self.ctx.ndk.ndk_dir, "sources/android/cpufeatures") |
| 47 | + lib_file = join(cpufeatures_dir, "obj", "local", arch.arch, "libcpufeatures.a") |
| 48 | + |
| 49 | + if not exists(lib_file): |
| 50 | + shprint( |
| 51 | + sh.Command(join(self.ctx.ndk_dir, "ndk-build")), |
| 52 | + f"NDK_PROJECT_PATH={cpufeatures_dir}", |
| 53 | + f"APP_BUILD_SCRIPT={cpufeatures_dir}/Android.mk", |
| 54 | + f"APP_ABI={arch.arch}", |
| 55 | + "APP_PLATFORM=latest", |
| 56 | + _env=env |
| 57 | + ) |
| 58 | + |
| 59 | + shprint(sh.meson, 'setup', 'builddir', |
| 60 | + '--cross-file', join("/tmp", "android.meson.cross"), |
| 61 | + f'--prefix={install_dir}', |
| 62 | + '-Dpng=enabled', |
| 63 | + '-Dzlib=enabled', |
| 64 | + '-Dglib=disabled', |
| 65 | + '-Dgtk_doc=false', |
| 66 | + '-Dsymbol-lookup=disabled', |
| 67 | + |
| 68 | + # deps |
| 69 | + f'-Dpng_include_dir={png_include}', |
| 70 | + f'-Dpng_lib_dir={lib_dir}', |
| 71 | + f'-Dfreetype_include_dir={freetype_inc}', |
| 72 | + f'-Dfreetype_lib_dir={lib_dir}', |
| 73 | + _env=env) |
| 74 | + |
| 75 | + shprint(sh.ninja, '-C', 'builddir', '-j', str(cpu_count()), _env=env) |
| 76 | + # macOS fix: sometimes Ninja creates a dummy 'lib' file instead of a directory. |
| 77 | + # So we remove and recreate the install directory using shell commands, |
| 78 | + # since os.remove/os.makedirs behave inconsistently in this build env. |
| 79 | + shprint(sh.rm, '-rf', install_dir) |
| 80 | + shprint(sh.mkdir, install_dir) |
| 81 | + |
| 82 | + shprint(sh.ninja, '-C', 'builddir', 'install', _env=env) |
| 83 | + |
| 84 | + |
| 85 | +recipe = LibCairoRecipe() |
0 commit comments