Skip to content

Commit fc6dce8

Browse files
authored
Merge pull request #67 from python-project-templates/tkp/tc
Allow for toolchain tweaks in pyproject.toml
2 parents 3ba860f + a2a9642 commit fc6dce8

File tree

9 files changed

+123
-7
lines changed

9 files changed

+123
-7
lines changed

hatch_cpp/structs.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,15 @@ def default() -> HatchCppPlatform:
102102
toolchain = "clang"
103103
elif "cl" in CC and "cl" in CXX:
104104
toolchain = "msvc"
105+
# Fallback to platform defaults
106+
elif platform == "linux":
107+
toolchain = "gcc"
108+
elif platform == "darwin":
109+
toolchain = "clang"
110+
elif platform == "win32":
111+
toolchain = "msvc"
105112
else:
106-
raise Exception(f"Unrecognized toolchain: {CC}, {CXX}")
113+
toolchain = "gcc"
107114

108115
# Customizations
109116
if which("ccache") and not environ.get("HATCH_CPP_DISABLE_CCACHE"):
@@ -117,6 +124,12 @@ def default() -> HatchCppPlatform:
117124
# LD = which("ld.lld")
118125
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=platform, toolchain=toolchain)
119126

127+
@staticmethod
128+
def platform_for_toolchain(toolchain: CompilerToolchain) -> HatchCppPlatform:
129+
platform = HatchCppPlatform.default()
130+
platform.toolchain = toolchain
131+
return platform
132+
120133
def get_compile_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
121134
flags = ""
122135

@@ -241,11 +254,27 @@ class HatchCppBuildConfig(BaseModel):
241254
cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None)
242255
platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
243256

244-
@model_validator(mode="after")
245-
def check_toolchain_matches_args(self):
246-
if self.cmake and self.libraries:
257+
@model_validator(mode="wrap")
258+
@classmethod
259+
def validate_model(cls, data, handler):
260+
if "toolchain" in data:
261+
data["platform"] = HatchCppPlatform.platform_for_toolchain(data["toolchain"])
262+
data.pop("toolchain")
263+
elif "platform" not in data:
264+
data["platform"] = HatchCppPlatform.default()
265+
if "cc" in data:
266+
data["platform"].cc = data["cc"]
267+
data.pop("cc")
268+
if "cxx" in data:
269+
data["platform"].cxx = data["cxx"]
270+
data.pop("cxx")
271+
if "ld" in data:
272+
data["platform"].ld = data["ld"]
273+
data.pop("ld")
274+
model = handler(data)
275+
if model.cmake and model.libraries:
247276
raise ValueError("Must not provide libraries when using cmake toolchain.")
248-
return self
277+
return model
249278

250279

251280
class HatchCppBuildPlan(HatchCppBuildConfig):
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include "Python.h"
3+
4+
PyObject* hello(PyObject*, PyObject*);
5+
6+
static PyMethodDef extension_methods[] = {
7+
{"hello", (PyCFunction)hello, METH_NOARGS},
8+
{nullptr, nullptr, 0, nullptr}
9+
};
10+
11+
static PyModuleDef extension_module = {
12+
PyModuleDef_HEAD_INIT, "extension", "extension", -1, extension_methods};
13+
14+
PyMODINIT_FUNC PyInit_extension(void) {
15+
Py_Initialize();
16+
return PyModule_Create(&extension_module);
17+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "project/basic.hpp"
2+
3+
PyObject* hello(PyObject*, PyObject*) {
4+
return PyUnicode_FromString("A string");
5+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include "Python.h"
3+
4+
PyObject* hello(PyObject*, PyObject*);
5+
6+
static PyMethodDef extension_methods[] = {
7+
{"hello", (PyCFunction)hello, METH_NOARGS},
8+
{nullptr, nullptr, 0, nullptr}
9+
};
10+
11+
static PyModuleDef extension_module = {
12+
PyModuleDef_HEAD_INIT, "extension", "extension", -1, extension_methods};
13+
14+
PyMODINIT_FUNC PyInit_extension(void) {
15+
Py_Initialize();
16+
return PyModule_Create(&extension_module);
17+
}

hatch_cpp/tests/test_project_override_toolchain/project/__init__.py

Whitespace-only changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[build-system]
2+
requires = ["hatchling>=1.20"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "hatch-cpp-test-project-toolchain"
7+
description = "Toolchain override test project for hatch-cpp"
8+
version = "0.1.0"
9+
requires-python = ">=3.9"
10+
dependencies = [
11+
"hatchling>=1.20",
12+
"hatch-cpp",
13+
]
14+
15+
[tool.hatch.build]
16+
artifacts = [
17+
"project/*.dll",
18+
"project/*.dylib",
19+
"project/*.so",
20+
]
21+
22+
[tool.hatch.build.sources]
23+
src = "/"
24+
25+
[tool.hatch.build.targets.sdist]
26+
packages = ["project"]
27+
28+
[tool.hatch.build.targets.wheel]
29+
packages = ["project"]
30+
31+
[tool.hatch.build.hooks.hatch-cpp]
32+
verbose = true
33+
libraries = [
34+
{name = "project/extension", sources = ["cpp/project/basic.cpp"], include-dirs = ["cpp"]}
35+
]
36+
toolchain = "gcc"
37+
cc = "clang"
38+
cxx = "clang++"

hatch_cpp/tests/test_projects.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class TestProject:
1313
[
1414
"test_project_basic",
1515
"test_project_override_classes",
16+
"test_project_override_classes",
17+
"test_project_override_toolchain",
1618
"test_project_pybind",
1719
"test_project_nanobind",
1820
"test_project_limited_api",
@@ -29,8 +31,7 @@ def test_basic(self, project):
2931
# compile
3032
check_call(
3133
[
32-
"hatchling",
33-
"build",
34+
"hatch-build",
3435
"--hooks-only",
3536
],
3637
cwd=f"hatch_cpp/tests/{project}",

hatch_cpp/tests/test_structs.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,11 @@ def test_cmake_args(self):
4646
assert f"-DHATCH_CPP_TEST_PROJECT_BASIC_PYTHON_VERSION=3.{version_info.minor}" in hatch_build_plan.commands[0]
4747
if hatch_build_plan.platform.platform == "darwin":
4848
assert "-DCMAKE_OSX_DEPLOYMENT_TARGET=11" in hatch_build_plan.commands[0]
49+
50+
def test_platform_toolchain_override(self):
51+
txt = (Path(__file__).parent / "test_project_override_toolchain" / "pyproject.toml").read_text()
52+
toml = loads(txt)
53+
hatch_build_config = HatchCppBuildConfig(name=toml["project"]["name"], **toml["tool"]["hatch"]["build"]["hooks"]["hatch-cpp"])
54+
assert "clang" in hatch_build_config.platform.cc
55+
assert "clang++" in hatch_build_config.platform.cxx
56+
assert hatch_build_config.platform.toolchain == "gcc"

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ develop = [
4545
"check-manifest",
4646
"codespell>=2.4,<2.5",
4747
"hatchling",
48+
"hatch-build",
4849
"mdformat>=0.7.22,<0.8",
4950
"mdformat-tables>=1",
5051
"pytest",

0 commit comments

Comments
 (0)