Skip to content

Commit a4773bc

Browse files
committed
recipes: new pydantic-core recipe
1 parent fb97f1a commit a4773bc

File tree

4 files changed

+3260
-12
lines changed

4 files changed

+3260
-12
lines changed

.github/workflows/push.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ jobs:
226226
source ci/osx_ci.sh
227227
arm64_set_path_and_python_version 3.9.7
228228
make --file ci/makefiles/osx.mk
229+
230+
- name: Install recipe specific dependencies
231+
uses: dtolnay/rust-toolchain@stable
232+
if: contains('pydantic-core', github.event_path)
233+
229234
- name: Rebuild updated recipes
230235
run: |
231236
source ci/osx_ci.sh
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
from shutil import which
2+
from os.path import join, realpath, basename, isfile
3+
import sh
4+
import glob
5+
from pythonforandroid.recipe import CompiledComponentsPythonRecipe
6+
from pythonforandroid.logger import error, shprint, info
7+
from pythonforandroid.util import current_directory
8+
9+
# https://doc.rust-lang.org/nightly/rustc/platform-support.html
10+
RUST_ARCH_CODES = {
11+
"arm64-v8a": "aarch64-linux-android",
12+
"armeabi-v7a": "armv7-linux-androideabi",
13+
"x86_64": "x86_64-linux-android",
14+
"x86": "i686-linux-android",
15+
}
16+
17+
# Cargo config options
18+
CARGO_CONFIG = """
19+
[target.{}]
20+
linker = "{}"
21+
rustflags = ["-C", "link-args=-L{} -L{}"]
22+
"""
23+
24+
25+
class PydanticcoreRecipe(CompiledComponentsPythonRecipe):
26+
version = "2.16.1"
27+
url = (
28+
"https://github.com/pydantic/pydantic-core/archive/refs/tags/v{version}.tar.gz"
29+
)
30+
patches = [join("patches", "add_typing_extensions.patch")]
31+
32+
def get_recipe_env(self, arch):
33+
env = super().get_recipe_env(arch)
34+
# Requires rust
35+
build_target = RUST_ARCH_CODES[arch.arch]
36+
if which("rustup"):
37+
info("Ensuring rust build toolchain")
38+
shprint(sh.rustup, "target", "add", build_target)
39+
else:
40+
error(
41+
"Rust (`rustup`) was not found on host system. Please install it using:"
42+
"\n`curl https://sh.rustup.rs -sSf | sh`\n"
43+
)
44+
exit(1)
45+
46+
env["CARGO_BUILD_TARGET"] = build_target
47+
48+
env["PATH"] = ("{hostpython_dir}:{old_path}").format(
49+
hostpython_dir=self.get_recipe(
50+
"hostpython3", self.ctx
51+
).get_path_to_python(),
52+
old_path=env["PATH"],
53+
)
54+
return env
55+
56+
def configure_cargo(self, build_dir, arch, python_recipe):
57+
"""Writes the cargo configuration"""
58+
cargo_config = join(build_dir, ".cargo", "config.toml")
59+
config_string = [
60+
CARGO_CONFIG.format(
61+
arch_,
62+
join(
63+
self.ctx.ndk.llvm_prebuilt_dir,
64+
"bin",
65+
"{}{}-clang".format(
66+
# NDK's Clang format
67+
# aarch64-linux-android{ndk_api}-clang
68+
# i686-linux-android{ndk_api}-clang
69+
# x86_64-linux-android{ndk_api}-clang
70+
# armv7a-linux-androideabi{ndk_api}-clang
71+
arch_.replace("7", "7a")
72+
if arch_.startswith("armv7")
73+
else arch_,
74+
self.ctx.ndk_api,
75+
),
76+
),
77+
self.ctx.get_libs_dir(arch.arch),
78+
join(
79+
python_recipe.get_build_dir(arch.arch),
80+
"android-build",
81+
),
82+
)
83+
for arch_ in RUST_ARCH_CODES.values()
84+
]
85+
86+
if isfile(cargo_config):
87+
info("Writing cargo configuration")
88+
with open(cargo_config, "w") as file:
89+
file.write("".join(config_string)[1:])
90+
file.close()
91+
92+
def build_arch(self, arch):
93+
build_dir = self.get_build_dir(arch.arch)
94+
env = self.get_recipe_env(arch)
95+
python_recipe = self.get_recipe("python3", self.ctx)
96+
built_wheel = None
97+
self.configure_cargo(build_dir, arch, python_recipe)
98+
99+
# Check for maturin
100+
if not which("maturin"):
101+
error(
102+
"maturin was not found on host system, please install with pip and rerun"
103+
)
104+
exit(1)
105+
106+
with current_directory(build_dir):
107+
shprint(
108+
sh.maturin,
109+
"build",
110+
"-i",
111+
"python{}".format(".".join(python_recipe.version.split(".")[:2])),
112+
"--skip-auditwheel",
113+
_env=env,
114+
)
115+
built_wheel = realpath(glob.glob("target/wheels/*-linux_*.whl")[0])
116+
117+
if built_wheel:
118+
info("Installing built wheel '{}'".format(basename(built_wheel)))
119+
120+
# Use host pip to install wheel
121+
shprint(
122+
sh.pip,
123+
"install",
124+
built_wheel,
125+
"--platform",
126+
# Here RUST_ARCH_CODES[arch.arch] won't work
127+
# because file name is like "_linux_armv7l"
128+
# So do manual splitting
129+
# Example filename: pydantic_core-2.16.1-cp311-cp311-linux_armv7l.whl
130+
built_wheel.split("-")[-1].split(".")[0],
131+
"--no-deps",
132+
"--target",
133+
self.ctx.get_python_install_dir(arch.arch),
134+
"--upgrade",
135+
_env=env,
136+
)
137+
138+
139+
recipe = PydanticcoreRecipe()

0 commit comments

Comments
 (0)