hatch-cpp 0.4.2__tar.gz → 0.5.1__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.
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/.gitignore +5 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/PKG-INFO +17 -1
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/README.md +16 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/__init__.py +1 -1
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/config.py +13 -4
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/plugin.py +29 -19
- hatch_cpp-0.5.1/hatch_cpp/tests/test_project_pyodide/cpp/extension.cpp +9 -0
- hatch_cpp-0.5.1/hatch_cpp/tests/test_project_pyodide/pyodide_project/__init__.py +3 -0
- hatch_cpp-0.5.1/hatch_cpp/tests/test_project_pyodide/pyproject.toml +20 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_structs.py +54 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_vcpkg_ref.py +15 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/toolchains/common.py +20 -12
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/toolchains/vcpkg.py +6 -2
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/pyproject.toml +2 -2
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/LICENSE +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/hooks.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_hatch_build.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_platform_specific.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/CMakeLists.txt +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/Makefile +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/project/include/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/CMakeLists.txt +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/Makefile +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/project/include/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/vcpkg.json +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_classes/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_classes/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_classes/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_classes/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_toolchain/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_toolchain/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_toolchain/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_toolchain/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.cpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.hpp +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/project/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/pyproject.toml +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/vcpkg.json +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_projects.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/toolchains/__init__.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/toolchains/cmake.py +0 -0
- {hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/utils.py +0 -0
|
@@ -13,6 +13,10 @@ __pycache__/
|
|
|
13
13
|
*.exp
|
|
14
14
|
*.lib
|
|
15
15
|
|
|
16
|
+
# vcpkg
|
|
17
|
+
vcpkg/
|
|
18
|
+
vcpkg_installed/
|
|
19
|
+
|
|
16
20
|
# Rust
|
|
17
21
|
target
|
|
18
22
|
target-capi
|
|
@@ -142,6 +146,7 @@ hatch_cpp/labextension
|
|
|
142
146
|
|
|
143
147
|
# Emscripten SDK (locally installed)
|
|
144
148
|
emsdk
|
|
149
|
+
.pyodide_build/
|
|
145
150
|
|
|
146
151
|
# Mac
|
|
147
152
|
.DS_Store
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hatch-cpp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Hatch plugin for C++ builds
|
|
5
5
|
Project-URL: Repository, https://github.com/python-project-templates/hatch-cpp
|
|
6
6
|
Project-URL: Homepage, https://github.com/python-project-templates/hatch-cpp
|
|
@@ -227,5 +227,21 @@ options:
|
|
|
227
227
|
|
|
228
228
|
`hatch-cpp` will respect standard environment variables for compiler control, e.g. `CC`, `CXX`, `LD`, `CMAKE_GENERATOR`, `OSX_DEPLOYMENT_TARGET`, etc.
|
|
229
229
|
|
|
230
|
+
### Pyodide
|
|
231
|
+
|
|
232
|
+
Pyodide builds are detected from `PYODIDE_ABI_VERSION`. The hook preserves Pyodide's Emscripten compiler wrappers, gives extension modules CPython's Emscripten suffix, and emits the corresponding `pyemscripten` wheel platform tag. No project-specific build hook is required.
|
|
233
|
+
|
|
234
|
+
```toml
|
|
235
|
+
[tool.hatch.build.hooks.hatch-cpp]
|
|
236
|
+
libraries = [
|
|
237
|
+
{name = "project/extension", sources = ["cpp/extension.cpp"], binding = "pybind11"},
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
[tool.cibuildwheel.pyodide]
|
|
241
|
+
test-command = "python -c 'from project.extension import answer; assert answer() == 42'"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
When a `vcpkg.json` manifest is active, Emscripten builds use vcpkg's `wasm32-emscripten` community triplet. Package support varies by port.
|
|
245
|
+
|
|
230
246
|
> [!NOTE]
|
|
231
247
|
> This library was generated using [copier](https://copier.readthedocs.io/en/stable/) from the [Base Python Project Template repository](https://github.com/python-project-templates/base).
|
|
@@ -181,5 +181,21 @@ options:
|
|
|
181
181
|
|
|
182
182
|
`hatch-cpp` will respect standard environment variables for compiler control, e.g. `CC`, `CXX`, `LD`, `CMAKE_GENERATOR`, `OSX_DEPLOYMENT_TARGET`, etc.
|
|
183
183
|
|
|
184
|
+
### Pyodide
|
|
185
|
+
|
|
186
|
+
Pyodide builds are detected from `PYODIDE_ABI_VERSION`. The hook preserves Pyodide's Emscripten compiler wrappers, gives extension modules CPython's Emscripten suffix, and emits the corresponding `pyemscripten` wheel platform tag. No project-specific build hook is required.
|
|
187
|
+
|
|
188
|
+
```toml
|
|
189
|
+
[tool.hatch.build.hooks.hatch-cpp]
|
|
190
|
+
libraries = [
|
|
191
|
+
{name = "project/extension", sources = ["cpp/extension.cpp"], binding = "pybind11"},
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[tool.cibuildwheel.pyodide]
|
|
195
|
+
test-command = "python -c 'from project.extension import answer; assert answer() == 42'"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
When a `vcpkg.json` manifest is active, Emscripten builds use vcpkg's `wasm32-emscripten` community triplet. Package support varies by port.
|
|
199
|
+
|
|
184
200
|
> [!NOTE]
|
|
185
201
|
> This library was generated using [copier](https://copier.readthedocs.io/en/stable/) from the [Base Python Project Template repository](https://github.com/python-project-templates/base).
|
|
@@ -93,12 +93,19 @@ class HatchCppBuildPlan(HatchCppBuildConfig):
|
|
|
93
93
|
if "vcpkg" in self._active_toolchains:
|
|
94
94
|
log.warning("vcpkg toolchain is active; ensure that your compiler is configured to use vcpkg includes and libs.")
|
|
95
95
|
|
|
96
|
-
for library in self.libraries:
|
|
96
|
+
for library_index, library in enumerate(self.libraries):
|
|
97
97
|
compile_flags = self.platform.get_compile_flags(library, self.build_type)
|
|
98
98
|
link_flags = self.platform.get_link_flags(library, self.build_type)
|
|
99
|
-
self.
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
compiler = self.platform.cc if library.language == "c" else self.platform.cxx
|
|
100
|
+
if self.platform.platform == "emscripten":
|
|
101
|
+
objects = []
|
|
102
|
+
for source_index, source in enumerate(library.sources):
|
|
103
|
+
obj = Path("build/hatch-cpp") / f"{library_index}-{source_index}-{Path(source).stem}.o"
|
|
104
|
+
objects.append(str(obj))
|
|
105
|
+
self.commands.append(f"{compiler} -c {source} {compile_flags} -o {obj}")
|
|
106
|
+
self.commands.append(f"{compiler} {' '.join(objects)} {link_flags}")
|
|
107
|
+
else:
|
|
108
|
+
self.commands.append(f"{compiler} {' '.join(library.sources)} {compile_flags} {link_flags}")
|
|
102
109
|
|
|
103
110
|
if "cmake" in self._active_toolchains:
|
|
104
111
|
self.commands.extend(self.cmake.generate(self))
|
|
@@ -106,6 +113,8 @@ class HatchCppBuildPlan(HatchCppBuildConfig):
|
|
|
106
113
|
return self.commands
|
|
107
114
|
|
|
108
115
|
def execute(self):
|
|
116
|
+
if self.platform.platform == "emscripten" and "vanilla" in self._active_toolchains:
|
|
117
|
+
Path("build/hatch-cpp").mkdir(parents=True, exist_ok=True)
|
|
109
118
|
for command in self.commands:
|
|
110
119
|
ret = system_call(command)
|
|
111
120
|
if ret != 0:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from os import environ
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from platform import machine as platform_machine
|
|
5
|
-
from sys import
|
|
6
|
+
from sys import version_info
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
8
9
|
from hatch_build import parse_extra_args_model
|
|
@@ -14,6 +15,25 @@ from .utils import import_string
|
|
|
14
15
|
__all__ = ("HatchCppBuildHook",)
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def _wheel_tag(platform: str, machine: str, version_major: int, version_minor: int, abi3: bool) -> str:
|
|
19
|
+
if platform == "emscripten":
|
|
20
|
+
abi_version = environ.get("PYODIDE_ABI_VERSION")
|
|
21
|
+
if not abi_version:
|
|
22
|
+
raise ValueError("PYODIDE_ABI_VERSION is required for Emscripten wheel tags.")
|
|
23
|
+
return f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-pyemscripten_{abi_version}_wasm32"
|
|
24
|
+
|
|
25
|
+
if platform == "darwin":
|
|
26
|
+
os_name = "macosx_11_0"
|
|
27
|
+
elif platform == "linux":
|
|
28
|
+
os_name = "linux"
|
|
29
|
+
else:
|
|
30
|
+
os_name = "win"
|
|
31
|
+
# platform.machine() reports AMD64/ARM64 on Windows, but PEP 425 platform tags are lowercase
|
|
32
|
+
machine = machine.lower()
|
|
33
|
+
abi = "abi3" if abi3 else f"cp{version_major}{version_minor}"
|
|
34
|
+
return f"cp{version_major}{version_minor}-{abi}-{os_name}_{machine}"
|
|
35
|
+
|
|
36
|
+
|
|
17
37
|
class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
18
38
|
"""The hatch-cpp build hook."""
|
|
19
39
|
|
|
@@ -76,29 +96,19 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
|
76
96
|
machine = platform_machine()
|
|
77
97
|
version_major = version_info.major
|
|
78
98
|
version_minor = version_info.minor
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
build_data["tag"] = f"cp{version_major}{version_minor}-abi3-{os_name}_{machine}"
|
|
87
|
-
else:
|
|
88
|
-
build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"
|
|
99
|
+
build_data["tag"] = _wheel_tag(
|
|
100
|
+
build_plan.platform.platform,
|
|
101
|
+
machine,
|
|
102
|
+
version_major,
|
|
103
|
+
version_minor,
|
|
104
|
+
all(lib.py_limited_api for lib in build_plan.libraries),
|
|
105
|
+
)
|
|
89
106
|
else:
|
|
90
107
|
build_data["pure_python"] = False
|
|
91
108
|
machine = platform_machine()
|
|
92
109
|
version_major = version_info.major
|
|
93
110
|
version_minor = version_info.minor
|
|
94
|
-
|
|
95
|
-
if "darwin" in sys_platform:
|
|
96
|
-
os_name = "macosx_11_0"
|
|
97
|
-
elif "linux" in sys_platform:
|
|
98
|
-
os_name = "linux"
|
|
99
|
-
else:
|
|
100
|
-
os_name = "win"
|
|
101
|
-
build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"
|
|
111
|
+
build_data["tag"] = _wheel_tag(build_plan.platform.platform, machine, version_major, version_minor, False)
|
|
102
112
|
|
|
103
113
|
# force include libraries
|
|
104
114
|
for path in Path(".").rglob("*"):
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.20"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hatch-cpp-test-project-pyodide"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
requires-python = ">=3.14"
|
|
9
|
+
|
|
10
|
+
[tool.hatch.build.targets.wheel]
|
|
11
|
+
packages = ["pyodide_project"]
|
|
12
|
+
|
|
13
|
+
[tool.hatch.build.hooks.hatch-cpp]
|
|
14
|
+
verbose = true
|
|
15
|
+
libraries = [
|
|
16
|
+
{name = "pyodide_project/extension", sources = ["cpp/extension.cpp"], binding = "pybind11"},
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.cibuildwheel.pyodide]
|
|
20
|
+
test-command = "python -c 'from pyodide_project import answer; assert answer() == 42'"
|
|
@@ -8,6 +8,7 @@ from pydantic import ValidationError
|
|
|
8
8
|
from toml import loads
|
|
9
9
|
|
|
10
10
|
from hatch_cpp import HatchCppBuildConfig, HatchCppBuildPlan, HatchCppLibrary, HatchCppPlatform
|
|
11
|
+
from hatch_cpp.plugin import _wheel_tag
|
|
11
12
|
from hatch_cpp.toolchains.common import _normalize_rpath
|
|
12
13
|
|
|
13
14
|
|
|
@@ -58,6 +59,59 @@ class TestStructs:
|
|
|
58
59
|
assert "clang++" in hatch_build_config.platform.cxx
|
|
59
60
|
assert hatch_build_config.platform.toolchain == "gcc"
|
|
60
61
|
|
|
62
|
+
def test_pyodide_platform(self, monkeypatch: pytest.MonkeyPatch):
|
|
63
|
+
monkeypatch.setenv("PYODIDE_ABI_VERSION", "2026_0")
|
|
64
|
+
monkeypatch.setenv("CC", "/toolchain/cc")
|
|
65
|
+
monkeypatch.setenv("CXX", "/toolchain/c++")
|
|
66
|
+
|
|
67
|
+
platform = HatchCppPlatform.default()
|
|
68
|
+
library = HatchCppLibrary(name="project/extension", sources=["extension.cpp"], binding="pybind11")
|
|
69
|
+
|
|
70
|
+
assert platform.platform == "emscripten"
|
|
71
|
+
assert platform.toolchain == "clang"
|
|
72
|
+
assert platform.cc == "/toolchain/cc"
|
|
73
|
+
assert platform.cxx == "/toolchain/c++"
|
|
74
|
+
assert library.get_qualified_name(platform.platform) == (
|
|
75
|
+
f"project/extension.cpython-{version_info.major}{version_info.minor}-wasm32-emscripten.so"
|
|
76
|
+
)
|
|
77
|
+
assert "-undefined dynamic_lookup" not in platform.get_link_flags(library)
|
|
78
|
+
|
|
79
|
+
def test_pyodide_wheel_tag(self, monkeypatch: pytest.MonkeyPatch):
|
|
80
|
+
monkeypatch.setenv("PYODIDE_ABI_VERSION", "2026_0")
|
|
81
|
+
|
|
82
|
+
assert _wheel_tag("emscripten", "wasm32", 3, 14, False) == "cp314-cp314-pyemscripten_2026_0_wasm32"
|
|
83
|
+
|
|
84
|
+
def test_pyodide_wheel_tag_requires_abi_version(self, monkeypatch: pytest.MonkeyPatch):
|
|
85
|
+
monkeypatch.delenv("PYODIDE_ABI_VERSION", raising=False)
|
|
86
|
+
|
|
87
|
+
with pytest.raises(ValueError, match="PYODIDE_ABI_VERSION"):
|
|
88
|
+
_wheel_tag("emscripten", "wasm32", 3, 14, False)
|
|
89
|
+
|
|
90
|
+
def test_wheel_tag_machine_is_lowercased(self):
|
|
91
|
+
assert _wheel_tag("win32", "AMD64", 3, 11, False) == "cp311-cp311-win_amd64"
|
|
92
|
+
assert _wheel_tag("win32", "ARM64", 3, 11, True) == "cp311-abi3-win_arm64"
|
|
93
|
+
assert _wheel_tag("linux", "x86_64", 3, 11, False) == "cp311-cp311-linux_x86_64"
|
|
94
|
+
|
|
95
|
+
def test_pyodide_build_plan_compiles_objects_before_linking(self, monkeypatch: pytest.MonkeyPatch):
|
|
96
|
+
monkeypatch.setenv("PYODIDE_ABI_VERSION", "2026_0")
|
|
97
|
+
monkeypatch.setenv("CC", "/toolchain/cc")
|
|
98
|
+
monkeypatch.setenv("CXX", "/toolchain/c++")
|
|
99
|
+
build_plan = HatchCppBuildPlan(
|
|
100
|
+
name="pyodide-project",
|
|
101
|
+
libraries=[HatchCppLibrary(name="pyodide_project/extension", sources=["cpp/extension.cpp"], binding="pybind11")],
|
|
102
|
+
vcpkg=None,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
build_plan.generate()
|
|
106
|
+
|
|
107
|
+
assert len(build_plan.commands) == 2
|
|
108
|
+
assert build_plan.commands[0].startswith("/toolchain/c++ -c cpp/extension.cpp ")
|
|
109
|
+
assert build_plan.commands[0].endswith(" -o build/hatch-cpp/0-0-extension.o")
|
|
110
|
+
assert build_plan.commands[1].startswith("/toolchain/c++ build/hatch-cpp/0-0-extension.o ")
|
|
111
|
+
assert build_plan.commands[1].endswith(
|
|
112
|
+
f" -shared -o pyodide_project/extension.cpython-{version_info.major}{version_info.minor}-wasm32-emscripten.so"
|
|
113
|
+
)
|
|
114
|
+
|
|
61
115
|
def test_cmake_args_env_variable(self):
|
|
62
116
|
"""Test that CMAKE_ARGS environment variable is respected."""
|
|
63
117
|
txt = (Path(__file__).parent / "test_project_cmake" / "pyproject.toml").read_text()
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from types import SimpleNamespace
|
|
6
7
|
|
|
7
8
|
from hatch_cpp.toolchains.vcpkg import (
|
|
8
9
|
HatchCppVcpkgConfiguration,
|
|
@@ -87,6 +88,10 @@ class TestVcpkgRefConfig:
|
|
|
87
88
|
cfg = HatchCppVcpkgConfiguration(vcpkg_triplet="arm64-linux")
|
|
88
89
|
assert cfg.vcpkg_triplet == "arm64-linux"
|
|
89
90
|
|
|
91
|
+
def test_emscripten_triplet(self):
|
|
92
|
+
cfg = HatchCppVcpkgConfiguration(vcpkg_triplet="wasm32-emscripten")
|
|
93
|
+
assert cfg.vcpkg_triplet == "wasm32-emscripten"
|
|
94
|
+
|
|
90
95
|
|
|
91
96
|
class TestResolveVcpkgRef:
|
|
92
97
|
"""Tests for _resolve_vcpkg_ref priority logic."""
|
|
@@ -178,6 +183,16 @@ class TestVcpkgGenerate:
|
|
|
178
183
|
|
|
179
184
|
assert "./vcpkg/vcpkg install --triplet arm64-linux" in commands
|
|
180
185
|
|
|
186
|
+
def test_generate_detects_emscripten_triplet(self, tmp_path, monkeypatch):
|
|
187
|
+
monkeypatch.chdir(tmp_path)
|
|
188
|
+
self._make_vcpkg_env(tmp_path)
|
|
189
|
+
build_plan = SimpleNamespace(platform=SimpleNamespace(platform="emscripten"))
|
|
190
|
+
|
|
191
|
+
cfg = HatchCppVcpkgConfiguration()
|
|
192
|
+
commands = cfg.generate(build_plan)
|
|
193
|
+
|
|
194
|
+
assert "./vcpkg/vcpkg install --triplet wasm32-emscripten" in commands
|
|
195
|
+
|
|
181
196
|
def test_generate_uses_windows_command_paths(self, tmp_path, monkeypatch):
|
|
182
197
|
monkeypatch.chdir(tmp_path)
|
|
183
198
|
monkeypatch.setattr("hatch_cpp.toolchains.vcpkg.sys_platform", "win32")
|
|
@@ -4,7 +4,7 @@ from os import environ
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from re import match
|
|
6
6
|
from shutil import which
|
|
7
|
-
from sys import base_exec_prefix, exec_prefix, executable, platform as sys_platform
|
|
7
|
+
from sys import base_exec_prefix, exec_prefix, executable, platform as sys_platform, version_info
|
|
8
8
|
from sysconfig import get_config_var, get_path
|
|
9
9
|
from typing import Any, Literal
|
|
10
10
|
|
|
@@ -29,11 +29,12 @@ CompilerToolchain = Literal["gcc", "clang", "msvc"]
|
|
|
29
29
|
Toolchain = Literal["vcpkg", "cmake", "vanilla"]
|
|
30
30
|
Language = Literal["c", "c++"]
|
|
31
31
|
Binding = Literal["cpython", "pybind11", "nanobind", "generic"]
|
|
32
|
-
Platform = Literal["linux", "darwin", "win32"]
|
|
32
|
+
Platform = Literal["linux", "darwin", "win32", "emscripten"]
|
|
33
33
|
PlatformDefaults = {
|
|
34
34
|
"linux": {"CC": "gcc", "CXX": "g++", "LD": "ld"},
|
|
35
35
|
"darwin": {"CC": "clang", "CXX": "clang++", "LD": "ld"},
|
|
36
36
|
"win32": {"CC": "cl", "CXX": "cl", "LD": "link"},
|
|
37
|
+
"emscripten": {"CC": "emcc", "CXX": "em++", "LD": "wasm-ld"},
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
|
|
@@ -100,6 +101,10 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
|
|
|
100
101
|
return value
|
|
101
102
|
|
|
102
103
|
def get_qualified_name(self, platform):
|
|
104
|
+
if platform == "emscripten":
|
|
105
|
+
if self.binding == "generic":
|
|
106
|
+
return f"{self.name}.wasm"
|
|
107
|
+
return f"{self.name}.cpython-{version_info.major}{version_info.minor}-wasm32-emscripten.so"
|
|
103
108
|
if self.binding == "cpython" and not self.py_limited_api:
|
|
104
109
|
suffix = get_config_var("EXT_SUFFIX")
|
|
105
110
|
return f"{self.name}{suffix}"
|
|
@@ -242,9 +247,10 @@ class HatchCppPlatform(BaseModel):
|
|
|
242
247
|
|
|
243
248
|
@staticmethod
|
|
244
249
|
def default() -> HatchCppPlatform:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
250
|
+
platform = "emscripten" if environ.get("PYODIDE_ABI_VERSION") else sys_platform
|
|
251
|
+
CC = environ.get("CC", PlatformDefaults[platform]["CC"])
|
|
252
|
+
CXX = environ.get("CXX", PlatformDefaults[platform]["CXX"])
|
|
253
|
+
LD = environ.get("LD", PlatformDefaults[platform]["LD"])
|
|
248
254
|
if "gcc" in CC and "g++" in CXX:
|
|
249
255
|
toolchain = "gcc"
|
|
250
256
|
elif "clang" in CC and "clang++" in CXX:
|
|
@@ -252,11 +258,11 @@ class HatchCppPlatform(BaseModel):
|
|
|
252
258
|
elif "cl" in CC and "cl" in CXX:
|
|
253
259
|
toolchain = "msvc"
|
|
254
260
|
# Fallback to platform defaults
|
|
255
|
-
elif
|
|
261
|
+
elif platform == "linux":
|
|
256
262
|
toolchain = "gcc"
|
|
257
|
-
elif
|
|
263
|
+
elif platform in ("darwin", "emscripten"):
|
|
258
264
|
toolchain = "clang"
|
|
259
|
-
elif
|
|
265
|
+
elif platform == "win32":
|
|
260
266
|
toolchain = "msvc"
|
|
261
267
|
else:
|
|
262
268
|
toolchain = "gcc"
|
|
@@ -267,13 +273,13 @@ class HatchCppPlatform(BaseModel):
|
|
|
267
273
|
# LD = which("ld.mold")
|
|
268
274
|
# elif which("ld.lld"):
|
|
269
275
|
# LD = which("ld.lld")
|
|
270
|
-
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=
|
|
276
|
+
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=platform, toolchain=toolchain)
|
|
271
277
|
|
|
272
278
|
@model_validator(mode="wrap")
|
|
273
279
|
@classmethod
|
|
274
280
|
def validate_model(cls, data, handler):
|
|
275
281
|
model = handler(data)
|
|
276
|
-
if which("ccache") and not model.disable_ccache and model.toolchain in ["gcc", "clang"]:
|
|
282
|
+
if which("ccache") and model.platform != "emscripten" and not model.disable_ccache and model.toolchain in ["gcc", "clang"]:
|
|
277
283
|
if not model.cc.startswith("ccache "):
|
|
278
284
|
model.cc = f"ccache {model.cc}"
|
|
279
285
|
if not model.cxx.startswith("ccache "):
|
|
@@ -324,7 +330,8 @@ class HatchCppPlatform(BaseModel):
|
|
|
324
330
|
# Toolchain-specific flags
|
|
325
331
|
if self.toolchain == "gcc":
|
|
326
332
|
flags += " " + " ".join(f"-I{d}" for d in effective_include_dirs)
|
|
327
|
-
|
|
333
|
+
if self.platform != "emscripten":
|
|
334
|
+
flags += " -fPIC"
|
|
328
335
|
flags += " " + " ".join(effective_compile_args)
|
|
329
336
|
flags += " " + " ".join(f"-D{macro}" for macro in effective_define_macros)
|
|
330
337
|
flags += " " + " ".join(f"-U{macro}" for macro in effective_undef_macros)
|
|
@@ -332,7 +339,8 @@ class HatchCppPlatform(BaseModel):
|
|
|
332
339
|
flags += f" -std={library.std}"
|
|
333
340
|
elif self.toolchain == "clang":
|
|
334
341
|
flags += " ".join(f"-I{d}" for d in effective_include_dirs)
|
|
335
|
-
|
|
342
|
+
if self.platform != "emscripten":
|
|
343
|
+
flags += " -fPIC"
|
|
336
344
|
flags += " " + " ".join(effective_compile_args)
|
|
337
345
|
flags += " " + " ".join(f"-D{macro}" for macro in effective_define_macros)
|
|
338
346
|
flags += " " + " ".join(f"-U{macro}" for macro in effective_undef_macros)
|
|
@@ -29,6 +29,7 @@ VcpkgTriplet = Literal[
|
|
|
29
29
|
"arm64-uwp",
|
|
30
30
|
"arm64-windows",
|
|
31
31
|
"arm64-windows-static-md",
|
|
32
|
+
"wasm32-emscripten",
|
|
32
33
|
]
|
|
33
34
|
VcpkgPlatformDefaults = {
|
|
34
35
|
("linux", "x86_64"): "x64-linux",
|
|
@@ -38,6 +39,7 @@ VcpkgPlatformDefaults = {
|
|
|
38
39
|
("win32", "x86_64"): "x64-windows-static-md",
|
|
39
40
|
("win32", "AMD64"): "x64-windows-static-md",
|
|
40
41
|
("win32", "arm64"): "arm64-windows-static-md",
|
|
42
|
+
("emscripten", "wasm32"): "wasm32-emscripten",
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
|
|
@@ -122,9 +124,11 @@ class HatchCppVcpkgConfiguration(BaseModel):
|
|
|
122
124
|
commands = []
|
|
123
125
|
|
|
124
126
|
if self.vcpkg_triplet is None:
|
|
125
|
-
|
|
127
|
+
platform = config.platform.platform if config is not None else sys_platform
|
|
128
|
+
machine = "wasm32" if platform == "emscripten" else platform_machine()
|
|
129
|
+
self.vcpkg_triplet = VcpkgPlatformDefaults.get((platform, machine))
|
|
126
130
|
if self.vcpkg_triplet is None:
|
|
127
|
-
raise ValueError(f"Could not determine vcpkg triplet for platform {
|
|
131
|
+
raise ValueError(f"Could not determine vcpkg triplet for platform {platform} and architecture {machine}")
|
|
128
132
|
|
|
129
133
|
if self.vcpkg and Path(self.vcpkg).exists():
|
|
130
134
|
vcpkg_root = Path(self.vcpkg_root)
|
|
@@ -12,7 +12,7 @@ authors = [
|
|
|
12
12
|
description = "Hatch plugin for C++ builds"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
license = { text = "Apache-2.0" }
|
|
15
|
-
version = "0.
|
|
15
|
+
version = "0.5.1"
|
|
16
16
|
requires-python = ">=3.10"
|
|
17
17
|
keywords = [
|
|
18
18
|
"hatch",
|
|
@@ -79,7 +79,7 @@ Repository = "https://github.com/python-project-templates/hatch-cpp"
|
|
|
79
79
|
Homepage = "https://github.com/python-project-templates/hatch-cpp"
|
|
80
80
|
|
|
81
81
|
[tool.bumpversion]
|
|
82
|
-
current_version = "0.
|
|
82
|
+
current_version = "0.5.1"
|
|
83
83
|
commit = true
|
|
84
84
|
tag = true
|
|
85
85
|
commit_args = "-s"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_basic/cpp/project/basic.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake/cpp/project/basic.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/cpp/project/basic.hpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_cmake_vcpkg/project/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/cpp/project/basic.hpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_hatch_build/project/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.hpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_limited_api/project/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.hpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_nanobind/project/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_classes/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_override_toolchain/pyproject.toml
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind/cpp/project/basic.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.cpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.hpp
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/project/__init__.py
RENAMED
|
File without changes
|
{hatch_cpp-0.4.2 → hatch_cpp-0.5.1}/hatch_cpp/tests/test_project_pybind_vcpkg/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|