Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ cmake_env_args = {} # env-specific cmake args to pass
include_flags = {} # include flags to pass -D
```

### CLI

`hatch-cpp` is integrated with [`hatch-build`](https://github.com/python-project-templates/hatch-build) to allow easy configuration of options via command line:

```bash
hatch-build \
-- \
--verbose \
--platform linux \
--vcpkg.vcpkg a/path/to/vcpkg.json \
--libraries.0.binding pybind11 \
--libraries.0.include-dirs cpp,another-dir
```

### Environment Variables

`hatch-cpp` will respect standard environment variables for compiler control.
Expand Down
4 changes: 4 additions & 0 deletions hatch_cpp/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from sys import platform as sys_platform, version_info
from typing import Any

from hatch_build import parse_extra_args_model
from hatchling.builders.hooks.plugin.interface import BuildHookInterface

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

# Parse override args
parse_extra_args_model(build_plan)

# Generate commands
build_plan.generate()

Expand Down
46 changes: 46 additions & 0 deletions hatch_cpp/tests/test_hatch_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from os import listdir
from pathlib import Path
from shutil import rmtree
from subprocess import check_call
from sys import modules, path, platform


class TestHatchBuild:
def test_hatch_build(self):
project = "test_project_hatch_build"

rmtree(f"hatch_cpp/tests/{project}/project/extension.so", ignore_errors=True)
rmtree(f"hatch_cpp/tests/{project}/project/extension.pyd", ignore_errors=True)
modules.pop("project", None)
modules.pop("project.extension", None)

# compile
check_call(
[
"hatch-build",
"--hooks-only",
"--",
"--libraries.0.name=project/extension",
"--libraries.0.sources=cpp/project/basic.cpp",
"--libraries.0.include-dirs=cpp",
"--libraries.0.binding=nanobind",
],
cwd=f"hatch_cpp/tests/{project}",
)

# assert built

if project == "test_project_limited_api" and platform != "win32":
assert "extension.abi3.so" in listdir(f"hatch_cpp/tests/{project}/project")
else:
if platform == "win32":
assert "extension.pyd" in listdir(f"hatch_cpp/tests/{project}/project")
else:
assert "extension.so" in listdir(f"hatch_cpp/tests/{project}/project")

# import
here = Path(__file__).parent / project
path.insert(0, str(here))
import project.extension

assert project.extension.hello() == "A string"
2 changes: 1 addition & 1 deletion hatch_cpp/tests/test_project_cmake/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ packages = ["project"]
packages = ["project"]

[tool.hatch.build.hooks.hatch-cpp]
verbose = true
verbose = false

[tool.hatch.build.hooks.hatch-cpp.cmake]
root = "CMakeLists.txt"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "project/basic.hpp"

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#include <nanobind/nanobind.h>
#include <nanobind/stl/string.h>

NB_MODULE(extension, m) {
m.def("hello", []() { return "A string"; });
}
Empty file.
36 changes: 36 additions & 0 deletions hatch_cpp/tests/test_project_hatch_build/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[build-system]
requires = ["hatchling>=1.20"]
build-backend = "hatchling.build"

[project]
name = "hatch-cpp-test-project-nanobind"
description = "Basic test project for hatch-cpp"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = [
"hatchling>=1.20",
"hatch-cpp",
]

[tool.hatch.build]
artifacts = [
"project/*.dll",
"project/*.dylib",
"project/*.so",
]

[tool.hatch.build.sources]
src = "/"

[tool.hatch.build.targets.sdist]
packages = ["project"]

[tool.hatch.build.targets.wheel]
packages = ["project"]

[tool.hatch.build.hooks.hatch-cpp]
verbose = true
libraries = [
# {name = "project/extension", sources = ["cpp/project/basic.cpp"], include-dirs = ["cpp"], binding = "nanobind"},
{name = "wrong", sources = ["wrong"], include-dirs = ["wrong"], binding = "generic"},
]
6 changes: 3 additions & 3 deletions hatch_cpp/toolchains/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from os import environ
from pathlib import Path
from sys import version_info
from typing import Any, Dict, Optional
from typing import Any, Dict, Optional, Union

from pydantic import BaseModel, Field

Expand All @@ -23,15 +23,15 @@


class HatchCppCmakeConfiguration(BaseModel):
root: Path
root: Optional[Path] = None
build: Path = Field(default_factory=lambda: Path("build"))
install: Optional[Path] = Field(default=None)

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

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

def generate(self, config) -> Dict[str, Any]:
commands = []
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "Hatch plugin for C++ builds"
readme = "README.md"
license = { text = "Apache-2.0" }
version = "0.1.9"
requires-python = ">=3.9"
requires-python = ">=3.10"
keywords = [
"hatch",
"python",
Expand All @@ -25,7 +25,6 @@ classifiers = [
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -35,6 +34,7 @@ classifiers = [

dependencies = [
"hatchling>=1.20",
"hatch-build>=0.4,<0.5",
"pydantic",
]

Expand All @@ -45,7 +45,7 @@ develop = [
"check-manifest",
"codespell>=2.4,<2.5",
"hatchling",
"hatch-build",
"hatch-build>=0.3.2",
"mdformat>=0.7.22,<1.1",
"mdformat-tables>=1",
"pytest",
Expand Down