hatch-cpp 0.1.6__py3-none-any.whl → 0.1.8__py3-none-any.whl

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/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.1.6"
1
+ __version__ = "0.1.8"
2
2
 
3
3
  from .hooks import hatch_register_build_hook
4
4
  from .plugin import HatchCppBuildHook
hatch_cpp/plugin.py CHANGED
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- import logging
4
- import os
5
- import platform as sysplatform
6
- import sys
7
- import typing as t
3
+ from logging import getLogger
4
+ from os import getenv
5
+ from pathlib import Path
6
+ from platform import machine as platform_machine
7
+ from sys import platform as sys_platform, version_info
8
+ from typing import Any
8
9
 
9
10
  from hatchling.builders.hooks.plugin.interface import BuildHookInterface
10
11
 
@@ -18,13 +19,14 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
18
19
  """The hatch-cpp build hook."""
19
20
 
20
21
  PLUGIN_NAME = "hatch-cpp"
21
- _logger = logging.getLogger(__name__)
22
+ _logger = getLogger(__name__)
22
23
 
23
- def initialize(self, version: str, build_data: dict[str, t.Any]) -> None:
24
+ def initialize(self, version: str, build_data: dict[str, Any]) -> None:
24
25
  """Initialize the plugin."""
25
26
  # Log some basic information
27
+ project_name = self.metadata.config["project"]["name"]
26
28
  self._logger.info("Initializing hatch-cpp plugin version %s", version)
27
- self._logger.info("Running hatch-cpp")
29
+ self._logger.info(f"Running hatch-cpp: {project_name}")
28
30
 
29
31
  # Only run if creating wheel
30
32
  # TODO: Add support for specify sdist-plan
@@ -34,7 +36,7 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
34
36
 
35
37
  # Skip if SKIP_HATCH_CPP is set
36
38
  # TODO: Support CLI once https://github.com/pypa/hatch/pull/1743
37
- if os.getenv("SKIP_HATCH_CPP"):
39
+ if getenv("SKIP_HATCH_CPP"):
38
40
  self._logger.info("Skipping the build hook since SKIP_HATCH_CPP was set")
39
41
  return
40
42
 
@@ -42,17 +44,13 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
42
44
  build_config_class = import_string(self.config["build-config-class"]) if "build-config-class" in self.config else HatchCppBuildConfig
43
45
 
44
46
  # Instantiate build config
45
- config = build_config_class(**self.config)
46
-
47
- # Grab libraries and platform
48
- libraries = config.libraries
49
- platform = config.platform
47
+ config = build_config_class(name=project_name, **self.config)
50
48
 
51
49
  # Get build plan class or use default
52
50
  build_plan_class = import_string(self.config["build-plan-class"]) if "build-plan-class" in self.config else HatchCppBuildPlan
53
51
 
54
52
  # Instantiate builder
55
- build_plan = build_plan_class(libraries=libraries, platform=platform)
53
+ build_plan = build_plan_class(**config.model_dump())
56
54
 
57
55
  # Generate commands
58
56
  build_plan.generate()
@@ -68,24 +66,48 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
68
66
  # Perform any cleanup actions
69
67
  build_plan.cleanup()
70
68
 
71
- # force include libraries
72
- for library in libraries:
73
- name = library.get_qualified_name(build_plan.platform.platform)
74
- build_data["force_include"][name] = name
69
+ if build_plan.libraries:
70
+ # force include libraries
71
+ for library in build_plan.libraries:
72
+ name = library.get_qualified_name(build_plan.platform.platform)
73
+ build_data["force_include"][name] = name
75
74
 
76
- if libraries:
77
75
  build_data["pure_python"] = False
78
- machine = sysplatform.machine()
79
- version_major = sys.version_info.major
80
- version_minor = sys.version_info.minor
81
- # TODO abi3
82
- if "darwin" in sys.platform:
76
+ machine = platform_machine()
77
+ version_major = version_info.major
78
+ version_minor = version_info.minor
79
+ if "darwin" in sys_platform:
83
80
  os_name = "macosx_11_0"
84
- elif "linux" in sys.platform:
81
+ elif "linux" in sys_platform:
85
82
  os_name = "linux"
86
83
  else:
87
84
  os_name = "win"
88
- if all([lib.py_limited_api for lib in libraries]):
85
+ if all([lib.py_limited_api for lib in build_plan.libraries]):
89
86
  build_data["tag"] = f"cp{version_major}{version_minor}-abi3-{os_name}_{machine}"
90
87
  else:
91
88
  build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"
89
+ else:
90
+ build_data["pure_python"] = False
91
+ machine = platform_machine()
92
+ version_major = version_info.major
93
+ version_minor = version_info.minor
94
+ # TODO abi3
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}"
102
+
103
+ # force include libraries
104
+ for path in Path(".").rglob("*"):
105
+ if path.is_dir():
106
+ continue
107
+ if str(path).startswith(str(build_plan.cmake.build)) or str(path).startswith("dist"):
108
+ continue
109
+ if path.suffix in (".pyd", ".dll", ".so", ".dylib"):
110
+ build_data["force_include"][str(path)] = str(path)
111
+
112
+ for path in build_data["force_include"]:
113
+ self._logger.warning(f"Force include: {path}")
hatch_cpp/structs.py CHANGED
@@ -1,12 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- from os import environ, system
3
+ from os import environ, system as system_call
4
4
  from pathlib import Path
5
5
  from re import match
6
6
  from shutil import which
7
- from sys import executable, platform as sys_platform
7
+ from sys import executable, platform as sys_platform, version_info
8
8
  from sysconfig import get_path
9
- from typing import Any, List, Literal, Optional
9
+ from typing import Any, Dict, List, Literal, Optional
10
10
 
11
11
  from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator
12
12
 
