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
2 changes: 1 addition & 1 deletion docs/template-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- **Docs-only:** If `docs_only` is true, source package and test files are omitted.
- **Notebooks:** If `python_notebooks` is true, the template generates a `notebooks/` folder.
- **Paper:** If `latex_paper` is true, the template generates a `paper/` folder with a LaTeX manuscript scaffold and Make targets.
- **C++:** The bundled `cpp_template` is a separate Meson-based template with `include/`, `src/`, `tests/`, `examples/`, optional pybind11 Python bindings, Doxygen hooks, and the same repoman Make target names used by CI.
- **C++:** The bundled `cpp_template` is a separate Meson-based template with `include/`, `src/`, `tests/`, `examples/`, optional pybind11 Python bindings, meson-python wheel packaging, Doxygen hooks, and the same repoman Make target names used by CI.

## High-level generated layout

Expand Down
1 change: 1 addition & 0 deletions src/repoman/cpp_template/template/.gitignore.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

# docs and python tooling
.venv/
.wheel-venv/
.venvs/
uv.lock
*.egg-info/
Expand Down
18 changes: 16 additions & 2 deletions src/repoman/cpp_template/template/Makefile.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ SHELL := bash
version := 0.1.0

BUILD_DIR ?= build
DIST_DIR ?= dist
IMAGE ?= {{ project_name }}-dev
DOCS_CONFIG ?= config/mkdocs.yml
MESON ?= uv run meson
NINJA ?= uv run ninja
CLANG_FORMAT ?= clang-format
DOXYGEN ?= doxygen
WHEEL_VENV ?= .wheel-venv

cxx.format.files := $(shell find include src tests examples -type f \( -name "*.hpp" -o -name "*.cpp" \) 2>/dev/null || :)

.PHONY: setup configure build test clean distclean format format-check lint check-types type-check check-quality check docs docs-serve docs-check check-docs docs-api docs-check-api docker-build docker-shell help
.PHONY: setup configure build test clean distclean format format-check lint check-types type-check check-quality check build-wheel check-wheel docs docs-serve docs-check check-docs docs-api docs-check-api docker-build docker-shell help

setup: ## Install Python-hosted developer tooling.
@$(call i, Installing developer tooling)
Expand All @@ -34,7 +36,7 @@ clean: ## Clean compiled outputs while keeping the Meson build directory.
@if [ -d "$(BUILD_DIR)" ]; then $(NINJA) -C "$(BUILD_DIR)" clean; fi

distclean: ## Remove all generated build and docs outputs.
rm -rf "$(BUILD_DIR)" site
rm -rf "$(BUILD_DIR)" "$(DIST_DIR)" "$(WHEEL_VENV)" site

format: ## Format C++ sources with clang-format.
@$(call i, Formatting C++ sources)
Expand All @@ -55,6 +57,18 @@ check-quality: format-check lint ## Run formatting and compiler-warning checks.

check: check-quality check-types ## Run all quality checks.

build-wheel: ## Build a Python wheel for the pybind11 bindings.
@$(call i, Building Python wheel)
uv build --wheel --out-dir "$(DIST_DIR)"

check-wheel: ## Build, install, and import-check the Python wheel in a clean venv.
@$(call i, Checking Python wheel)
rm -rf "$(WHEEL_VENV)" "$(DIST_DIR)"
python_version="$$(uv run python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"; uv venv --python "$$python_version" "$(WHEEL_VENV)"
uv build --wheel --python "$(WHEEL_VENV)/bin/python" --out-dir "$(DIST_DIR)"
wheel_path="$$(find "$(DIST_DIR)" -maxdepth 1 -type f -name "*.whl" | sort | tail -n 1)"; uv pip install --python "$(WHEEL_VENV)/bin/python" "$$wheel_path"
"$(WHEEL_VENV)/bin/python" -c "import {{ cpp_namespace }}; assert {{ cpp_namespace }}.add(2, 3) == 5; assert {{ cpp_namespace }}.__version__ == '0.1.0'"

