pyodide-build 0.26.0.dev0__tar.gz → 0.26.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyodide_build-0.26.2/.gitignore +43 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/PKG-INFO +24 -26
- pyodide_build-0.26.2/pyodide_build/__init__.py +1 -0
- pyodide_build-0.26.2/pyodide_build/_f2c_fixes.py +198 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/_py_compile.py +4 -3
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/bash_runner.py +1 -1
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/build_env.py +37 -134
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/buildall.py +14 -16
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/buildpkg.py +37 -22
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/build.py +1 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/build_recipes.py +7 -7
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/config.py +2 -2
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/create_zipfile.py +18 -0
- pyodide_build-0.26.2/pyodide_build/cli/xbuildenv.py +152 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/common.py +61 -4
- pyodide_build-0.26.2/pyodide_build/config.py +218 -0
- pyodide-build-0.26.0.dev0/pyodide_build/create_pypa_index.py → pyodide_build-0.26.2/pyodide_build/create_package_index.py +7 -7
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/io.py +48 -61
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/out_of_tree/build.py +5 -1
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/out_of_tree/venv.py +26 -4
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/pypabuild.py +11 -6
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/pywasmcross.py +11 -2
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/pyzip.py +14 -38
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/recipe.py +5 -5
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/vendor/_pypabuild.py +9 -0
- pyodide_build-0.26.2/pyodide_build/xbuildenv.py +345 -0
- pyodide_build-0.26.2/pyodide_build/xbuildenv_releases.py +159 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyproject.toml +16 -25
- pyodide-build-0.26.0.dev0/pyodide_build/__init__.py +0 -1
- pyodide-build-0.26.0.dev0/pyodide_build/_f2c_fixes.py +0 -600
- pyodide-build-0.26.0.dev0/pyodide_build/cli/xbuildenv.py +0 -61
- pyodide-build-0.26.0.dev0/pyodide_build/install_xbuildenv.py +0 -130
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/PKG-INFO +0 -52
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/SOURCES.txt +0 -44
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/dependency_links.txt +0 -1
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/entry_points.txt +0 -10
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/requires.txt +0 -27
- pyodide-build-0.26.0.dev0/pyodide_build.egg-info/top_level.txt +0 -2
- pyodide-build-0.26.0.dev0/setup.cfg +0 -4
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/LICENSE +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/README.md +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/__init__.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/py_compile.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/skeleton.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/cli/venv.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/create_xbuildenv.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/logger.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/mkpkg.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/out_of_tree/__init__.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/out_of_tree/pypi.py +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/tools/cmake/Modules/Platform/Emscripten.cmake +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/tools/emscripten.meson.cross +0 -0
- {pyodide-build-0.26.0.dev0 → pyodide_build-0.26.2}/pyodide_build/tools/pyo3_config.ini +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
*.a
|
|
2
|
+
*.o
|
|
3
|
+
*.pyc
|
|
4
|
+
*.gen.*
|
|
5
|
+
src/js/generated
|
|
6
|
+
*.out.*
|
|
7
|
+
|
|
8
|
+
*.egg-info/
|
|
9
|
+
|
|
10
|
+
__pycache__
|
|
11
|
+
|
|
12
|
+
.docker_home
|
|
13
|
+
.hypothesis
|
|
14
|
+
.idea
|
|
15
|
+
.mozilla
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.vscode
|
|
19
|
+
.venv*
|
|
20
|
+
tsconfig.tsbuildinfo
|
|
21
|
+
|
|
22
|
+
build
|
|
23
|
+
ccache
|
|
24
|
+
cpython/downloads
|
|
25
|
+
cpython/installs
|
|
26
|
+
cpython/build.log
|
|
27
|
+
dist*/
|
|
28
|
+
docs/_build/
|
|
29
|
+
emsdk/emsdk
|
|
30
|
+
geckodriver.log
|
|
31
|
+
node_modules
|
|
32
|
+
packages/.artifacts
|
|
33
|
+
packages/.build
|
|
34
|
+
packages/.libs
|
|
35
|
+
packages/*/build.log*
|
|
36
|
+
packages/build-logs
|
|
37
|
+
dist/
|
|
38
|
+
pyodide-build/**/build.log
|
|
39
|
+
xbuildenv/
|
|
40
|
+
pytest-pyodide
|
|
41
|
+
tools/symlinks
|
|
42
|
+
xbuildenv/
|
|
43
|
+
.pyodide-xbuildenv*
|
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: pyodide-build
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.2
|
|
4
4
|
Summary: "Tools for building Pyodide"
|
|
5
|
-
Author: Pyodide developers
|
|
6
|
-
License: MPL-2.0
|
|
7
5
|
Project-URL: Homepage, https://github.com/pyodide/pyodide
|
|
8
6
|
Project-URL: Bug Tracker, https://github.com/pyodide/pyodide/issues
|
|
9
7
|
Project-URL: Documentation, https://pyodide.org/en/stable/
|
|
10
|
-
|
|
8
|
+
Author: Pyodide developers
|
|
9
|
+
License: MPL-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
11
|
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
14
|
Requires-Python: >=3.12
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Requires-Dist:
|
|
17
|
-
Requires-Dist:
|
|
15
|
+
Requires-Dist: auditwheel-emscripten~=0.0.9
|
|
16
|
+
Requires-Dist: build~=1.2.0
|
|
17
|
+
Requires-Dist: cmake>=3.24
|
|
18
|
+
Requires-Dist: loky
|
|
18
19
|
Requires-Dist: packaging
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist: build>=1.0.0
|
|
21
|
-
Requires-Dist: virtualenv
|
|
22
|
-
Requires-Dist: pydantic<2,>=1.10.2
|
|
20
|
+
Requires-Dist: pydantic<3,>=2
|
|
23
21
|
Requires-Dist: pyodide-cli~=0.2.1
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
22
|
+
Requires-Dist: pyodide-lock==0.1.0a6
|
|
23
|
+
Requires-Dist: pyyaml
|
|
26
24
|
Requires-Dist: requests
|
|
27
|
-
Requires-Dist: types-requests
|
|
28
|
-
Requires-Dist: typer
|
|
29
|
-
Requires-Dist: auditwheel-emscripten~=0.0.9
|
|
30
|
-
Requires-Dist: pyodide-lock==0.1.0a4
|
|
31
25
|
Requires-Dist: resolvelib
|
|
32
26
|
Requires-Dist: rich
|
|
33
|
-
Requires-Dist:
|
|
27
|
+
Requires-Dist: ruamel-yaml
|
|
28
|
+
Requires-Dist: typer
|
|
29
|
+
Requires-Dist: types-requests
|
|
30
|
+
Requires-Dist: unearth~=0.6
|
|
31
|
+
Requires-Dist: virtualenv
|
|
32
|
+
Requires-Dist: wheel
|
|
34
33
|
Provides-Extra: test
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist: pytest-
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Requires-Dist: moto; extra == "deploy"
|
|
34
|
+
Requires-Dist: packaging; extra == 'test'
|
|
35
|
+
Requires-Dist: pytest-httpserver; extra == 'test'
|
|
36
|
+
Requires-Dist: pytest-pyodide==0.57.0; extra == 'test'
|
|
37
|
+
Requires-Dist: pytest<8.0.0; extra == 'test'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
41
39
|
|
|
42
40
|
# pyodide-build
|
|
43
41
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.26.2"
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from textwrap import dedent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def fix_f2c_input(f2c_input: Path) -> None:
|
|
9
|
+
if f2c_input.name.endswith("_flapack-f2pywrappers.f"):
|
|
10
|
+
content = f2c_input.read_text()
|
|
11
|
+
content = content.replace("character cmach", "integer cmach")
|
|
12
|
+
content = content.replace("character norm", "integer norm")
|
|
13
|
+
f2c_input.write_text(content)
|
|
14
|
+
return
|
|
15
|
+
|
|
16
|
+
if f2c_input.name in [
|
|
17
|
+
"_lapack_subroutine_wrappers.f",
|
|
18
|
+
"_blas_subroutine_wrappers.f",
|
|
19
|
+
]:
|
|
20
|
+
content = f2c_input.read_text()
|
|
21
|
+
content = content.replace("character", "integer")
|
|
22
|
+
content = content.replace(
|
|
23
|
+
"ret = chla_transtype(", "call chla_transtype(ret, 1,"
|
|
24
|
+
)
|
|
25
|
+
f2c_input.write_text(content)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def fix_f2c_output(f2c_output: Path) -> None:
|
|
29
|
+
"""
|
|
30
|
+
This function is called on the name of each C output file. It fixes up the C
|
|
31
|
+
output in various ways to compensate for the lack of f2c support for Fortran
|
|
32
|
+
90 and Fortran 95.
|
|
33
|
+
"""
|
|
34
|
+
if f2c_output.name == "_lapack_subroutine_wrappers.c":
|
|
35
|
+
content = f2c_output.read_text()
|
|
36
|
+
content = content.replace("integer chla_transtype__", "void chla_transtype__")
|
|
37
|
+
f2c_output.write_text(content)
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
if f2c_output.name.endswith("eupd.c"):
|
|
41
|
+
content = f2c_output.read_text()
|
|
42
|
+
content = re.sub(
|
|
43
|
+
r"ftnlen\s*(howmny_len|bmat_len),?", "", content, flags=re.MULTILINE
|
|
44
|
+
)
|
|
45
|
+
f2c_output.write_text(content)
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
if f2c_output.name.endswith("lansvd.c"):
|
|
49
|
+
content = f2c_output.read_text()
|
|
50
|
+
content += dedent(
|
|
51
|
+
"""
|
|
52
|
+
#include <time.h>
|
|
53
|
+
|
|
54
|
+
int second_(real *t) {
|
|
55
|
+
*t = clock()/1000;
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
"""
|
|
59
|
+
)
|
|
60
|
+
f2c_output.write_text(content)
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def scipy_fix_cfile(path: Path) -> None:
|
|
65
|
+
"""
|
|
66
|
+
Replace void return types with int return types in various generated .c and
|
|
67
|
+
.h files. We can't achieve this with a simple patch because these files are
|
|
68
|
+
not in the sdist, they are generated as part of the build.
|
|
69
|
+
"""
|
|
70
|
+
text = path.read_text()
|
|
71
|
+
text = text.replace("extern void F_WRAPPEDFUNC", "extern int F_WRAPPEDFUNC")
|
|
72
|
+
text = text.replace("extern void F_FUNC", "extern int F_FUNC")
|
|
73
|
+
text = text.replace("void (*f2py_func)", "int (*f2py_func)")
|
|
74
|
+
text = text.replace("static void cb_", "static int cb_")
|
|
75
|
+
text = text.replace("typedef void(*cb_", "typedef int(*cb_")
|
|
76
|
+
text = text.replace("void(*)", "int(*)")
|
|
77
|
+
text = text.replace("static void f2py_setup_", "static int f2py_setup_")
|
|
78
|
+
|
|
79
|
+
if path.name.endswith("_flapackmodule.c"):
|
|
80
|
+
text = text.replace(",size_t", "")
|
|
81
|
+
text = re.sub(r",slen\([a-z]*\)\)", ")", text)
|
|
82
|
+
|
|
83
|
+
path.write_text(text)
|
|
84
|
+
|
|
85
|
+
for lib in ["lapack", "blas"]:
|
|
86
|
+
if path.name.endswith(f"cython_{lib}.c"):
|
|
87
|
+
header_name = f"_{lib}_subroutines.h"
|
|
88
|
+
header_dir = path.parent
|
|
89
|
+
header_path = find_header(header_dir, header_name)
|
|
90
|
+
|
|
91
|
+
header_text = header_path.read_text()
|
|
92
|
+
header_text = header_text.replace("void F_FUNC", "int F_FUNC")
|
|
93
|
+
header_path.write_text(header_text)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def find_header(source_dir: Path, header_name: str) -> Path:
|
|
97
|
+
"""
|
|
98
|
+
Find the header file that corresponds to a source file.
|
|
99
|
+
"""
|
|
100
|
+
while not (header_path := source_dir / header_name).exists():
|
|
101
|
+
# meson copies the source files into a subdirectory of the build
|
|
102
|
+
source_dir = source_dir.parent
|
|
103
|
+
if source_dir == Path("/"):
|
|
104
|
+
raise RuntimeError(f"Could not find header file {header_name}")
|
|
105
|
+
|
|
106
|
+
return header_path
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def scipy_fixes(args: list[str]) -> None:
|
|
110
|
+
for arg in args:
|
|
111
|
+
if arg.endswith(".c"):
|
|
112
|
+
scipy_fix_cfile(Path(arg))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def replay_f2c(args: list[str], dryrun: bool = False) -> list[str] | None:
|
|
116
|
+
"""Apply f2c to compilation arguments
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
args
|
|
121
|
+
input compiler arguments
|
|
122
|
+
dryrun
|
|
123
|
+
if False run f2c on detected fortran files
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
new_args
|
|
128
|
+
output compiler arguments
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
Examples
|
|
132
|
+
--------
|
|
133
|
+
|
|
134
|
+
>>> replay_f2c(['gfortran', 'test.f'], dryrun=True)
|
|
135
|
+
['gcc', 'test.c']
|
|
136
|
+
"""
|
|
137
|
+
f2c_path = os.environ.get("F2C_PATH", "f2c")
|
|
138
|
+
|
|
139
|
+
new_args = ["gcc"]
|
|
140
|
+
found_source = False
|
|
141
|
+
for arg in args[1:]:
|
|
142
|
+
if not arg.endswith((".f", ".F")):
|
|
143
|
+
new_args.append(arg)
|
|
144
|
+
continue
|
|
145
|
+
found_source = True
|
|
146
|
+
filepath = Path(arg).resolve()
|
|
147
|
+
new_args.append(arg[:-2] + ".c")
|
|
148
|
+
if dryrun:
|
|
149
|
+
continue
|
|
150
|
+
fix_f2c_input(Path(arg))
|
|
151
|
+
if arg.endswith(".F"):
|
|
152
|
+
# .F files apparently expect to be run through the C
|
|
153
|
+
# preprocessor (they have #ifdef's in them)
|
|
154
|
+
# Use gfortran frontend, as gcc frontend might not be
|
|
155
|
+
# present on osx
|
|
156
|
+
# The file-system might be not case-sensitive,
|
|
157
|
+
# so take care to handle this by renaming.
|
|
158
|
+
# For preprocessing and further operation the
|
|
159
|
+
# expected file-name and extension needs to be preserved.
|
|
160
|
+
subprocess.check_call(
|
|
161
|
+
[
|
|
162
|
+
"gfortran",
|
|
163
|
+
"-E",
|
|
164
|
+
"-C",
|
|
165
|
+
"-P",
|
|
166
|
+
filepath,
|
|
167
|
+
"-o",
|
|
168
|
+
filepath.with_suffix(".f77"),
|
|
169
|
+
]
|
|
170
|
+
)
|
|
171
|
+
filepath = filepath.with_suffix(".f77")
|
|
172
|
+
# -R flag is important, it means that Fortran functions that
|
|
173
|
+
# return real e.g. sdot will be transformed into C functions
|
|
174
|
+
# that return float. For historic reasons, by default f2c
|
|
175
|
+
# transform them into functions that return a double. Using -R
|
|
176
|
+
# allows to match what OpenBLAS has done when they f2ced their
|
|
177
|
+
# Fortran files, see
|
|
178
|
+
# https://github.com/xianyi/OpenBLAS/pull/3539#issuecomment-1493897254
|
|
179
|
+
# for more details
|
|
180
|
+
with (
|
|
181
|
+
open(filepath) as input_pipe,
|
|
182
|
+
open(filepath.with_suffix(".c"), "w") as output_pipe,
|
|
183
|
+
):
|
|
184
|
+
subprocess.check_call(
|
|
185
|
+
[f2c_path, "-R"],
|
|
186
|
+
stdin=input_pipe,
|
|
187
|
+
stdout=output_pipe,
|
|
188
|
+
cwd=filepath.parent,
|
|
189
|
+
)
|
|
190
|
+
fix_f2c_output(Path(arg[:-2] + ".c"))
|
|
191
|
+
|
|
192
|
+
new_args_str = " ".join(args)
|
|
193
|
+
if ".so" in new_args_str and "libgfortran.so" not in new_args_str:
|
|
194
|
+
found_source = True
|
|
195
|
+
|
|
196
|
+
if not found_source:
|
|
197
|
+
return None
|
|
198
|
+
return new_args
|
|
@@ -122,9 +122,10 @@ def _compile(
|
|
|
122
122
|
else:
|
|
123
123
|
compression = zipfile.ZIP_STORED
|
|
124
124
|
|
|
125
|
-
with
|
|
126
|
-
input_path
|
|
127
|
-
|
|
125
|
+
with (
|
|
126
|
+
zipfile.ZipFile(input_path) as fh_zip_in,
|
|
127
|
+
TemporaryDirectory() as temp_dir_str,
|
|
128
|
+
):
|
|
128
129
|
temp_dir = Path(temp_dir_str)
|
|
129
130
|
output_path_tmp = temp_dir / output_name
|
|
130
131
|
with zipfile.ZipFile(
|
|
@@ -106,7 +106,7 @@ def get_bash_runner(
|
|
|
106
106
|
extra_envs: dict[str, str],
|
|
107
107
|
) -> Iterator[BashRunnerWithSharedEnvironment]:
|
|
108
108
|
pyodide_root = get_pyodide_root()
|
|
109
|
-
env = get_build_environment_vars()
|
|
109
|
+
env = get_build_environment_vars(pyodide_root)
|
|
110
110
|
env.update(extra_envs)
|
|
111
111
|
|
|
112
112
|
with BashRunnerWithSharedEnvironment(env=env) as b:
|
|
@@ -5,7 +5,6 @@ import functools
|
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
7
|
import subprocess
|
|
8
|
-
import tomllib
|
|
9
8
|
from collections.abc import Iterator
|
|
10
9
|
from contextlib import nullcontext, redirect_stdout
|
|
11
10
|
from io import StringIO
|
|
@@ -13,8 +12,8 @@ from pathlib import Path
|
|
|
13
12
|
|
|
14
13
|
from packaging.tags import Tag, compatible_tags, cpython_tags
|
|
15
14
|
|
|
16
|
-
from .common import
|
|
17
|
-
from .
|
|
15
|
+
from .common import search_pyproject_toml, xbuildenv_dirname
|
|
16
|
+
from .config import ConfigManager
|
|
18
17
|
from .recipe import load_all_recipes
|
|
19
18
|
|
|
20
19
|
RUST_BUILD_PRELUDE = """
|
|
@@ -23,47 +22,6 @@ rustup target add wasm32-unknown-emscripten --toolchain ${RUST_TOOLCHAIN}
|
|
|
23
22
|
"""
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
BUILD_VARS: set[str] = {
|
|
27
|
-
"CARGO_BUILD_TARGET",
|
|
28
|
-
"CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_LINKER",
|
|
29
|
-
"HOME",
|
|
30
|
-
"HOSTINSTALLDIR",
|
|
31
|
-
"HOSTSITEPACKAGES",
|
|
32
|
-
"NUMPY_LIB",
|
|
33
|
-
"PATH",
|
|
34
|
-
"PLATFORM_TRIPLET",
|
|
35
|
-
"PIP_CONSTRAINT",
|
|
36
|
-
"PYMAJOR",
|
|
37
|
-
"PYMICRO",
|
|
38
|
-
"PYMINOR",
|
|
39
|
-
"PYO3_CROSS_INCLUDE_DIR",
|
|
40
|
-
"PYO3_CROSS_LIB_DIR",
|
|
41
|
-
"PYODIDE_EMSCRIPTEN_VERSION",
|
|
42
|
-
"PYODIDE_JOBS",
|
|
43
|
-
"PYODIDE_PACKAGE_ABI",
|
|
44
|
-
"PYODIDE_ROOT",
|
|
45
|
-
"PYTHON_ARCHIVE_SHA256",
|
|
46
|
-
"PYTHON_ARCHIVE_URL",
|
|
47
|
-
"PYTHONINCLUDE",
|
|
48
|
-
"PYTHONPATH",
|
|
49
|
-
"PYVERSION",
|
|
50
|
-
"RUSTFLAGS",
|
|
51
|
-
"RUST_TOOLCHAIN",
|
|
52
|
-
"SIDE_MODULE_CFLAGS",
|
|
53
|
-
"SIDE_MODULE_CXXFLAGS",
|
|
54
|
-
"SIDE_MODULE_LDFLAGS",
|
|
55
|
-
"STDLIB_MODULE_CFLAGS",
|
|
56
|
-
"SYSCONFIGDATA_DIR",
|
|
57
|
-
"SYSCONFIG_NAME",
|
|
58
|
-
"TARGETINSTALLDIR",
|
|
59
|
-
"WASM_LIBRARY_DIR",
|
|
60
|
-
"CMAKE_TOOLCHAIN_FILE",
|
|
61
|
-
"PYO3_CONFIG_FILE",
|
|
62
|
-
"MESON_CROSS_FILE",
|
|
63
|
-
"PKG_CONFIG_LIBDIR",
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
25
|
@dataclasses.dataclass(eq=False, order=False, kw_only=True)
|
|
68
26
|
class BuildArgs:
|
|
69
27
|
"""
|
|
@@ -114,14 +72,16 @@ def _init_xbuild_env(*, quiet: bool = False) -> Path:
|
|
|
114
72
|
-------
|
|
115
73
|
The path to the Pyodide root directory inside the xbuild environment
|
|
116
74
|
"""
|
|
117
|
-
from . import
|
|
75
|
+
from .xbuildenv import CrossBuildEnvManager # avoid circular import
|
|
118
76
|
|
|
119
|
-
# TODO: Do not hardcode the path
|
|
120
77
|
xbuildenv_path = Path(xbuildenv_dirname()).resolve()
|
|
121
|
-
|
|
122
78
|
context = redirect_stdout(StringIO()) if quiet else nullcontext()
|
|
123
79
|
with context:
|
|
124
|
-
|
|
80
|
+
manager = CrossBuildEnvManager(xbuildenv_path)
|
|
81
|
+
if manager.current_version is None:
|
|
82
|
+
manager.install()
|
|
83
|
+
|
|
84
|
+
return manager.pyodide_root
|
|
125
85
|
|
|
126
86
|
|
|
127
87
|
@functools.cache
|
|
@@ -136,24 +96,13 @@ def search_pyodide_root(curdir: str | Path, *, max_depth: int = 10) -> Path | No
|
|
|
136
96
|
by looking for the pyproject.toml file in the parent directories
|
|
137
97
|
which contains [tool.pyodide] section.
|
|
138
98
|
"""
|
|
99
|
+
pyproject_path, pyproject_file = search_pyproject_toml(curdir, max_depth)
|
|
139
100
|
|
|
140
|
-
|
|
141
|
-
|
|
101
|
+
if pyproject_path is None or pyproject_file is None:
|
|
102
|
+
return None
|
|
142
103
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if not pyproject_file.is_file():
|
|
147
|
-
continue
|
|
148
|
-
|
|
149
|
-
try:
|
|
150
|
-
with pyproject_file.open("rb") as f:
|
|
151
|
-
configs = tomllib.load(f)
|
|
152
|
-
except tomllib.TOMLDecodeError as e:
|
|
153
|
-
raise ValueError(f"Could not parse {pyproject_file}.") from e
|
|
154
|
-
|
|
155
|
-
if "tool" in configs and "pyodide" in configs["tool"]:
|
|
156
|
-
return base
|
|
104
|
+
if "tool" in pyproject_file and "_pyodide" in pyproject_file["tool"]:
|
|
105
|
+
return pyproject_path.parent
|
|
157
106
|
|
|
158
107
|
return None
|
|
159
108
|
|
|
@@ -164,84 +113,33 @@ def in_xbuildenv() -> bool:
|
|
|
164
113
|
|
|
165
114
|
|
|
166
115
|
@functools.cache
|
|
167
|
-
def get_build_environment_vars() -> dict[str, str]:
|
|
116
|
+
def get_build_environment_vars(pyodide_root: Path) -> dict[str, str]:
|
|
168
117
|
"""
|
|
169
118
|
Get common environment variables for the in-tree and out-of-tree build.
|
|
170
119
|
"""
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
env["CMAKE_TOOLCHAIN_FILE"] = str(
|
|
184
|
-
tools_dir / "cmake/Modules/Platform/Emscripten.cmake"
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
if "PYO3_CONFIG_FILE" not in env:
|
|
188
|
-
env["PYO3_CONFIG_FILE"] = str(tools_dir / "pyo3_config.ini")
|
|
189
|
-
|
|
190
|
-
if "MESON_CROSS_FILE" not in env:
|
|
191
|
-
env["MESON_CROSS_FILE"] = str(tools_dir / "emscripten.meson.cross")
|
|
192
|
-
|
|
193
|
-
hostsitepackages = env["HOSTSITEPACKAGES"]
|
|
194
|
-
pythonpath = [
|
|
195
|
-
hostsitepackages,
|
|
196
|
-
]
|
|
197
|
-
env["PYTHONPATH"] = ":".join(pythonpath)
|
|
198
|
-
|
|
199
|
-
return env
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def _get_make_environment_vars(*, pyodide_root: Path | None = None) -> dict[str, str]:
|
|
203
|
-
"""Load environment variables from Makefile.envs
|
|
204
|
-
|
|
205
|
-
This allows us to set all build vars in one place
|
|
206
|
-
|
|
207
|
-
Parameters
|
|
208
|
-
----------
|
|
209
|
-
pyodide_root
|
|
210
|
-
The root directory of the Pyodide repository. If None, this will be inferred.
|
|
211
|
-
"""
|
|
212
|
-
|
|
213
|
-
PYODIDE_ROOT = get_pyodide_root() if pyodide_root is None else pyodide_root
|
|
214
|
-
environment = {}
|
|
215
|
-
result = subprocess.run(
|
|
216
|
-
["make", "-f", str(PYODIDE_ROOT / "Makefile.envs"), ".output_vars"],
|
|
217
|
-
capture_output=True,
|
|
218
|
-
text=True,
|
|
219
|
-
env={"PYODIDE_ROOT": str(PYODIDE_ROOT)},
|
|
120
|
+
config_manager = ConfigManager(pyodide_root)
|
|
121
|
+
env = config_manager.to_env()
|
|
122
|
+
|
|
123
|
+
env.update(
|
|
124
|
+
{
|
|
125
|
+
# This environment variable is used for packages to detect if they are built
|
|
126
|
+
# for pyodide during build time
|
|
127
|
+
"PYODIDE": "1",
|
|
128
|
+
# This is the legacy environment variable used for the aforementioned purpose
|
|
129
|
+
"PYODIDE_PACKAGE_ABI": "1",
|
|
130
|
+
"PYTHONPATH": env["HOSTSITEPACKAGES"],
|
|
131
|
+
}
|
|
220
132
|
)
|
|
221
133
|
|
|
222
|
-
|
|
223
|
-
logger.error("ERROR: Failed to load environment variables from Makefile.envs")
|
|
224
|
-
exit_with_stdio(result)
|
|
225
|
-
|
|
226
|
-
for line in result.stdout.splitlines():
|
|
227
|
-
equalPos = line.find("=")
|
|
228
|
-
if equalPos != -1:
|
|
229
|
-
varname = line[0:equalPos]
|
|
230
|
-
|
|
231
|
-
if varname not in BUILD_VARS:
|
|
232
|
-
continue
|
|
233
|
-
|
|
234
|
-
value = line[equalPos + 1 :]
|
|
235
|
-
value = value.strip("'").strip()
|
|
236
|
-
environment[varname] = value
|
|
237
|
-
return environment
|
|
134
|
+
return env
|
|
238
135
|
|
|
239
136
|
|
|
240
137
|
def get_build_flag(name: str) -> str:
|
|
241
138
|
"""
|
|
242
139
|
Get a value of a build flag.
|
|
243
140
|
"""
|
|
244
|
-
|
|
141
|
+
pyodide_root = get_pyodide_root()
|
|
142
|
+
build_vars = get_build_environment_vars(pyodide_root)
|
|
245
143
|
if name not in build_vars:
|
|
246
144
|
raise ValueError(f"Unknown build flag: {name}")
|
|
247
145
|
|
|
@@ -293,6 +191,11 @@ def platform() -> str:
|
|
|
293
191
|
return f"emscripten_{version}_wasm32"
|
|
294
192
|
|
|
295
193
|
|
|
194
|
+
def wheel_platform() -> str:
|
|
195
|
+
abi_version = get_build_flag("PYODIDE_ABI_VERSION")
|
|
196
|
+
return f"pyodide_{abi_version}_wasm32"
|
|
197
|
+
|
|
198
|
+
|
|
296
199
|
def pyodide_tags() -> Iterator[Tag]:
|
|
297
200
|
"""
|
|
298
201
|
Returns the sequence of tag triples for the Pyodide interpreter.
|
|
@@ -301,10 +204,10 @@ def pyodide_tags() -> Iterator[Tag]:
|
|
|
301
204
|
"""
|
|
302
205
|
PYMAJOR = get_pyversion_major()
|
|
303
206
|
PYMINOR = get_pyversion_minor()
|
|
304
|
-
|
|
207
|
+
PLATFORMS = [platform(), wheel_platform()]
|
|
305
208
|
python_version = (int(PYMAJOR), int(PYMINOR))
|
|
306
|
-
yield from cpython_tags(platforms=
|
|
307
|
-
yield from compatible_tags(platforms=
|
|
209
|
+
yield from cpython_tags(platforms=PLATFORMS, python_version=python_version)
|
|
210
|
+
yield from compatible_tags(platforms=PLATFORMS, python_version=python_version)
|
|
308
211
|
# Following line can be removed once packaging 22.0 is released and we update to it.
|
|
309
212
|
yield Tag(interpreter=f"cp{PYMAJOR}{PYMINOR}", abi="none", platform="any")
|
|
310
213
|
|
|
@@ -100,7 +100,7 @@ class BasePackage:
|
|
|
100
100
|
class Package(BasePackage):
|
|
101
101
|
def __init__(self, pkgdir: Path, config: MetaConfig):
|
|
102
102
|
self.pkgdir = pkgdir
|
|
103
|
-
self.meta = config.
|
|
103
|
+
self.meta = config.model_copy(deep=True)
|
|
104
104
|
|
|
105
105
|
self.name = self.meta.package.name
|
|
106
106
|
self.version = self.meta.package.version
|
|
@@ -772,16 +772,14 @@ def generate_lockfile(
|
|
|
772
772
|
) -> PyodideLockSpec:
|
|
773
773
|
"""Generate the package.json file"""
|
|
774
774
|
|
|
775
|
-
from . import __version__
|
|
776
|
-
|
|
777
775
|
# Build package.json data.
|
|
778
776
|
[platform, _, arch] = build_env.platform().rpartition("_")
|
|
779
777
|
info = {
|
|
780
778
|
"arch": arch,
|
|
781
779
|
"platform": platform,
|
|
782
|
-
|
|
783
|
-
"version": __version__,
|
|
780
|
+
"version": build_env.get_build_flag("PYODIDE_VERSION"),
|
|
784
781
|
"python": sys.version.partition(" ")[0],
|
|
782
|
+
"abi_version": build_env.get_build_flag("PYODIDE_ABI_VERSION"),
|
|
785
783
|
}
|
|
786
784
|
packages = generate_packagedata(output_dir, pkg_map)
|
|
787
785
|
lock_spec = PyodideLockSpec(info=info, packages=packages)
|
|
@@ -875,7 +873,7 @@ def install_packages(
|
|
|
875
873
|
"""
|
|
876
874
|
Install packages into the output directory.
|
|
877
875
|
- copies build artifacts (wheel, zip, ...) to the output directory
|
|
878
|
-
- create
|
|
876
|
+
- create pyodide-lock.json
|
|
879
877
|
|
|
880
878
|
|
|
881
879
|
pkg_map
|
|
@@ -905,15 +903,15 @@ def install_packages(
|
|
|
905
903
|
def set_default_build_args(build_args: BuildArgs) -> BuildArgs:
|
|
906
904
|
args = dataclasses.replace(build_args)
|
|
907
905
|
|
|
908
|
-
if args.cflags
|
|
909
|
-
args.cflags = build_env.get_build_flag("SIDE_MODULE_CFLAGS")
|
|
910
|
-
if args.cxxflags
|
|
911
|
-
args.cxxflags = build_env.get_build_flag("SIDE_MODULE_CXXFLAGS")
|
|
912
|
-
if args.ldflags
|
|
913
|
-
args.ldflags = build_env.get_build_flag("SIDE_MODULE_LDFLAGS")
|
|
914
|
-
if args.target_install_dir
|
|
915
|
-
args.target_install_dir = build_env.get_build_flag("TARGETINSTALLDIR")
|
|
916
|
-
if args.host_install_dir
|
|
917
|
-
args.host_install_dir = build_env.get_build_flag("HOSTINSTALLDIR")
|
|
906
|
+
if not args.cflags:
|
|
907
|
+
args.cflags = build_env.get_build_flag("SIDE_MODULE_CFLAGS")
|
|
908
|
+
if not args.cxxflags:
|
|
909
|
+
args.cxxflags = build_env.get_build_flag("SIDE_MODULE_CXXFLAGS")
|
|
910
|
+
if not args.ldflags:
|
|
911
|
+
args.ldflags = build_env.get_build_flag("SIDE_MODULE_LDFLAGS")
|
|
912
|
+
if not args.target_install_dir:
|
|
913
|
+
args.target_install_dir = build_env.get_build_flag("TARGETINSTALLDIR")
|
|
914
|
+
if not args.host_install_dir:
|
|
915
|
+
args.host_install_dir = build_env.get_build_flag("HOSTINSTALLDIR")
|
|
918
916
|
|
|
919
917
|
return args
|