@@ -20,7 +20,7 @@ __all__ = (
20
20
  BuildType = Literal["debug", "release"]
21
21
  CompilerToolchain = Literal["gcc", "clang", "msvc"]
22
22
  Language = Literal["c", "c++"]
23
- Binding = Literal["cpython", "pybind11", "nanobind"]
23
+ Binding = Literal["cpython", "pybind11", "nanobind", "generic"]
24
24
  Platform = Literal["linux", "darwin", "win32"]
25
25
  PlatformDefaults = {
26
26
  "linux": {"CC": "gcc", "CXX": "g++", "LD": "ld"},
@@ -65,9 +65,9 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
65
65
 
66
66
  def get_qualified_name(self, platform):
67
67
  if platform == "win32":
68
- suffix = "dll" if self.binding == "none" else "pyd"
68
+ suffix = "dll" if self.binding == "generic" else "pyd"
69
69
  elif platform == "darwin":
70
- suffix = "dylib" if self.binding == "none" else "so"
70
+ suffix = "dylib" if self.binding == "generic" else "so"
71
71
  else:
72
72
  suffix = "so"
73
73
  if self.py_limited_api and platform != "win32":
@@ -78,6 +78,8 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
78
78
  def check_binding_and_py_limited_api(self):
79
79
  if self.binding == "pybind11" and self.py_limited_api:
80
80
  raise ValueError("pybind11 does not support Py_LIMITED_API")
81
+ if self.binding == "generic" and self.py_limited_api:
82
+ raise ValueError("Generic binding can not support Py_LIMITED_API")
81
83
  return self
82
84
 
83
85
 
@@ -100,8 +102,15 @@ class HatchCppPlatform(BaseModel):
100
102
  toolchain = "clang"
101
103
  elif "cl" in CC and "cl" in CXX:
102
104
  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"
103
112
  else:
104
- raise Exception(f"Unrecognized toolchain: {CC}, {CXX}")
113
+ toolchain = "gcc"
105
114
 
106
115
  # Customizations
107
116
  if which("ccache") and not environ.get("HATCH_CPP_DISABLE_CCACHE"):
@@ -115,11 +124,18 @@ class HatchCppPlatform(BaseModel):
115
124
  # LD = which("ld.lld")
116
125
  return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=platform, toolchain=toolchain)
117
126
 
127
+ @staticmethod
128
+ def platform_for_toolchain(toolchain: CompilerToolchain) -> HatchCppPlatform:
129
+ platform = HatchCppPlatform.default()
130
+ platform.toolchain = toolchain
131
+ return platform
132
+
118
133
  def get_compile_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
119
134
  flags = ""
120
135
 
121
136
  # Python.h
122
- library.include_dirs.append(get_path("include"))
137
+ if library.binding != "generic":
138
+ library.include_dirs.append(get_path("include"))
123
139
 
124
140
  if library.binding == "pybind11":
125
141
  import pybind11
@@ -217,36 +233,116 @@ class HatchCppPlatform(BaseModel):
217
233
  return flags
218
234
 
219
235
 
220
- class HatchCppBuildPlan(BaseModel):
221
- build_type: BuildType = "release"
236
+ class HatchCppCmakeConfiguration(BaseModel):
237
+ root: Path
238
+ build: Path = Field(default_factory=lambda: Path("build"))
239
+ install: Optional[Path] = Field(default=None)
240
+
241
+ cmake_arg_prefix: Optional[str] = Field(default=None)
242
+ cmake_args: Dict[str, str] = Field(default_factory=dict)
243
+ cmake_env_args: Dict[Platform, Dict[str, str]] = Field(default_factory=dict)
244
+
245
+ include_flags: Optional[Dict[str, Any]] = Field(default=None)
246
+
247
+
248
+ class HatchCppBuildConfig(BaseModel):
249
+ """Build config values for Hatch C++ Builder."""
250
+
251
+ verbose: Optional[bool] = Field(default=False)
252
+ name: Optional[str] = Field(default=None)
222
253
  libraries: List[HatchCppLibrary] = Field(default_factory=list)
223
- platform: HatchCppPlatform = Field(default_factory=HatchCppPlatform.default)
254
+ cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None)
255
+ platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
256
+
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:
276
+ raise ValueError("Must not provide libraries when using cmake toolchain.")
277
+ return model
278
+
279
+
280
+ class HatchCppBuildPlan(HatchCppBuildConfig):
281
+ build_type: BuildType = "release"
224
282
  commands: List[str] = Field(default_factory=list)
225
283
 
226
284
  def generate(self):
227
285
  self.commands = []
228
- for library in self.libraries:
229
- compile_flags = self.platform.get_compile_flags(library, self.build_type)
230
- link_flags = self.platform.get_link_flags(library, self.build_type)
231
- self.commands.append(
232
- f"{self.platform.cc if library.language == 'c' else self.platform.cxx} {' '.join(library.sources)} {compile_flags} {link_flags}"
233
- )
286
+ if self.libraries:
287
+ for library in self.libraries:
288
+ compile_flags = self.platform.get_compile_flags(library, self.build_type)
289
+ link_flags = self.platform.get_link_flags(library, self.build_type)
290
+ self.commands.append(
291
+ f"{self.platform.cc if library.language == 'c' else self.platform.cxx} {' '.join(library.sources)} {compile_flags} {link_flags}"
292
+ )
293
+ elif self.cmake:
294
+ # Derive prefix
295
+ if self.cmake.cmake_arg_prefix is None:
296
+ self.cmake.cmake_arg_prefix = f"{self.name.replace('.', '_').replace('-', '_').upper()}_"
297
+
298
+ # Append base command
299
+ self.commands.append(f"cmake {Path(self.cmake.root).parent} -DCMAKE_BUILD_TYPE={self.build_type} -B {self.cmake.build}")
300
+
301
+ # Setup install path
302
+ if self.cmake.install:
303
+ self.commands[-1] += f" -DCMAKE_INSTALL_PREFIX={self.cmake.install}"
304
+ else:
305
+ self.commands[-1] += f" -DCMAKE_INSTALL_PREFIX={Path(self.cmake.root).parent}"
306
+
307
+ # TODO: CMAKE_CXX_COMPILER
308
+ if self.platform.platform == "win32":
309
+ # TODO: prefix?
310
+ self.commands[-1] += f' -G "{environ.get("GENERATOR", "Visual Studio 17 2022")}"'
311
+
312
+ # Put in CMake flags
313
+ args = self.cmake.cmake_args.copy()
314
+ for platform, env_args in self.cmake.cmake_env_args.items():
315
+ if platform == self.platform.platform:
316
+ for key, value in env_args.items():
317
+ args[key] = value
318
+ for key, value in args.items():
319
+ self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}{key.upper()}={value}"
320
+
321
+ # Include customs
322
+ if self.cmake.include_flags:
323
+ if self.cmake.include_flags.get("python_version", False):
324
+ self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}PYTHON_VERSION={version_info.major}.{version_info.minor}"
325
+ if self.cmake.include_flags.get("manylinux", False) and self.platform.platform == "linux":
326
+ self.commands[-1] += f" -D{self.cmake.cmake_arg_prefix}MANYLINUX=ON"
327
+
328
+ # Include mac deployment target
329
+ if self.platform.platform == "darwin":
330
+ self.commands[-1] += f" -DCMAKE_OSX_DEPLOYMENT_TARGET={environ.get('OSX_DEPLOYMENT_TARGET', '11')}"
331
+
332
+ # Append build command
333
+ self.commands.append(f"cmake --build {self.cmake.build} --config {self.build_type}")
334
+
335
+ # Append install command
336
+ self.commands.append(f"cmake --install {self.cmake.build} --config {self.build_type}")
337
+
234
338
  return self.commands
