diff --git a/pythonforandroid/recipes/jpeg/__init__.py b/pythonforandroid/recipes/jpeg/__init__.py index 33a9ba44da..3060c9b8ca 100644 --- a/pythonforandroid/recipes/jpeg/__init__.py +++ b/pythonforandroid/recipes/jpeg/__init__.py @@ -14,9 +14,7 @@ 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'] + built_libraries = {'libjpeg.so': '.', 'libturbojpeg.so': '.'} def build_arch(self, arch): build_dir = self.get_build_dir(arch.arch) @@ -34,6 +32,8 @@ def build_arch(self, arch): '-DCMAKE_ANDROID_ARCH_ABI={arch}'.format(arch=arch.arch), '-DCMAKE_ANDROID_NDK=' + self.ctx.ndk_dir, '-DCMAKE_C_COMPILER={cc}'.format(cc=arch.get_clang_exe()), + f'-DCMAKE_ASM_COMPILER={arch.get_clang_exe()}', + f'-DCMAKE_ASM_FLAGS=--target={arch.target}', '-DCMAKE_CXX_COMPILER={cc_plus}'.format( cc_plus=arch.get_clang_exe(plus_plus=True)), '-DCMAKE_BUILD_TYPE=Release', @@ -42,12 +42,11 @@ def build_arch(self, arch): '-DANDROID_ABI={arch}'.format(arch=arch.arch), '-DANDROID_ARM_NEON=ON', - '-DENABLE_NEON=ON', - # '-DREQUIRE_SIMD=1', + '-DWITH_SIMD=1', + '-DREQUIRE_SIMD=1', # Force disable shared, with the static ones is enough - '-DENABLE_SHARED=0', - '-DENABLE_STATIC=1', + '-DENABLE_SHARED=1', # Fix cmake compatibility issue '-DCMAKE_POLICY_VERSION_MINIMUM=3.5', diff --git a/pythonforandroid/recipes/jpeg/build-static.patch b/pythonforandroid/recipes/jpeg/build-static.patch deleted file mode 100644 index 0aa9c70a98..0000000000 --- a/pythonforandroid/recipes/jpeg/build-static.patch +++ /dev/null @@ -1,85 +0,0 @@ -diff -Naur jpeg/Android.mk b/Android.mk ---- jpeg/Android.mk 2015-12-14 11:37:25.900190235 -0600 -+++ b/Android.mk 2015-12-14 11:41:27.532182210 -0600 -@@ -54,8 +54,7 @@ - - LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST) - --LOCAL_SHARED_LIBRARIES := libcutils --LOCAL_STATIC_LIBRARIES := libsimd -+LOCAL_STATIC_LIBRARIES := libsimd libcutils - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -68,7 +67,7 @@ - - LOCAL_MODULE := libjpeg - --include $(BUILD_SHARED_LIBRARY) -+include $(BUILD_STATIC_LIBRARY) - - ###################################################### - ### cjpeg ### -@@ -82,7 +81,7 @@ - - LOCAL_SRC_FILES:= $(cjpeg_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -110,7 +109,7 @@ - - LOCAL_SRC_FILES:= $(djpeg_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -137,7 +136,7 @@ - - LOCAL_SRC_FILES:= $(jpegtran_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) \ - $(LOCAL_PATH)/android -@@ -163,7 +162,7 @@ - - LOCAL_SRC_FILES:= $(tjunittest_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -189,7 +188,7 @@ - - LOCAL_SRC_FILES:= $(tjbench_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -215,7 +214,7 @@ - - LOCAL_SRC_FILES:= $(rdjpgcom_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - -@@ -240,7 +239,7 @@ - - LOCAL_SRC_FILES:= $(wrjpgcom_SOURCES) - --LOCAL_SHARED_LIBRARIES := libjpeg -+LOCAL_STATIC_LIBRARIES := libjpeg - - LOCAL_C_INCLUDES := $(LOCAL_PATH) - diff --git a/pythonforandroid/recipes/jpeg/remove-version.patch b/pythonforandroid/recipes/jpeg/remove-version.patch deleted file mode 100644 index 311aa33bc4..0000000000 --- a/pythonforandroid/recipes/jpeg/remove-version.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- jpeg/CMakeLists.txt.orig 2018-11-12 20:20:28.000000000 +0100 -+++ jpeg/CMakeLists.txt 2018-12-14 12:43:45.338704504 +0100 -@@ -573,6 +573,9 @@ - add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES}) - set_property(TARGET turbojpeg PROPERTY COMPILE_FLAGS - "-DBMP_SUPPORTED -DPPM_SUPPORTED") -+ set_property(TARGET jpeg PROPERTY NO_SONAME 1) -+ set_property(TARGET turbojpeg PROPERTY NO_SONAME 1) -+ set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "") - if(WIN32) - set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE) - endif() diff --git a/pythonforandroid/recipes/libthorvg/__init__.py b/pythonforandroid/recipes/libthorvg/__init__.py new file mode 100644 index 0000000000..b0e145bdea --- /dev/null +++ b/pythonforandroid/recipes/libthorvg/__init__.py @@ -0,0 +1,100 @@ +from pythonforandroid.recipe import Recipe, MesonRecipe +from os.path import join +from pythonforandroid.util import ensure_dir, current_directory +from pythonforandroid.logger import shprint +from multiprocessing import cpu_count +from glob import glob +import sh + + +class LibThorVGRecipe(MesonRecipe): + name = "libthorvg" + version = "1.0.1" + url = "https://github.com/thorvg/thorvg/releases/download/v{version}/thorvg.tar.gz" + config_otps = [ + "-Dsimd=true", + "-Dbindings=capi", + "-Dtools=all", + "-Dengines=sw,gl", + "-Dloaders=svg,png,jpg,ttf,webp", + "-Dextra=opengl_es,lottie_exp,openmp", + ] + need_stl_shared = True + skip_python = True + depends = ["png", "libwebp", "jpeg"] + patches = ["meson.patch"] + bins = ["tvg-lottie2gif", "tvg-svg2png"] + built_libraries = { + "libthorvg-1.so": "install/lib", + "libomp.so": "install/lib" + } + for bin in bins: + built_libraries[f"lib{bin}bin.so"] = "install/bin" + + def should_build(self, arch): + return Recipe.should_build(self, arch) + + def get_include_dir(self, arch): + return join(self.get_build_dir(arch.arch), "install", "include") + + def build_arch(self, arch): + super().build_arch(arch) + build_dir = self.get_build_dir(arch.arch) + install_dir = join(build_dir, "install") + ensure_dir(install_dir) + env = self.get_recipe_env(arch) + + lib_dir = self.ctx.get_libs_dir(arch.arch) + png_include = self.get_recipe("png", self.ctx).get_build_dir(arch.arch) + webp_include = join( + self.get_recipe("libwebp", self.ctx).get_build_dir(arch.arch), "src" + ) + jpg_dir = self.get_recipe("jpeg", self.ctx).get_build_dir(arch.arch) + + with current_directory(build_dir): + + shprint( + sh.meson, + "setup", + "builddir", + "--cross-file", + join("/tmp", "android.meson.cross"), + f"--prefix={install_dir}", + # config opts + *self.config_otps, + # deps + f"-Dpng_include_dir={png_include}", + f"-Dpng_lib_dir={lib_dir}", + f"-Dwebp_include_dir={webp_include}", + f"-Dwebp_lib_dir={lib_dir}", + f"-Djpg_include_dir={jpg_dir}", + f"-Djpg_lib_dir={jpg_dir}", + _env=env, + ) + + shprint(sh.ninja, "-C", "builddir", "-j", str(cpu_count()), _env=env) + shprint(sh.rm, "-rf", install_dir) + shprint(sh.mkdir, install_dir) + shprint(sh.ninja, "-C", "builddir", "install", _env=env) + + # copy libomp.so + arch_map = { + "arm64-v8a": "aarch64", + "armeabi-v7a": "arm", + "x86": "i386", + "x86_64": "x86_64", + } + lib_arch = arch_map[arch.arch] + # clang version directory is variable, so glob it + pattern = join(self.ctx.ndk.llvm_prebuilt_dir, "lib/clang/*/lib/linux", lib_arch) + clang_lib_dir = glob(pattern)[0] + libomp = join(clang_lib_dir, "libomp.so") + shprint(sh.cp, libomp, join("install", "lib")) + + # setup bins + bin_dir = join("install", "bin") + for bin in self.bins: + shprint(sh.cp, join(bin_dir, bin), join(bin_dir, f"lib{bin}bin.so")) + + +recipe = LibThorVGRecipe() diff --git a/pythonforandroid/recipes/libthorvg/meson.patch b/pythonforandroid/recipes/libthorvg/meson.patch new file mode 100644 index 0000000000..ffdbdf5616 --- /dev/null +++ b/pythonforandroid/recipes/libthorvg/meson.patch @@ -0,0 +1,77 @@ +diff '--color=auto' -uNr thorvg/meson_options.txt thorvg.mod/meson_options.txt +--- thorvg/meson_options.txt 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/meson_options.txt 2026-03-06 11:11:43.111722092 +0530 +@@ -68,3 +68,11 @@ + choices: ['', 'opengl_es', 'lottie_exp', 'openmp'], + value: ['lottie_exp', 'openmp'], + description: 'Enable support for extra options') ++ ++ ++option('png_include_dir', type: 'string', value: '', description: 'Path to PNG headers') ++option('png_lib_dir', type: 'string', value: '', description: 'Path to PNG library') ++option('webp_include_dir', type: 'string', value: '', description: 'Path to WEBP headers') ++option('webp_lib_dir', type: 'string', value: '', description: 'Path to WEBP library') ++option('jpg_include_dir', type: 'string', value: '', description: 'Path to JPG headers') ++option('jpg_lib_dir', type: 'string', value: '', description: 'Path to JPG library') +diff '--color=auto' -uNr thorvg/src/loaders/external_jpg/meson.build thorvg.mod/src/loaders/external_jpg/meson.build +--- thorvg/src/loaders/external_jpg/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_jpg/meson.build 2026-03-06 11:16:26.360504907 +0530 +@@ -3,11 +3,12 @@ + 'tvgJpgLoader.cpp', + ] + +-jpg_dep = dependency('libturbojpeg', required: false) +- +-if not jpg_dep.found() +- jpg_dep = cc.find_library('turbojpeg', required: false) +-endif ++jpg_inc = include_directories(get_option('jpg_include_dir')) ++jpg_lib = cc.find_library('turbojpeg', dirs: [get_option('jpg_lib_dir')], required: true) ++jpg_dep = declare_dependency( ++ include_directories: jpg_inc, ++ dependencies: [jpg_lib] ++) + + if jpg_dep.found() + subloader_dep += [declare_dependency( +diff '--color=auto' -uNr thorvg/src/loaders/external_png/meson.build thorvg.mod/src/loaders/external_png/meson.build +--- thorvg/src/loaders/external_png/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_png/meson.build 2026-03-06 10:59:38.966203768 +0530 +@@ -3,7 +3,12 @@ + 'tvgPngLoader.cpp', + ] + +-png_dep = dependency('libpng', required: false) ++png_inc = include_directories(get_option('png_include_dir')) ++png_lib = cc.find_library('png16', dirs: [get_option('png_lib_dir')], required: true) ++png_dep = declare_dependency( ++ include_directories: png_inc, ++ dependencies: [png_lib] ++) + + if png_dep.found() + subloader_dep += [declare_dependency( +diff '--color=auto' -uNr thorvg/src/loaders/external_webp/meson.build thorvg.mod/src/loaders/external_webp/meson.build +--- thorvg/src/loaders/external_webp/meson.build 2026-02-12 21:02:13.000000000 +0530 ++++ thorvg.mod/src/loaders/external_webp/meson.build 2026-03-06 11:03:55.626148453 +0530 +@@ -3,7 +3,12 @@ + 'tvgWebpLoader.cpp', + ] + +-webp_dep = dependency('libwebp', required: false) ++webp_inc = include_directories(get_option('webp_include_dir')) ++webp_lib = cc.find_library('webp', dirs: [get_option('webp_lib_dir')], required: true) ++webp_dep = declare_dependency( ++ include_directories: webp_inc, ++ dependencies: [webp_lib] ++) + + if webp_dep.found() + subloader_dep += [declare_dependency( +@@ -11,4 +16,4 @@ + dependencies : webp_dep, + sources : source_file + )] +-endif +\ No newline at end of file ++endif diff --git a/pythonforandroid/recipes/thorvg-python/__init__.py b/pythonforandroid/recipes/thorvg-python/__init__.py new file mode 100644 index 0000000000..18b1fe1329 --- /dev/null +++ b/pythonforandroid/recipes/thorvg-python/__init__.py @@ -0,0 +1,12 @@ +from pythonforandroid.recipe import PyProjectRecipe + + +class ThorVGPythonRecipe(PyProjectRecipe): + site_packages_name = "thorvg_python" + version = "1.1.1" + url = "https://github.com/laggykiller/thorvg-python/archive/refs/tags/v{version}.tar.gz" + depends = ["libthorvg"] + patches = ["sharedlib.patch"] + + +recipe = ThorVGPythonRecipe() diff --git a/pythonforandroid/recipes/thorvg-python/sharedlib.patch b/pythonforandroid/recipes/thorvg-python/sharedlib.patch new file mode 100644 index 0000000000..971c29ae31 --- /dev/null +++ b/pythonforandroid/recipes/thorvg-python/sharedlib.patch @@ -0,0 +1,43 @@ +diff '--color=auto' -uNr thorvg-python-1.1.1/pyproject.toml thorvg-python-1.1.1.mod/pyproject.toml +--- thorvg-python-1.1.1/pyproject.toml 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/pyproject.toml 2026-03-06 13:36:02.822762758 +0530 +@@ -34,7 +34,6 @@ + + [build-system] + requires = [ +- "conan>=2.0", + "setuptools>=45" + ] + build-backend = "setuptools.build_meta" +@@ -45,4 +44,4 @@ + + [tool.mypy] + python_version = "3.9" +-files = ["src", "tests"] +\ No newline at end of file ++files = ["src", "tests"] +diff '--color=auto' -uNr thorvg-python-1.1.1/setup.py thorvg-python-1.1.1.mod/setup.py +--- thorvg-python-1.1.1/setup.py 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/setup.py 2026-03-06 13:32:56.878441668 +0530 +@@ -213,10 +213,4 @@ + packages=find_packages(where="src"), + package_dir={"": "src"}, + include_package_data=True, +- package_data={ +- "thorvg_python": ["*.dll", "*.dylib", "*.so"], +- }, +- cmdclass={ +- "build_py": build_py_custom, +- }, + ) +diff '--color=auto' -uNr thorvg-python-1.1.1/src/thorvg_python/engine.py thorvg-python-1.1.1.mod/src/thorvg_python/engine.py +--- thorvg-python-1.1.1/src/thorvg_python/engine.py 2026-02-28 01:45:23.000000000 +0530 ++++ thorvg-python-1.1.1.mod/src/thorvg_python/engine.py 2026-03-06 16:42:11.625316343 +0530 +@@ -14,6 +14,7 @@ + ) -> Optional[ctypes.CDLL]: + package_dir = os.path.dirname(__file__) + thorvg_lib_name = lib_prefix + "thorvg" + lib_suffix ++ return ctypes.cdll.LoadLibrary(thorvg_lib_name) + thorvg_lib_path_local = os.path.join(package_dir, thorvg_lib_name) + + if os.path.isfile(thorvg_lib_path_local):