Skip to content

Commit 06295d8

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

File tree

4 files changed

+3269
-12
lines changed

4 files changed

+3269
-12
lines changed

.github/workflows/push.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,11 @@ jobs:
187187
- name: Pull docker image
188188
run: |
189189
make docker/pull
190+
- name: Install recipe specific dependencies
191+
uses: dtolnay/rust-toolchain@stable
190192
- name: Rebuild updated recipes
191193
run: |
194+
pip3 install maturin
192195
make docker/run/make/rebuild_updated_recipes
193196
194197
macos_rebuild_updated_recipes:
@@ -226,8 +229,11 @@ jobs:
226229
source ci/osx_ci.sh
227230
arm64_set_path_and_python_version 3.9.7
228231
make --file ci/makefiles/osx.mk
232+
- name: Install recipe specific dependencies
233+
uses: dtolnay/rust-toolchain@stable
229234
- name: Rebuild updated recipes
230235
run: |
236+
pip3 install maturin
231237
source ci/osx_ci.sh
232238
arm64_set_path_and_python_version 3.9.7
233239
make rebuild_updated_recipes
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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 should_build(self, arch):
33+
name = self.folder_name
34+
if self.ctx.has_package(name.replace("-", "_"), arch):
35+
info('Python package already exists in site-packages')
36+
return False
37+
info('{} apparently isn\'t already in site-packages'.format(name))
38+
return True
39+
40+
def get_recipe_env(self, arch):
41+
env = super().get_recipe_env(arch)
42+
# Requires rust
43+
build_target = RUST_ARCH_CODES[arch.arch]
44+
if which("rustup"):
45+
info("Ensuring rust build toolchain")
46+
shprint(sh.rustup, "target", "add", build_target)
47+
else:
48+
error(
49+
"Rust (`rustup`) was not found on host system. Please install it using:"
50+
"\n`curl https://sh.rustup.rs -sSf | sh`\n"
51+
)
52+
exit(1)
53+
54+
env["CARGO_BUILD_TARGET"] = build_target
55+
56+
env["PATH"] = ("{hostpython_dir}:{old_path}").format(
57+
hostpython_dir=self.get_recipe(
58+
"hostpython3", self.ctx
59+
).get_path_to_python(),
60+
old_path=env["PATH"],
61+
)
62+
return env
63+
64+
def configure_cargo(self, build_dir, arch, python_recipe):
65+
"""Writes the cargo configuration"""
66+
cargo_config = join(build_dir, ".cargo", "config.toml")
67+
config_string = [
68+
CARGO_CONFIG.format(
69+
arch_,
70+
join(
71+
self.ctx.ndk.llvm_prebuilt_dir,
72+
"bin",
73+
"{}{}-clang".format(
74+
# NDK's Clang format
75+
# aarch64-linux-android{ndk_api}-clang
76+
# i686-linux-android{ndk_api}-clang
77+
# x86_64-linux-android{ndk_api}-clang
78+
# armv7a-linux-androideabi{ndk_api}-clang
79+
arch_.replace("7", "7a")
80+
if arch_.startswith("armv7")
81+
else arch_,
82+
self.ctx.ndk_api,
83+
),
84+
),
85+
self.ctx.get_libs_dir(arch.arch),
86+
join(
87+
python_recipe.get_build_dir(arch.arch),
88+
"android-build",
89+
),
90+
)
91+
for arch_ in RUST_ARCH_CODES.values()
92+
]
93+
94+
if isfile(cargo_config):
95+
info("Writing cargo configuration")
96+
with open(cargo_config, "w") as file:
97+
file.write("".join(config_string)[1:])
98+
file.close()
99+
100+
def build_arch(self, arch):
101+
build_dir = self.get_build_dir(arch.arch)
102+
env = self.get_recipe_env(arch)
103+
python_recipe = self.get_recipe("python3", self.ctx)
104+
built_wheel = None
105+
self.configure_cargo(build_dir, arch, python_recipe)
106+
107+
# Check for maturin
108+
if not which("maturin"):
109+
error(
110+
"maturin was not found on host system, please install with pip and rerun"
111+
)
112+
exit(1)
113+
114+
with current_directory(build_dir):
115+
shprint(
116+
sh.maturin,
117+
"build",
118+
"-i",
119+
"python{}".format(".".join(python_recipe.version.split(".")[:2])),
120+
"--skip-auditwheel",
121+
_env=env,
122+
)
123+
built_wheel = realpath(glob.glob("target/wheels/*-linux_*.whl")[0])
124+
125+
if built_wheel:
126+
info("Installing built wheel '{}'".format(basename(built_wheel)))
127+
128+
# Use host pip to install wheel
129+
shprint(
130+
sh.pip,
131+
"install",
132+
built_wheel,
133+
"--platform",
134+
# Here RUST_ARCH_CODES[arch.arch] won't work
135+
# because file name is like "_linux_armv7l"
136+
# So do manual splitting
137+
# Example filename: pydantic_core-2.16.1-cp311-cp311-linux_armv7l.whl
138+
built_wheel.split("-")[-1].split(".")[0],
139+
"--no-deps",
140+
"--target",
141+
self.ctx.get_python_install_dir(arch.arch),
142+
"--upgrade",
143+
_env=env,
144+
)
145+
146+
147+
recipe = PydanticcoreRecipe()

0 commit comments

Comments
 (0)