From 9d609e21431ceb7ba0ad1cdf77d4b60e9a1d9194 Mon Sep 17 00:00:00 2001 From: Ansh Dadwal Date: Wed, 22 May 2024 11:42:54 +0530 Subject: [PATCH] recipes: add new `polars` recipe --- pythonforandroid/recipe.py | 24 +++++--- pythonforandroid/recipes/polars/__init__.py | 68 +++++++++++++++++++++ 2 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 pythonforandroid/recipes/polars/__init__.py diff --git a/pythonforandroid/recipe.py b/pythonforandroid/recipe.py index c4131c53e6..fcd535b0ec 100644 --- a/pythonforandroid/recipe.py +++ b/pythonforandroid/recipe.py @@ -1204,8 +1204,8 @@ def get_wheel_platform_tag(self, arch): "x86": "i686", }[arch.arch] - def install_wheel(self, arch, built_wheels): - _wheel = built_wheels[0] + def install_wheel(self, arch, pattern): + _wheel = [realpath(whl) for whl in glob.glob(pattern)][0] built_wheel_dir = dirname(_wheel) # Fix wheel platform tag wheel_tag = wheel_tags( @@ -1247,13 +1247,11 @@ def build_arch(self, arch): "builddir={}".format(sub_build_dir), ] + self.extra_build_args - built_wheels = [] with current_directory(build_dir): shprint( sh.Command(self.ctx.python_recipe.python_exe), *build_args, _env=env ) - built_wheels = [realpath(whl) for whl in glob.glob("dist/*.whl")] - self.install_wheel(arch, built_wheels) + self.install_wheel(arch, join(build_dir, "dist", "*.whl")) class MesonRecipe(PyProjectRecipe): @@ -1355,6 +1353,8 @@ class RustCompiledComponentsRecipe(PyProjectRecipe): "x86_64": "x86_64-linux-android", "x86": "i686-linux-android", } + # Rust toolchain to be used for building + toolchain = "stable" call_hostpython_via_targetpython = False @@ -1367,6 +1367,7 @@ def get_recipe_env(self, arch, **kwargs): build_target.upper().replace("-", "_") ) env["CARGO_BUILD_TARGET"] = build_target + env["TARGET"] = build_target env[cargo_linker_name] = join( self.ctx.ndk.llvm_prebuilt_dir, "bin", @@ -1388,10 +1389,6 @@ def get_recipe_env(self, arch, **kwargs): realpython_dir, "android-build", "build", "lib.linux-*-{}/".format(self.python_major_minor_version), ))[0]) - - info_main("Ensuring rust build toolchain") - shprint(sh.rustup, "target", "add", build_target) - # Add host python to PATH env["PATH"] = ("{hostpython_dir}:{old_path}").format( hostpython_dir=Recipe.get_recipe( @@ -1401,10 +1398,16 @@ def get_recipe_env(self, arch, **kwargs): ) return env + def ensure_rust_toolchain(self, arch): + info_main("Ensuring rust build toolchain : {}".format(self.toolchain)) + shprint(sh.rustup, "toolchain", "install", self.toolchain) + shprint(sh.rustup, "target", "add", "--toolchain", self.toolchain, self.RUST_ARCH_CODES[arch.arch]) + shprint(sh.rustup, "default", self.toolchain) + def check_host_deps(self): if not hasattr(sh, "rustup"): error( - "`rustup` was not found on host system." + "\n`rustup` was not found on host system." "Please install it using :" "\n`curl https://sh.rustup.rs -sSf | sh`\n" ) @@ -1412,6 +1415,7 @@ def check_host_deps(self): def build_arch(self, arch): self.check_host_deps() + self.ensure_rust_toolchain(arch) super().build_arch(arch) diff --git a/pythonforandroid/recipes/polars/__init__.py b/pythonforandroid/recipes/polars/__init__.py new file mode 100644 index 0000000000..7a00a365ab --- /dev/null +++ b/pythonforandroid/recipes/polars/__init__.py @@ -0,0 +1,68 @@ +import time +from os.path import join +from glob import glob +from pythonforandroid.logger import warning +from pythonforandroid.recipe import RustCompiledComponentsRecipe + +WARNING_MSG = """ + +This build requires at least 6GB of free RAM. If you cannot arrange free RAM, please consider adding some swap memory. + +For Linux: + +1. Open a terminal and execute the following commands to create an 8GB swap file: + sudo fallocate -l 8G /swapfile.swap + sudo chmod 700 /swapfile.swap + sudo mkswap /swapfile.swap + sudo swapon /swapfile.swap + +2. To make the swap memory permanent, add it to your system's configuration by executing: + sudo sh -c 'echo "/swapfile.swap swap swap defaults 0 0" >> /etc/fstab' + +Learn more about swap: https://en.wikipedia.org/wiki/Memory_paging +""" + + +class PolarsRecipe(RustCompiledComponentsRecipe): + version = "0.20.25" + url = "https://github.com/pola-rs/polars/releases/download/py-{version}/polars-{version}.tar.gz" + toolchain = "nightly-2024-04-15" # from rust-toolchain.toml + need_stl_shared = True + + def get_recipe_env(self, arch, **kwargs): + env = super().get_recipe_env(arch, **kwargs) + # Required for libz-ng-sys + env["CMAKE_TOOLCHAIN_FILE"] = join( + self.ctx.ndk_dir, "build", "cmake", "android.toolchain.cmake") + + # Enable SIMD instructions + simd_include = glob(join( + self.ctx.ndk.llvm_prebuilt_dir, + "lib64", + "clang", + "*", + "include" + ))[0] + env["CFLAGS"] += " -D__ARM_FEATURE_SIMD32=1 -I{}".format(simd_include) + + # Required for libgit2-sys + env["CFLAGS"] += " -I{}".format(self.ctx.ndk.sysroot_include_dir) + + # We don't want rust cc to set flags for us + env["CRATE_CC_NO_DEFAULTS"] = "1" + return env + + def build_arch(self, arch): + warning(WARNING_MSG) + time.sleep(5) # let user read the warning + + # Polars doesn't officially support 32-bit Python. + # See https://github.com/pola-rs/polars/issues/10460 + if arch.arch in ["x86", "armeabi-v7a"]: + warning("Polars does not support architecture: {}".format(arch.arch)) + return + else: + super().build_arch(arch) + + +recipe = PolarsRecipe()