235
339
 
236
340
  def execute(self):
237
341
  for command in self.commands:
238
- system(command)
342
+ system_call(command)
239
343
  return self.commands
240
344
 
241
345
  def cleanup(self):
242
346
  if self.platform.platform == "win32":
243
347
  for temp_obj in Path(".").glob("*.obj"):
244
348
  temp_obj.unlink()
245
-
246
-
247
- class HatchCppBuildConfig(BaseModel):
248
- """Build config values for Hatch C++ Builder."""
249
-
250
- verbose: Optional[bool] = Field(default=False)
251
- libraries: List[HatchCppLibrary] = Field(default_factory=list)
252
- platform: Optional[HatchCppPlatform] = Field(default_factory=HatchCppPlatform.default)
@@ -0,0 +1,92 @@
1
+ cmake_minimum_required(VERSION 3.20.0)
2
+ project(hatch-cpp-test-project-basic VERSION "0.1.0")
3
+ set(CMAKE_CXX_STANDARD 20)
4
+ include(CheckCCompilerFlag)
5
+ include(CheckLinkerFlag)
6
+
7
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
8
+ set(WIN32 ON)
9
+ set(MACOS OFF)
10
+ set(LINUX OFF)
11
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
12
+ set(WIN32 OFF)
13
+ set(MACOS ON)
14
+ set(LINUX OFF)
15
+ else()
16
+ set(WIN32 OFF)
17
+ set(MACOS OFF)
18
+ set(LINUX ON)
19
+ endif()
20
+
21
+ option(CMAKE_BUILD_TYPE "Release/Debug build" RELEASE)
22
+ option(HATCH_CPP_TEST_PROJECT_BASIC_BUILD_TESTS "Build tests" OFF)
23
+ option(HATCH_CPP_TEST_PROJECT_BASIC_MANYLINUX "Build for python's manylinux setup" OFF)
24
+
25
+ string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
26
+
27
+ set(BUILD_SHARED_LIBS TRUE)
28
+ set(CMAKE_MACOSX_RPATH TRUE)
29
+ set(CMAKE_SKIP_RPATH FALSE)
30
+ set(CMAKE_SKIP_BUILD_RPATH FALSE)
31
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
32
+ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
33
+ set(CMAKE_INSTALL_NAME_DIR "@rpath")
34
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
35
+
36
+ string(REGEX REPLACE "[ ]*-O[^ ]+[ ]*" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
37
+ string(REGEX REPLACE "[ ]*-Wl,-O2 -Wl,[^ ]+[ ]*" " " CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
38
+ string(REGEX REPLACE "[ ]*-Wl,-O2 -Wl,[^ ]+[ ]*" " " CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
39
+
40
+
41
+ if(MACOS)
42
+ set(CMAKE_THREAD_LIBS_INIT "-lpthread")
43
+ set(CMAKE_HAVE_THREADS_LIBRARY 1)
44
+ set(CMAKE_USE_WIN32_THREADS_INIT 0)
45
+ set(CMAKE_USE_PTHREADS_INIT 1)
46
+ set(THREADS_PREFER_PTHREAD_FLAG ON)
47
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup")
48
+ endif()
49
+
50
+
51
+ if(MACOS)
52
+ set(CMAKE_INSTALL_RPATH "@loader_path/")
53
+ elseif(LINUX)
54
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN")
55
+ endif()
56
+
57
+ if(WIN32)
58
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MP /bigobj")
59
+ foreach(warning 4244 4251 4267 4275 4290 4786 4305 4996)
60
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd${warning}")
61
+ endforeach(warning)
62
+ else()
63
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
64
+ -g \
65
+ -Wall \
66
+ -Werror \
67
+ -Wno-deprecated-declarations \
68
+ -Wno-deprecated \
69
+ ")
70
+ endif()
71
+
72
+
73
+ find_package(Python ${CSP_PYTHON_VERSION} EXACT REQUIRED COMPONENTS Interpreter Development.Module)
74
+ link_directories(${Python_LIBRARY_DIRS})
75
+ include_directories(${Python_INCLUDE_DIRS})
76
+
77
+ set(CMAKE_SHARED_LIBRARY_PREFIX "")
78
+ if(NOT WIN32)
79
+ set(CMAKE_SHARED_LIBRARY_SUFFIX .so)
80
+ else()
81
+ set(CMAKE_SHARED_LIBRARY_SUFFIX .pyd)
82
+ endif()
83
+
84
+ include_directories("${CMAKE_SOURCE_DIR}/cpp")
85
+
86
+ add_library(extension SHARED cpp/project/basic.cpp)
87
+ set_target_properties(extension PROPERTIES PUBLIC_HEADER cpp/project/basic.hpp)
88
+ install(TARGETS extension
89
+ PUBLIC_HEADER DESTINATION project/include/project
90
+ RUNTIME DESTINATION project/
91
+ LIBRARY DESTINATION project/
92
+ )
@@ -0,0 +1,140 @@
1
+ # CMAKE generated file: DO NOT EDIT!
2
+ # Generated by "Unix Makefiles" Generator, CMake Version 3.31
3
+
4
+ # Default target executed when no arguments are given to make.
5
+ default_target: all
6
+ .PHONY : default_target
7
+
8
+ # Allow only one "make -f Makefile2" at a time, but pass parallelism.
9
+ .NOTPARALLEL:
10
+
11
+ #=============================================================================
12
+ # Special targets provided by cmake.
13
+
14
+ # Disable implicit rules so canonical targets will work.
15
+ .SUFFIXES:
16
+
17
+ # Disable VCS-based implicit rules.
18
+ % : %,v
19
+
20
+ # Disable VCS-based implicit rules.
21
+ % : RCS/%
22
+
23
+ # Disable VCS-based implicit rules.
24
+ % : RCS/%,v
25
+
26
+ # Disable VCS-based implicit rules.
27
+ % : SCCS/s.%
28
+
29
+ # Disable VCS-based implicit rules.
30
+ % : s.%
31
+
32
+ .SUFFIXES: .hpux_make_needs_suffix_list
33
+
34
+ # Command-line flag to silence nested $(MAKE).
35
+ $(VERBOSE)MAKESILENT = -s
36
+
37
+ #Suppress display of executed commands.
38
+ $(VERBOSE).SILENT:
39
+
40
+ # A target that is always out of date.
41
+ cmake_force:
42
+ .PHONY : cmake_force
43
+
44
+ #=============================================================================
45
+ # Set environment variables for the build.
46
+
47
+ # The shell in which to execute make rules.
48
+ SHELL = /bin/sh
49
+
50
+ # The CMake executable.
51
+ CMAKE_COMMAND = /opt/homebrew/bin/cmake
52
+
53
+ # The command to remove a file.
54
+ RM = /opt/homebrew/bin/cmake -E rm -f
55
+
56
+ # Escaping for special characters.
57
+ EQUALS = =
58
+
59
+ # The top-level source directory on which CMake was run.
60
+ CMAKE_SOURCE_DIR = /Users/timkpaine/Developer/projects/templates/hatch-cpp/hatch_cpp/tests/test_project_cmake
61
+
62
+ # The top-level build directory on which CMake was run.
63
+ CMAKE_BINARY_DIR = /Users/timkpaine/Developer/projects/templates/hatch-cpp/hatch_cpp/tests/test_project_cmake
64
+
65
+ #=============================================================================
66
+ # Targets provided globally by CMake.
67
+
68
+ # Special rule for the target edit_cache
69
+ edit_cache:
70
+ @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake cache editor..."
71
+ /opt/homebrew/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
72
+ .PHONY : edit_cache
73
+
74
+ # Special rule for the target edit_cache
75
+ edit_cache/fast: edit_cache
76
+ .PHONY : edit_cache/fast
77
+
78
+ # Special rule for the target rebuild_cache
79
+ rebuild_cache:
80
+ @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..."
81
+ /opt/homebrew/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
82
+ .PHONY : rebuild_cache
83
+
84
+ # Special rule for the target rebuild_cache
85
+ rebuild_cache/fast: rebuild_cache
86
+ .PHONY : rebuild_cache/fast
87
+
88
+ # The main all target
89
+ all: cmake_check_build_system
90
+ $(CMAKE_COMMAND) -E cmake_progress_start /Users/timkpaine/Developer/projects/templates/hatch-cpp/hatch_cpp/tests/test_project_cmake/CMakeFiles /Users/timkpaine/Developer/projects/templates/hatch-cpp/hatch_cpp/tests/test_project_cmake//CMakeFiles/progress.marks
91
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all
92
+ $(CMAKE_COMMAND) -E cmake_progress_start /Users/timkpaine/Developer/projects/templates/hatch-cpp/hatch_cpp/tests/test_project_cmake/CMakeFiles 0
93
+ .PHONY : all
94
+
95
+ # The main clean target
96
+ clean:
97
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean
98
+ .PHONY : clean
99
+
100
+ # The main clean target
101
+ clean/fast: clean
102
+ .PHONY : clean/fast
103
+
104
+ # Prepare targets for installation.
105
+ preinstall: all
106
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
107
+ .PHONY : preinstall
108
+
109
+ # Prepare targets for installation.
110
+ preinstall/fast:
111
+ $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
112
+ .PHONY : preinstall/fast
113
+
114
+ # clear depends
115
+ depend:
116
+ $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
117
+ .PHONY : depend
118
+
119
+ # Help Target
120
+ help:
121
+ @echo "The following are some of the valid targets for this Makefile:"
122
+ @echo "... all (the default if no target is provided)"
123
+ @echo "... clean"
124
+ @echo "... depend"
125
+ @echo "... edit_cache"
126
+ @echo "... rebuild_cache"
127
+ .PHONY : help
128
+
129
+
130
+
131
+ #=============================================================================
132
+ # Special targets to cleanup operation of make.
133
+
134
+ # Special rule to run CMake to check the build system integrity.
135
+ # No rule that depends on this can have commands that come from listfiles
136
+ # because they might be regenerated.
137
+ cmake_check_build_system:
138
+ $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
139
+ .PHONY : cmake_check_build_system
140
+
@@ -0,0 +1,5 @@
1
+ #include "project/basic.hpp"
2
+
3
+ PyObject* hello(PyObject*, PyObject*) {
4
+ return PyUnicode_FromString("A string");
5
+ }
@@ -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
+ }
File without changes
@@ -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
+ }
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.20"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hatch-cpp-test-project-basic"
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
+
34
+ [tool.hatch.build.hooks.hatch-cpp.cmake]
35
+ root = "CMakeLists.txt"
36
+ cmake_args = {"BUILD_TESTS" = "OFF"}
37
+ include_flags = {"python_version" = true}
38
+ [tool.hatch.build.hooks.hatch-cpp.cmake.cmake_env_args]
39
+ linux = {"MANYLINUX" = "ON"}
@@ -0,0 +1,5 @@
1
+ #include "project/basic.hpp"
2
+
3
+ PyObject* hello(PyObject*, PyObject*) {
4
+ return PyUnicode_FromString("A string");
5
+ }
@@ -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
+ }
@@ -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++"
@@ -9,7 +9,17 @@ import pytest
9
9
 
