Skip to content

Commit 7d88f4c

Browse files
committed
recipes: add a few recipes
1 parent 87a32be commit 7d88f4c

File tree

5 files changed

+177
-5
lines changed

5 files changed

+177
-5
lines changed

pythonforandroid/recipe.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,8 @@ class RustCompiledComponentsRecipe(PyProjectRecipe):
13551355
"x86_64": "x86_64-linux-android",
13561356
"x86": "i686-linux-android",
13571357
}
1358+
# Rust toolchain to be used for building
1359+
toolchain = "stable"
13581360

13591361
call_hostpython_via_targetpython = False
13601362

@@ -1367,6 +1369,7 @@ def get_recipe_env(self, arch, **kwargs):
13671369
build_target.upper().replace("-", "_")
13681370
)
13691371
env["CARGO_BUILD_TARGET"] = build_target
1372+
env["TARGET"] = build_target
13701373
env[cargo_linker_name] = join(
13711374
self.ctx.ndk.llvm_prebuilt_dir,
13721375
"bin",
@@ -1388,10 +1391,6 @@ def get_recipe_env(self, arch, **kwargs):
13881391
realpython_dir, "android-build", "build",
13891392
"lib.linux-*-{}/".format(self.python_major_minor_version),
13901393
))[0])
1391-
1392-
info_main("Ensuring rust build toolchain")
1393-
shprint(sh.rustup, "target", "add", build_target)
1394-
13951394
# Add host python to PATH
13961395
env["PATH"] = ("{hostpython_dir}:{old_path}").format(
13971396
hostpython_dir=Recipe.get_recipe(
@@ -1401,17 +1400,24 @@ def get_recipe_env(self, arch, **kwargs):
14011400
)
14021401
return env
14031402

1403+
def ensure_rust_toolchain(self, arch):
1404+
info_main("Ensuring rust build toolchain : {}".format(self.toolchain))
1405+
shprint(sh.rustup, "toolchain", "install", self.toolchain)
1406+
shprint(sh.rustup, "target", "add", "--toolchain", self.toolchain, self.RUST_ARCH_CODES[arch.arch])
1407+
shprint(sh.rustup, "default", self.toolchain)
1408+
14041409
def check_host_deps(self):
14051410
if not hasattr(sh, "rustup"):
14061411
error(
1407-
"`rustup` was not found on host system."
1412+
"\n`rustup` was not found on host system."
14081413
"Please install it using :"
14091414
"\n`curl https://sh.rustup.rs -sSf | sh`\n"
14101415
)
14111416
exit(1)
14121417

14131418
def build_arch(self, arch):
14141419
self.check_host_deps()
1420+
self.ensure_rust_toolchain(arch)
14151421
super().build_arch(arch)
14161422

14171423

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from os import makedirs, remove
2+
from os.path import exists, join
3+
import sh
4+
5+
from pythonforandroid.recipe import Recipe
6+
from pythonforandroid.logger import shprint
7+
8+
9+
class LibPthread(Recipe):
10+
'''
11+
This is a dumb recipe. We may need this because some recipes inserted some
12+
flags `-lpthread` without our control, case of:
13+
14+
- :class:`~pythonforandroid.recipes.uvloop.UvloopRecipe`
15+
16+
.. note:: the libpthread doesn't exist in android but it is integrated into
17+
libc, so we create a symbolic link which we will remove when our build
18+
finishes'''
19+
20+
def build_arch(self, arch):
21+
libc_path = join(arch.ndk_lib_dir_versioned, 'libc')
22+
# Create a temporary folder to add to link path with a fake libpthread.so:
23+
fake_libpthread_temp_folder = join(
24+
self.get_build_dir(arch.arch),
25+
"p4a-libpthread-recipe-tempdir"
26+
)
27+
if not exists(fake_libpthread_temp_folder):
28+
makedirs(fake_libpthread_temp_folder)
29+
30+
# Set symlinks, and make sure to update them on every build run:
31+
if exists(join(fake_libpthread_temp_folder, "libpthread.so")):
32+
remove(join(fake_libpthread_temp_folder, "libpthread.so"))
33+
shprint(sh.ln, '-sf',
34+
libc_path + '.so',
35+
join(fake_libpthread_temp_folder, "libpthread.so"),
36+
)
37+
if exists(join(fake_libpthread_temp_folder, "libpthread.a")):
38+
remove(join(fake_libpthread_temp_folder, "libpthread.a"))
39+
shprint(sh.ln, '-sf',
40+
libc_path + '.a',
41+
join(fake_libpthread_temp_folder, "libpthread.a"),
42+
)
43+
44+
# Add folder as -L link option for all recipes if not done yet:
45+
if fake_libpthread_temp_folder not in arch.extra_global_link_paths:
46+
arch.extra_global_link_paths.append(
47+
fake_libpthread_temp_folder
48+
)
49+
50+
51+
recipe = LibPthread()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import time
2+
from os.path import join
3+
from glob import glob
4+
from pythonforandroid.logger import warning
5+
from pythonforandroid.recipe import RustCompiledComponentsRecipe
6+
7+
WARNING_MSG = """
8+
9+
This build requires at least 6GB of free RAM. If you cannot arrange free RAM, please consider adding some swap memory.
10+
11+
For Linux:
12+
13+
1. Open a terminal and execute the following commands to create an 8GB swap file:
14+
sudo fallocate -l 8G /swapfile.swap
15+
sudo chmod 700 /swapfile.swap
16+
sudo mkswap /swapfile.swap
17+
sudo swapon /swapfile.swap
18+
19+
2. To make the swap memory permanent, add it to your system's configuration by executing:
20+
sudo sh -c 'echo "/swapfile.swap swap swap defaults 0 0" >> /etc/fstab'
21+
22+
Learn more about swap: https://en.wikipedia.org/wiki/Memory_paging
23+
"""
24+
25+
26+
class PolarsRecipe(RustCompiledComponentsRecipe):
27+
version = "0.20.25"
28+
url = "https://github.com/pola-rs/polars/releases/download/py-{version}/polars-{version}.tar.gz"
29+
toolchain = "nightly-2024-04-15" # from rust-toolchain.toml
30+
need_stl_shared = True
31+
32+
def get_recipe_env(self, arch, **kwargs):
33+
env = super().get_recipe_env(arch, **kwargs)
34+
# Required for libz-ng-sys
35+
env["CMAKE_TOOLCHAIN_FILE"] = join(
36+
self.ctx.ndk_dir, "build", "cmake", "android.toolchain.cmake")
37+
38+
# Enable SIMD instructions
39+
simd_include = glob(join(
40+
self.ctx.ndk.llvm_prebuilt_dir,
41+
"lib64",
42+
"clang",
43+
"*",
44+
"include"
45+
))[0]
46+
env["CFLAGS"] += " -DARM_SIMD -D_MSC_VER -I{}".format(simd_include)
47+
48+
# Required for libgit2-sys
49+
env["CFLAGS"] += " -I{}".format(self.ctx.ndk.sysroot_include_dir)
50+
return env
51+
52+
def build_arch(self, arch):
53+
warning(WARNING_MSG)
54+
time.sleep(5) # let user read the warning
55+
56+
# Polars doesn't officially support 32-bit Python.
57+
# See https://github.com/pola-rs/polars/issues/10460
58+
if arch.arch in ["x86", "armeabi-v7a"]:
59+
warning("Polars does not support architecture: {}".format(arch.arch))
60+
return
61+
else:
62+
super().build_arch(arch)
63+
64+
65+
recipe = PolarsRecipe()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from pythonforandroid.logger import info
2+
from pythonforandroid.recipe import RustCompiledComponentsRecipe
3+
4+
5+
class Pyreqwest_impersonateRecipe(RustCompiledComponentsRecipe):
6+
version = "v0.4.5"
7+
url = "https://github.com/deedy5/pyreqwest_impersonate/archive/refs/tags/{version}.tar.gz"
8+
9+
def get_recipe_env_post(self, arch, **kwargs):
10+
env = super().get_recipe_env(arch, **kwargs)
11+
env["ANDROID_NDK_HOME"] = self.ctx.ndk.llvm_prebuilt_dir
12+
return env
13+
14+
def get_recipe_env_pre(self, arch, **kwargs):
15+
env = super().get_recipe_env(arch, **kwargs)
16+
env["ANDROID_NDK_HOME"] = self.ctx.ndk_dir
17+
return env
18+
19+
def build_arch(self, arch):
20+
# Why need of two env?
21+
# Because there are two dependencies which accepts
22+
# different ANDROID_NDK_HOME
23+
self.get_recipe_env = self.get_recipe_env_pre
24+
prebuild_ = super().build_arch
25+
try:
26+
prebuild_(arch)
27+
except Exception:
28+
info("pyreqwest_impersonate first build failed, as expected")
29+
self.get_recipe_env = self.get_recipe_env_post
30+
prebuild_(arch)
31+
32+
33+
recipe = Pyreqwest_impersonateRecipe()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from pythonforandroid.recipe import PyProjectRecipe
2+
3+
4+
class UvloopRecipe(PyProjectRecipe):
5+
# 0.19.0
6+
version = '6c770dc3fbdd281d15c2ad46588c139696f9269c'
7+
url = 'git+https://github.com/MagicStack/uvloop'
8+
depends = ['librt', 'libpthread']
9+
10+
def get_recipe_env(self, arch, **kwargs):
11+
env = super().get_recipe_env(arch, **kwargs)
12+
env["LIBUV_CONFIGURE_HOST"] = arch.command_prefix
13+
env["PLATFORM"] = "android"
14+
return env
15+
16+
17+
recipe = UvloopRecipe()

0 commit comments

Comments
 (0)