Skip to content

Commit 5af6ca9

Browse files
authored
Merge pull request #73 from python-project-templates/tkp/cli
Add support for hatch-build
2 parents 69409c3 + 6f3b893 commit 5af6ca9

File tree

10 files changed

+115
-5
lines changed

10 files changed

+115
-5
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ cmake_env_args = {} # env-specific cmake args to pass
8383
include_flags = {} # include flags to pass -D
8484
```
8585

86+
### CLI
87+
88+
`hatch-cpp` is integrated with [`hatch-build`](https://github.com/python-project-templates/hatch-build) to allow easy configuration of options via command line:
89+
90+
```bash
91+
hatch-build \
92+
-- \
93+
--verbose \
94+
--platform linux \
95+
--vcpkg.vcpkg a/path/to/vcpkg.json \
96+
--libraries.0.binding pybind11 \
97+
--libraries.0.include-dirs cpp,another-dir
98+
```
99+
86100
### Environment Variables
87101

88102
`hatch-cpp` will respect standard environment variables for compiler control.

hatch_cpp/plugin.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from sys import platform as sys_platform, version_info
88
from typing import Any
99

10+
from hatch_build import parse_extra_args_model
1011
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
1112

1213
from .config import HatchCppBuildConfig, HatchCppBuildPlan
@@ -52,6 +53,9 @@ def initialize(self, version: str, build_data: dict[str, Any]) -> None:
5253
# Instantiate builder
5354
build_plan = build_plan_class(**config.model_dump())
5455

56+
# Parse override args
57+
parse_extra_args_model(build_plan)
58+
5559
# Generate commands
5660
build_plan.generate()
5761

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from os import listdir
2+
from pathlib import Path
3+
from shutil import rmtree
4+
from subprocess import check_call
5+
from sys import modules, path, platform
6+
7+
8+
class TestHatchBuild:
9+
def test_hatch_build(self):
10+
project = "test_project_hatch_build"
11+
12+
rmtree(f"hatch_cpp/tests/{project}/project/extension.so", ignore_errors=True)
13+
rmtree(f"hatch_cpp/tests/{project}/project/extension.pyd", ignore_errors=True)
14+
modules.pop("project", None)
15+
modules.pop("project.extension", None)
16+
17+
# compile
18+
check_call(
19+
[
20+
"hatch-build",
21+
"--hooks-only",
22+
"--",
23+
"--libraries.0.name=project/extension",
24+
"--libraries.0.sources=cpp/project/basic.cpp",
25+
"--libraries.0.include-dirs=cpp",
26+
"--libraries.0.binding=nanobind",
27+
],
28+
cwd=f"hatch_cpp/tests/{project}",
29+
)
30+
31+
# assert built
32+
33+
if project == "test_project_limited_api" and platform != "win32":
34+
assert "extension.abi3.so" in listdir(f"hatch_cpp/tests/{project}/project")
35+
else:
36+
if platform == "win32":
37+
assert "extension.pyd" in listdir(f"hatch_cpp/tests/{project}/project")
38+
else:
39+
assert "extension.so" in listdir(f"hatch_cpp/tests/{project}/project")
40+
41+
# import
42+
here = Path(__file__).parent / project
43+
path.insert(0, str(here))
44+
import project.extension
45+
46+
assert project.extension.hello() == "A string"

hatch_cpp/tests/test_project_cmake/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ packages = ["project"]
2929
packages = ["project"]
3030

3131
[tool.hatch.build.hooks.hatch-cpp]
32-
verbose = true
32+
verbose = false
3333

3434
[tool.hatch.build.hooks.hatch-cpp.cmake]
3535
root = "CMakeLists.txt"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include "project/basic.hpp"
2+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
#include <nanobind/nanobind.h>
3+
#include <nanobind/stl/string.h>
4+
5+
NB_MODULE(extension, m) {
6+
m.def("hello", []() { return "A string"; });
7+
}

hatch_cpp/tests/test_project_hatch_build/project/__init__.py

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[build-system]
2+
requires = ["hatchling>=1.20"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "hatch-cpp-test-project-nanobind"
7+
description = "Basic 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"], binding = "nanobind"},
35+
{name = "wrong", sources = ["wrong"], include-dirs = ["wrong"], binding = "generic"},
36+
]

hatch_cpp/toolchains/cmake.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from os import environ
44
from pathlib import Path
55
from sys import version_info
6-
from typing import Any, Dict, Optional
6+
from typing import Any, Dict, Optional, Union
77

88
from pydantic import BaseModel, Field
99

@@ -23,15 +23,15 @@
2323

2424

2525
class HatchCppCmakeConfiguration(BaseModel):
26-
root: Path
26+
root: Optional[Path] = None
2727
build: Path = Field(default_factory=lambda: Path("build"))
2828
install: Optional[Path] = Field(default=None)
2929

3030
cmake_arg_prefix: Optional[str] = Field(default=None)
3131
cmake_args: Dict[str, str] = Field(default_factory=dict)
3232
cmake_env_args: Dict[Platform, Dict[str, str]] = Field(default_factory=dict)
3333

34-
include_flags: Optional[Dict[str, Any]] = Field(default=None)
34+
include_flags: Optional[Dict[str, Union[str, int, float, bool]]] = Field(default=None)
3535

3636
def generate(self, config) -> Dict[str, Any]:
3737
commands = []

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ classifiers = [
3535

3636
dependencies = [
3737
"hatchling>=1.20",
38+
"hatch-build>=0.4,<0.5",
3839
"pydantic",
3940
]
4041

@@ -45,7 +46,7 @@ develop = [
4546
"check-manifest",
4647
"codespell>=2.4,<2.5",
4748
"hatchling",
48-
"hatch-build",
49+
"hatch-build>=0.3.2",
4950
"mdformat>=0.7.22,<1.1",
5051
"mdformat-tables>=1",
5152
"pytest",

0 commit comments

Comments
 (0)