10
10
  class TestProject:
11
11
  @pytest.mark.parametrize(
12
- "project", ["test_project_basic", "test_project_override_classes", "test_project_pybind", "test_project_nanobind", "test_project_limited_api"]
12
+ "project",
13
+ [
14
+ "test_project_basic",
15
+ "test_project_override_classes",
16
+ "test_project_override_classes",
17
+ "test_project_override_toolchain",
18
+ "test_project_pybind",
19
+ "test_project_nanobind",
20
+ "test_project_limited_api",
21
+ "test_project_cmake",
22
+ ],
13
23
  )
14
24
  def test_basic(self, project):
15
25
  # cleanup
@@ -21,8 +31,7 @@ class TestProject:
21
31
  # compile
22
32
  check_call(
23
33
  [
24
- "hatchling",
25
- "build",
34
+ "hatch-build",
26
35
  "--hooks-only",
27
36
  ],
28
37
  cwd=f"hatch_cpp/tests/{project}",
@@ -1,7 +1,11 @@
1
+ from pathlib import Path
2
+ from sys import version_info
3
+
1
4
  import pytest
2
5
  from pydantic import ValidationError
6
+ from toml import loads
3
7
 
4
- from hatch_cpp.structs import HatchCppLibrary, HatchCppPlatform
8
+ from hatch_cpp.structs import HatchCppBuildConfig, HatchCppBuildPlan, HatchCppLibrary, HatchCppPlatform
5
9
 
6
10
 
7
11
  class TestStructs:
@@ -24,3 +28,29 @@ class TestStructs:
24
28
 
25
29
  with pytest.raises(ValidationError):
26
30
  library.binding = "pybind11"
31
+
32
+ def test_cmake_args(self):
33
+ txt = (Path(__file__).parent / "test_project_cmake" / "pyproject.toml").read_text()
34
+ toml = loads(txt)
35
+ hatch_build_config = HatchCppBuildConfig(name=toml["project"]["name"], **toml["tool"]["hatch"]["build"]["hooks"]["hatch-cpp"])
36
+ hatch_build_plan = HatchCppBuildPlan(**hatch_build_config.model_dump())
37
+ hatch_build_plan.generate()
38
+
39
+ assert hatch_build_plan.commands[0].startswith("cmake .")
40
+ assert hatch_build_plan.commands[1].startswith("cmake --build build")
41
+ assert hatch_build_plan.commands[2].startswith("cmake --install build")
42
+
43
+ assert "-DCMAKE_BUILD_TYPE=release" in hatch_build_plan.commands[0]
44
+ assert "-B build" in hatch_build_plan.commands[0]
45
+ assert "-DHATCH_CPP_TEST_PROJECT_BASIC_BUILD_TESTS=OFF" in hatch_build_plan.commands[0]
46
+ assert f"-DHATCH_CPP_TEST_PROJECT_BASIC_PYTHON_VERSION=3.{version_info.minor}" in hatch_build_plan.commands[0]
47
+ if hatch_build_plan.platform.platform == "darwin":
48
+ 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"
hatch_cpp/utils.py CHANGED
@@ -10,123 +10,3 @@ _import_string_adapter = TypeAdapter(ImportString)
10
10
  @lru_cache(maxsize=None)
11
11
  def import_string(input_string: str):
12
12
  return _import_string_adapter.validate_python(input_string)
13
-
14
-
15
- # import multiprocessing
16
- # import os
17
- # import os.path
18
- # import platform
19
- # import subprocess
20
- # import sys
21
- # from shutil import which
22
- # from skbuild import setup
23
-
24
- # CSP_USE_VCPKG = os.environ.get("CSP_USE_VCPKG", "1").lower() in ("1", "on")
25
- # # Allow arg to override default / env
26
- # if "--csp-no-vcpkg" in sys.argv:
27
- # CSP_USE_VCPKG = False
28
- # sys.argv.remove("--csp-no-vcpkg")
29
-
30
- # # CMake Options
31
- # CMAKE_OPTIONS = (
32
- # ("CSP_BUILD_NO_CXX_ABI", "0"),
33
- # ("CSP_BUILD_TESTS", "1"),
34
- # ("CSP_MANYLINUX", "0"),
35
- # ("CSP_BUILD_KAFKA_ADAPTER", "1"),
36
- # ("CSP_BUILD_PARQUET_ADAPTER", "1"),
37
- # ("CSP_BUILD_WS_CLIENT_ADAPTER", "1"),
38
- # # NOTE:
39
- # # - omit vcpkg, need to test for presence
40
- # # - omit ccache, need to test for presence
41
- # # - omit coverage/gprof, not implemented
42
- # )
43
-
44
- # if sys.platform == "linux":
45
- # VCPKG_TRIPLET = "x64-linux"
46
- # elif sys.platform == "win32":
47
- # VCPKG_TRIPLET = "x64-windows-static-md"
48
- # else:
49
- # VCPKG_TRIPLET = None
50
-
51
- # # This will be used for e.g. the sdist
52
- # if CSP_USE_VCPKG:
53
- # if not os.path.exists("vcpkg"):
54
- # subprocess.call(["git", "clone", "https://github.com/Microsoft/vcpkg.git"])
55
- # if not os.path.exists("vcpkg/ports"):
56
- # subprocess.call(["git", "submodule", "update", "--init", "--recursive"])
57
- # if not os.path.exists("vcpkg/buildtrees"):
58
- # subprocess.call(["git", "pull"], cwd="vcpkg")
59
- # args = ["install"]
60
- # if VCPKG_TRIPLET is not None:
61
- # args.append(f"--triplet={VCPKG_TRIPLET}")
62
-
63
- # if os.name == "nt":
64
- # subprocess.call(["bootstrap-vcpkg.bat"], cwd="vcpkg", shell=True)
65
- # subprocess.call(["vcpkg.bat"] + args, cwd="vcpkg", shell=True)
66
- # else:
67
- # subprocess.call(["./bootstrap-vcpkg.sh"], cwd="vcpkg")
68
- # subprocess.call(["./vcpkg"] + args, cwd="vcpkg")
69
-
70
-
71
- # python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
72
- # cmake_args = [f"-DCSP_PYTHON_VERSION={python_version}"]
73
- # vcpkg_toolchain_file = os.path.abspath(
74
- # os.environ.get(
75
- # "CSP_VCPKG_PATH",
76
- # os.path.join("vcpkg/scripts/buildsystems/vcpkg.cmake"),
77
- # )
78
- # )
79
-
80
- # if CSP_USE_VCPKG and os.path.exists(vcpkg_toolchain_file):
81
- # cmake_args.extend(
82
- # [
83
- # "-DCMAKE_TOOLCHAIN_FILE={}".format(vcpkg_toolchain_file),
84
- # "-DCSP_USE_VCPKG=ON",
85
- # ]
86
- # )
87
-
88
- # if VCPKG_TRIPLET is not None:
89
- # cmake_args.append(f"-DVCPKG_TARGET_TRIPLET={VCPKG_TRIPLET}")
90
- # else:
91
- # cmake_args.append("-DCSP_USE_VCPKG=OFF")
92
-
93
- # if "CXX" in os.environ:
94
- # cmake_args.append(f"-DCMAKE_CXX_COMPILER={os.environ['CXX']}")
95
-
96
- # if "DEBUG" in os.environ:
97
- # cmake_args.append("-DCMAKE_BUILD_TYPE=Debug")
98
-
99
- # if platform.system() == "Windows":
100
- # import distutils.msvccompiler as dm
101
-
102
- # # https://wiki.python.org/moin/WindowsCompilers#Microsoft_Visual_C.2B-.2B-_14.0_with_Visual_Studio_2015_.28x86.2C_x64.2C_ARM.29
103
- # msvc = {
104
- # "12": "Visual Studio 12 2013",
105
- # "14": "Visual Studio 14 2015",
106
- # "14.0": "Visual Studio 14 2015",
107
- # "14.1": "Visual Studio 15 2017",
108
- # "14.2": "Visual Studio 16 2019",
109
- # "14.3": "Visual Studio 17 2022",
110
- # }.get(str(dm.get_build_version()), "Visual Studio 15 2017")
111
- # cmake_args.extend(
112
- # [
113
- # "-G",
114
- # os.environ.get("CSP_GENERATOR", msvc),
115
- # ]
116
- # )
117
-
118
- # for cmake_option, default in CMAKE_OPTIONS:
119
- # if os.environ.get(cmake_option, default).lower() in ("1", "on"):
120
- # cmake_args.append(f"-D{cmake_option}=ON")
121
- # else:
122
- # cmake_args.append(f"-D{cmake_option}=OFF")
123
-
124
- # if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
125
- # os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = str(multiprocessing.cpu_count())
126
-
127
- # if platform.system() == "Darwin":
128
- # os.environ["MACOSX_DEPLOYMENT_TARGET"] = os.environ.get("OSX_DEPLOYMENT_TARGET", "10.15")
129
- # cmake_args.append(f'-DCMAKE_OSX_DEPLOYMENT_TARGET={os.environ.get("OSX_DEPLOYMENT_TARGET", "10.15")}')
130
-
131
- # if which("ccache") and os.environ.get("CSP_USE_CCACHE", "") != "0":
132
- # cmake_args.append("-DCSP_USE_CCACHE=On")
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: hatch-cpp
3
+ Version: 0.1.8
4
+ Summary: Hatch plugin for C++ builds
5
+ Project-URL: Repository, https://github.com/python-project-templates/hatch-cpp
6
+ Project-URL: Homepage, https://github.com/python-project-templates/hatch-cpp
7
+ Author-email: the hatch-cpp authors <t.paine154@gmail.com>
8
+ License: Apache-2.0
9
+ License-File: LICENSE
10
+ Keywords: build,c++,cmake,cpp,hatch,python
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: hatchling>=1.20
25
+ Requires-Dist: pydantic
26
+ Provides-Extra: develop
27
+ Requires-Dist: build; extra == 'develop'
28
+ Requires-Dist: bump-my-version; extra == 'develop'
29
+ Requires-Dist: check-manifest; extra == 'develop'
30
+ Requires-Dist: codespell<2.5,>=2.4; extra == 'develop'
31
+ Requires-Dist: hatch-build; extra == 'develop'
32
+ Requires-Dist: hatchling; extra == 'develop'
33
+ Requires-Dist: mdformat-tables>=1; extra == 'develop'
34
+ Requires-Dist: mdformat<0.8,>=0.7.22; extra == 'develop'
35
+ Requires-Dist: nanobind<2.10.0; extra == 'develop'
36
+ Requires-Dist: pybind11; extra == 'develop'
37
+ Requires-Dist: pytest; extra == 'develop'
38
+ Requires-Dist: pytest-cov; extra == 'develop'
39
+ Requires-Dist: ruff; extra == 'develop'
40
+ Requires-Dist: toml; extra == 'develop'
41
+ Requires-Dist: twine; extra == 'develop'
42
+ Requires-Dist: uv; extra == 'develop'
43
+ Requires-Dist: wheel; extra == 'develop'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # hatch-cpp
47
+
48
+ Hatch plugin for C++ builds
49
+
50
+ [![Build Status](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yaml/badge.svg?branch=main&event=push)](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yaml)
51
+ [![codecov](https://codecov.io/gh/python-project-templates/hatch-cpp/branch/main/graph/badge.svg)](https://codecov.io/gh/python-project-templates/hatch-cpp)
52
+ [![License](https://img.shields.io/github/license/python-project-templates/hatch-cpp)](https://github.com/python-project-templates/hatch-cpp)
53
+ [![PyPI](https://img.shields.io/pypi/v/hatch-cpp.svg)](https://pypi.python.org/pypi/hatch-cpp)
54
+
55
+ ## Overview
56
+
57
+ A simple, extensible C++ build plugin for [hatch](https://hatch.pypa.io/latest/).
58
+
59
+ ```toml
60
+ [tool.hatch.build.hooks.hatch-cpp]
61
+ libraries = [
62
+ {name = "project/extension", sources = ["cpp/project/basic.cpp"], include-dirs = ["cpp"]}
63
+ ]
64
+ ```
65
+
66
+ For more complete systems, see:
67
+
68
+ - [scikit-build-core](https://github.com/scikit-build/scikit-build-core)
69
+ - [setuptools](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html)
70
+
71
+ ## Configuration
72
+
73
+ Configuration is driven from the `[tool.hatch.build.hooks.hatch-cpp]` hatch hook configuration field in a `pyproject.toml`.
74
+ It is designed to closely match existing Python/C/C++ packaging tools.
75
+
76
+ ```toml
77
+ verbose = true
78
+ libraries = { Library Args }
79
+ cmake = { CMake Args }
80
+ platform = { Platform, either "linux", "darwin", or "win32" }
81
+ ```
82
+
83
+ See the [test cases](./hatch_cpp/tests/) for more concrete examples.
84
+
85
+ `hatch-cpp` is driven by [pydantic](https://docs.pydantic.dev/latest/) models for configuration and execution of the build.
86
+ These models can themselves be overridden by setting `build-config-class` / `build-plan-class`.
87
+
88
+ ### Library Arguments
89
+
90
+ ```toml
91
+ name = "mylib"
92
+ sources = [
93
+ "path/to/file.cpp",
94
+ ]
95
+ language = "c++"
96
+
97
+ binding = "cpython" # or "pybind11", "nanobind", "generic"
98
+ std = "" # Passed to -std= or /std:
99
+
100
+ include_dirs = ["paths/to/add/to/-I"]
101
+ library_dirs = ["paths/to/add/to/-L"]
102
+ libraries = ["-llibraries_to_link"]
103
+
104
+ extra_compile_args = ["--extra-compile-args"]
105
+ extra_link_args = ["--extra-link-args"]
106
+ extra_objects = ["extra_objects"]
107
+
108
+ define_macros = ["-Ddefines_to_use"]
109
+ undef_macros = ["-Uundefines_to_use"]
110
+
111
+ py_limited_api = "cp39" # limited API to use
112
+ ```
113
+
114
+ ### CMake Arguments
115
+
116
+ `hatch-cpp` has some convenience integration with CMake.
117
+ Though this is not designed to be as full-featured as e.g. `scikit-build`, it should be satisfactory for many small projects.
118
+
119
+ ```toml
120
+ root = "path/to/cmake/root"
121
+ build = "path/to/cmake/build/folder"
122
+ install = "path/to/cmake/install/folder"
123
+
124
+ cmake_arg_prefix = "MYPROJECT_"
125
+ cmake_args = {} # any other cmake args to pass
126
+ cmake_env_args = {} # env-specific cmake args to pass
127
+
128
+ include_flags = {} # include flags to pass -D
129
+ ```
130
+
131
+ ### Environment Variables
132
+
133
+ `hatch-cpp` will respect standard environment variables for compiler control.
134
+
135
+ | Name | Default | Description |
136
+ | :------------------------- | :------ | :-------------------- |
137
+ | `CC` | | C Compiler override |
138
+ | `CXX` | | C++ Compiler override |
139
+ | `LD` | | Linker override |
140
+ | `HATCH_CPP_PLATFORM` | | Platform to build |
141
+ | `HATCH_CPP_DISABLE_CCACHE` | | Disable CCache usage |
142
+
143
+ > [!NOTE]
144
+ > 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).
@@ -1,14 +1,21 @@
1
- hatch_cpp/__init__.py,sha256=GpnnPr3BgwAuiIJ5m9xconjyECZPRPhuZQ9Q7HzWR0o,129
1
+ hatch_cpp/__init__.py,sha256=PG6tcYLGctNYf_dsMhB0P4JB-wagyyjDSzutyhUIgHY,129
2
2
  hatch_cpp/hooks.py,sha256=SQkF5WJIgzw-8rvlTzuQvBqdP6K3fHgnh6CZOZFag50,203
3
- hatch_cpp/plugin.py,sha256=iEDP6U7T_3G3m2ONCoYcMD3XNLq6ob_s_dn7AbtwnZ8,3238
4
- hatch_cpp/structs.py,sha256=o_XtXWVs0Zv0IARLY8R3NEbNqT2sAHQf7GNMIFggrKg,10681
5
- hatch_cpp/utils.py,sha256=topOiT6biVzisNAEKHvYzU-JdA56B3LA61jbU9fjAEQ,4444
6
- hatch_cpp/tests/test_projects.py,sha256=zE0XOPOuaQPfdvjgZRTPnsZ5gzK2shFPqKaPXkb5oSc,1509
7
- hatch_cpp/tests/test_structs.py,sha256=Qv2uBHwxf0edR8FIOnA2gj-AJgdsiDKt4vyK8HChAHg,851
3
+ hatch_cpp/plugin.py,sha256=AV5hcVcPPIOsalKKiGSXHcHrLlZ7mKIVc-g5_waK9fk,4403
4
+ hatch_cpp/structs.py,sha256=xNYK3ESJbwsNpBHOWCTtQgAGgjAuswcxUWNcegLI2w8,14898
5
+ hatch_cpp/utils.py,sha256=lxd3U3aMYsTS6DYMc1y17MR16LzgRzv92f_xh87LSg8,297
6
+ hatch_cpp/tests/test_projects.py,sha256=J3Ea6ADlDOe_bCXAyBlM-IHrmVAv_hTpFcB5_pzAoHY,1692
7
+ hatch_cpp/tests/test_structs.py,sha256=6S8LhX7TULd_UBwKCOWkH05MHPMSJMwEmzXktxWtV7s,2584
8
8
  hatch_cpp/tests/test_project_basic/pyproject.toml,sha256=eqM1UVpNmJWDfsuO18ZG_VOV9I4tAWgsM5Dhf49X8Nc,694
9
9
  hatch_cpp/tests/test_project_basic/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
10
10
  hatch_cpp/tests/test_project_basic/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
11
11
  hatch_cpp/tests/test_project_basic/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ hatch_cpp/tests/test_project_cmake/CMakeLists.txt,sha256=J6ijT9x9uSuisNEVIdFVgc_AstU9hbmIUbwvdjn_4GU,2795
13
+ hatch_cpp/tests/test_project_cmake/Makefile,sha256=Vfr65pvnktWTUeuvpMWqIxDR-7V9MT4PQAyj-WHG_pI,4357
14
+ hatch_cpp/tests/test_project_cmake/pyproject.toml,sha256=pu9RWhm_FY7KlcdOg2nmp-obnStnPJ04jW-bxei704w,814
15
+ hatch_cpp/tests/test_project_cmake/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
16
+ hatch_cpp/tests/test_project_cmake/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
17
+ hatch_cpp/tests/test_project_cmake/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ hatch_cpp/tests/test_project_cmake/project/include/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
12
19
  hatch_cpp/tests/test_project_limited_api/pyproject.toml,sha256=k_2y7YpZP5I-KPvKOZLmnHqoKXVE2oVM8fjxtRKoTo0,726
13
20
  hatch_cpp/tests/test_project_limited_api/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
14
21
  hatch_cpp/tests/test_project_limited_api/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
@@ -21,14 +28,18 @@ hatch_cpp/tests/test_project_override_classes/pyproject.toml,sha256=ykoZnutSWLYI
21
28
  hatch_cpp/tests/test_project_override_classes/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
22
29
  hatch_cpp/tests/test_project_override_classes/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
23
30
  hatch_cpp/tests/test_project_override_classes/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ hatch_cpp/tests/test_project_override_toolchain/pyproject.toml,sha256=t4zW-beld-tQzLsP7czECLMLYrewwF37EtNMrn-BRM8,758
32
+ hatch_cpp/tests/test_project_override_toolchain/cpp/project/basic.cpp,sha256=gQ2nmdLqIdgaqxSKvkN_vbp6Iv_pAoVIHETXPRnALb0,117
33
+ hatch_cpp/tests/test_project_override_toolchain/cpp/project/basic.hpp,sha256=SO5GhPj8k3RzWrfH37lFSDc8w1Vf3yqTUhxmr1hnoko,422
34
+ hatch_cpp/tests/test_project_override_toolchain/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
35
  hatch_cpp/tests/test_project_pybind/pyproject.toml,sha256=3IVlSprxx8XaC36s6OSgKr-OiSPn6cH6nX8pbp10suM,716
25
36
  hatch_cpp/tests/test_project_pybind/cpp/project/basic.cpp,sha256=MT3eCSQKr4guI3XZHV8kw8PoBGC6LEK8ClxnNMBnvnI,78
26
37
  hatch_cpp/tests/test_project_pybind/cpp/project/basic.hpp,sha256=LZSfCfhLY_91MBOxtnvDk7DcceO-9GhCHKpMnAjGe18,146
27
38
  hatch_cpp/tests/test_project_pybind/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
39
  hatch_cpp/toolchains/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
40
  hatch_cpp/toolchains/cmake.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- hatch_cpp-0.1.6.dist-info/METADATA,sha256=xxJ65xK090LytyqWJP48Gy4rQLOGJNIprM5UC2e8_gA,3003
31
- hatch_cpp-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
32
- hatch_cpp-0.1.6.dist-info/entry_points.txt,sha256=RgXfjpD4iwomJQK5n7FnPkXzb5fOnF5v3DI5hbkgVcw,30
33
- hatch_cpp-0.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
34
- hatch_cpp-0.1.6.dist-info/RECORD,,
41
+ hatch_cpp-0.1.8.dist-info/METADATA,sha256=i4Y3Pcky1C2Gp46UEjyn8MzV6uO0JnyltuA4JRTr3Uw,5529
42
+ hatch_cpp-0.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
+ hatch_cpp-0.1.8.dist-info/entry_points.txt,sha256=RgXfjpD4iwomJQK5n7FnPkXzb5fOnF5v3DI5hbkgVcw,30
44
+ hatch_cpp-0.1.8.dist-info/licenses/LICENSE,sha256=FWyFTpd5xXEz50QpGDtsyIv6dgR2z_dHdoab_Nq_KMw,11452
45
+ hatch_cpp-0.1.8.dist-info/RECORD,,
@@ -186,7 +186,11 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
+ <<<<<<< before updating
189
190
  Copyright [yyyy] [name of copyright owner]
191
+ =======
192
+ Copyright 2025 the hatch-cpp authors
193
+ >>>>>>> after updating
190
194
 
191
195
  Licensed under the Apache License, Version 2.0 (the "License");
192
196
  you may not use this file except in compliance with the License.
@@ -1,71 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: hatch-cpp
3
- Version: 0.1.6
4
- Summary: Hatch plugin for C++ builds
5
- Project-URL: Repository, https://github.com/python-project-templates/hatch-cpp
6
- Project-URL: Homepage, https://github.com/python-project-templates/hatch-cpp
7
- Author-email: the hatch-cpp authors <t.paine154@gmail.com>
8
- License: Apache-2.0
9
- License-File: LICENSE
10
- Keywords: build,c++,cmake,cpp,hatch,python
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: License :: OSI Approved :: Apache Software License
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: Implementation :: CPython
20
- Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.9
22
- Requires-Dist: hatchling>=1.20
23
- Requires-Dist: pydantic
24
- Provides-Extra: develop
25
- Requires-Dist: build; extra == 'develop'
26
- Requires-Dist: bump-my-version; extra == 'develop'
27
- Requires-Dist: check-manifest; extra == 'develop'
28
- Requires-Dist: nanobind; extra == 'develop'
29
- Requires-Dist: pybind11; extra == 'develop'
30
- Requires-Dist: pytest; extra == 'develop'
31
- Requires-Dist: pytest-cov; extra == 'develop'
32
- Requires-Dist: ruff<0.9,>=0.3; extra == 'develop'
33
- Requires-Dist: twine; extra == 'develop'
34
- Requires-Dist: wheel; extra == 'develop'
35
- Description-Content-Type: text/markdown
36
-
37
- # hatch-cpp
38
-
39
- Hatch plugin for C++ builds
40
-
41
- [![Build Status](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yml/badge.svg?branch=main&event=push)](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yml)
42
- [![codecov](https://codecov.io/gh/python-project-templates/hatch-cpp/branch/main/graph/badge.svg)](https://codecov.io/gh/python-project-templates/hatch-cpp)
43
- [![License](https://img.shields.io/github/license/python-project-templates/hatch-cpp)](https://github.com/python-project-templates/hatch-cpp)
44
- [![PyPI](https://img.shields.io/pypi/v/hatch-cpp.svg)](https://pypi.python.org/pypi/hatch-cpp)
45
-
46
- ## Overview
47
-
48
- A simple, extensible C++ build plugin for [hatch](https://hatch.pypa.io/latest/).
49
-
50
- ```toml
51
- [tool.hatch.build.hooks.hatch-cpp]
52
- libraries = [
53
- {name = "project/extension", sources = ["cpp/project/basic.cpp"], include-dirs = ["cpp"]}
54
- ]
55
- ```
56
-
57
- For more complete systems, see:
58
- - [scikit-build-core](https://github.com/scikit-build/scikit-build-core)
59
- - [setuptools](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html)
60
-
61
- ## Environment Variables
62
- | Name | Default | Description |
63
- |:-----|:--------|:------------|
64
- |`CC`| | |
65
- |`CXX`| | |
66
- |`LD`| | |
67
- |`HATCH_CPP_PLATFORM`| | |
68
- |`HATCH_CPP_DISABLE_CCACHE`| | |
69
-
70
- > [!NOTE]
71
- > 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).