docs-api: ## Generate Doxygen API documentation.
@$(call i, Generating Doxygen documentation)
$(DOXYGEN) Doxyfile
Expand Down
6 changes: 6 additions & 0 deletions src/repoman/cpp_template/template/README.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ Disable them with:
uv run meson configure build -Dbuild_python_bindings=false
```

Build and validate a local wheel for the Python bindings:

```bash
make check-wheel
```

## Layout

```text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ Run all local checks:
```bash
make check
```

Build and validate the Python wheel in a clean temporary environment:

```bash
make check-wheel
```
3 changes: 3 additions & 0 deletions src/repoman/cpp_template/template/meson.build.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public_include = include_directories('include')
{{ cpp_library_name }}_sources,
include_directories: public_include,
install: true,
install_tag: 'runtime',
)

{{ cpp_library_name }}_dep = declare_dependency(
Expand All @@ -39,6 +40,7 @@ if get_option('build_cli')
'src/cli.cpp',
dependencies: [{{ cpp_library_name }}_dep],
install: true,
install_tag: 'bin',
)
endif

Expand All @@ -54,6 +56,7 @@ if get_option('build_python_bindings')
pybind11_dep,
],
install: true,
install_tag: 'python-runtime',
)
endif

Expand Down
20 changes: 18 additions & 2 deletions src/repoman/cpp_template/template/pyproject.toml.jinja
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
[build-system]
build-backend = "mesonpy"
requires = [
"meson>=1.5.0",
"meson-python>=0.17.0",
"ninja>=1.11.1",
"pybind11>=2.13.6",
]

[project]
name = "{{ project_name }}-docs"
name = "{{ project_name }}"
version = "0.1.0"
description = "Documentation and developer tooling for {{ project_name }}"
description = "{{ project_description }}"
authors = [{name = "{{ author_fullname }}", email = "{{ author_email }}"}]
license = "{{ copyright_license }}"
license-files = ["LICENSE"]
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
Expand All @@ -10,9 +22,13 @@ dependencies = []
package = false
default-groups = ["ci", "docs"]

[tool.meson-python.args]
install = ["--tags=runtime,python-runtime"]

[dependency-groups]
ci = [
"meson>=1.5.0",
"meson-python>=0.17.0",
"ninja>=1.11.1",
"pybind11>=2.13.6",
]
Expand Down
13 changes: 12 additions & 1 deletion tests/test_template/test_cpp_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,26 @@ def test_cpp_template_renders_spinach_style_structure(tmp_path: Path) -> None:
assert "'cpp_std=c++17'" in meson
assert "python.extension_module(" in meson
assert "dependency('pybind11')" in meson
assert "install_tag: 'runtime'" in meson
assert "install_tag: 'bin'" in meson
assert "install_tag: 'python-runtime'" in meson
assert "option('build_python_bindings'" in meson_options
assert 'build-backend = "mesonpy"' in pyproject
assert 'name = "sample-cpp"' in pyproject
assert 'description = "Sample C++ library"' in pyproject
assert '"meson-python>=0.17.0"' in pyproject
assert '"pybind11>=2.13.6"' in pyproject
assert 'install = ["--tags=runtime,python-runtime"]' in pyproject
assert 'module.attr("__version__") = sample_cpp::version();' in python_bindings
assert 'module.add(2, 3) == 5' in python_bindings_test
assert "module.add(2, 3) == 5" in python_bindings_test
assert 'module.version() == "0.1.0"' in python_bindings_test
assert 'module.__version__ == "0.1.0"' in python_bindings_test
assert "assert module.__doc__" in python_bindings_test
assert "except TypeError:" in python_bindings_test
assert "PYTHONPATH=build uv run python" in readme
assert "make check-wheel" in readme
assert "uv build --wheel" in makefile
assert "uv pip install --python" in makefile
assert "make check-docs" in github_ci
assert "make check" in github_ci
assert "make test" in github_ci
Expand Down
Loading