hatch-cpp 0.0.0__tar.gz → 0.1.6__tar.gz
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-0.1.6/.gitignore +169 -0
- {hatch_cpp-0.0.0 → hatch_cpp-0.1.6}/LICENSE +1 -1
- hatch_cpp-0.1.6/PKG-INFO +71 -0
- hatch_cpp-0.1.6/README.md +35 -0
- hatch_cpp-0.1.6/hatch_cpp/__init__.py +5 -0
- hatch_cpp-0.1.6/hatch_cpp/hooks.py +10 -0
- hatch_cpp-0.1.6/hatch_cpp/plugin.py +91 -0
- hatch_cpp-0.1.6/hatch_cpp/structs.py +252 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_basic/cpp/project/basic.cpp +5 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_basic/cpp/project/basic.hpp +17 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_basic/project/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_basic/pyproject.toml +35 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.cpp +5 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_limited_api/cpp/project/basic.hpp +17 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_limited_api/project/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_limited_api/pyproject.toml +35 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.cpp +2 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_nanobind/cpp/project/basic.hpp +7 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_nanobind/project/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_nanobind/pyproject.toml +35 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_override_classes/cpp/project/basic.cpp +5 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_override_classes/cpp/project/basic.hpp +17 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_override_classes/project/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_override_classes/pyproject.toml +37 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_pybind/cpp/project/basic.cpp +6 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_pybind/cpp/project/basic.hpp +9 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_pybind/project/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_project_pybind/pyproject.toml +35 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_projects.py +46 -0
- hatch_cpp-0.1.6/hatch_cpp/tests/test_structs.py +26 -0
- hatch_cpp-0.1.6/hatch_cpp/toolchains/__init__.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/toolchains/cmake.py +0 -0
- hatch_cpp-0.1.6/hatch_cpp/utils.py +132 -0
- hatch_cpp-0.1.6/pyproject.toml +131 -0
- hatch_cpp-0.0.0/PKG-INFO +0 -224
- hatch_cpp-0.0.0/README.md +0 -1
- hatch_cpp-0.0.0/hatch_cpp.egg-info/PKG-INFO +0 -224
- hatch_cpp-0.0.0/hatch_cpp.egg-info/SOURCES.txt +0 -8
- hatch_cpp-0.0.0/hatch_cpp.egg-info/dependency_links.txt +0 -1
- hatch_cpp-0.0.0/hatch_cpp.egg-info/top_level.txt +0 -1
- hatch_cpp-0.0.0/pyproject.toml +0 -29
- hatch_cpp-0.0.0/setup.cfg +0 -4
- hatch_cpp-0.0.0/setup.py +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.a
|
|
8
|
+
*.so
|
|
9
|
+
*.obj
|
|
10
|
+
*.dll
|
|
11
|
+
*.exp
|
|
12
|
+
*.lib
|
|
13
|
+
|
|
14
|
+
# Distribution / packaging
|
|
15
|
+
.Python
|
|
16
|
+
env/
|
|
17
|
+
build/
|
|
18
|
+
develop-eggs/
|
|
19
|
+
dist/
|
|
20
|
+
downloads/
|
|
21
|
+
eggs/
|
|
22
|
+
.eggs/
|
|
23
|
+
lib/
|
|
24
|
+
lib64/
|
|
25
|
+
parts/
|
|
26
|
+
sdist/
|
|
27
|
+
var/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
*.manifest
|
|
36
|
+
*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
python_junit.xml
|
|
49
|
+
junit.xml
|
|
50
|
+
nosetests.xml
|
|
51
|
+
coverage.xml
|
|
52
|
+
*,cover
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache
|
|
55
|
+
.ruff_cache
|
|
56
|
+
js/playwright-report
|
|
57
|
+
|
|
58
|
+
# Translations
|
|
59
|
+
*.mo
|
|
60
|
+
*.pot
|
|
61
|
+
|
|
62
|
+
# Django stuff:
|
|
63
|
+
*.log
|
|
64
|
+
local_settings.py
|
|
65
|
+
|
|
66
|
+
# Flask instance folder
|
|
67
|
+
instance/
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
docs/source
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# IPython Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
*.ipynb
|
|
82
|
+
.autoversion
|
|
83
|
+
|
|
84
|
+
# pyenv
|
|
85
|
+
.python-version
|
|
86
|
+
|
|
87
|
+
# celery beat schedule file
|
|
88
|
+
celerybeat-schedule
|
|
89
|
+
|
|
90
|
+
# dotenv
|
|
91
|
+
.env
|
|
92
|
+
|
|
93
|
+
# virtualenv
|
|
94
|
+
venv/
|
|
95
|
+
ENV/
|
|
96
|
+
|
|
97
|
+
# Spyder project settings
|
|
98
|
+
.spyderproject
|
|
99
|
+
|
|
100
|
+
# Rope project settings
|
|
101
|
+
.ropeproject
|
|
102
|
+
|
|
103
|
+
# =========================
|
|
104
|
+
# Operating System Files
|
|
105
|
+
# =========================
|
|
106
|
+
|
|
107
|
+
# OSX
|
|
108
|
+
# =========================
|
|
109
|
+
|
|
110
|
+
.DS_Store
|
|
111
|
+
.AppleDouble
|
|
112
|
+
.LSOverride
|
|
113
|
+
|
|
114
|
+
# Thumbnails
|
|
115
|
+
._*
|
|
116
|
+
|
|
117
|
+
# Files that might appear in the root of a volume
|
|
118
|
+
.DocumentRevisions-V100
|
|
119
|
+
.fseventsd
|
|
120
|
+
.Spotlight-V100
|
|
121
|
+
.TemporaryItems
|
|
122
|
+
.Trashes
|
|
123
|
+
.VolumeIcon.icns
|
|
124
|
+
|
|
125
|
+
# Directories potentially created on remote AFP share
|
|
126
|
+
.AppleDB
|
|
127
|
+
.AppleDesktop
|
|
128
|
+
Network Trash Folder
|
|
129
|
+
Temporary Items
|
|
130
|
+
.apdisk
|
|
131
|
+
|
|
132
|
+
# Windows
|
|
133
|
+
# =========================
|
|
134
|
+
|
|
135
|
+
# Windows image file caches
|
|
136
|
+
Thumbs.db
|
|
137
|
+
ehthumbs.db
|
|
138
|
+
|
|
139
|
+
# Folder config file
|
|
140
|
+
Desktop.ini
|
|
141
|
+
|
|
142
|
+
# Recycle Bin used on file shares
|
|
143
|
+
$RECYCLE.BIN/
|
|
144
|
+
|
|
145
|
+
# Windows Installer files
|
|
146
|
+
*.cab
|
|
147
|
+
*.msi
|
|
148
|
+
*.msm
|
|
149
|
+
*.msp
|
|
150
|
+
|
|
151
|
+
# Windows shortcuts
|
|
152
|
+
*.lnk
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# NPM
|
|
156
|
+
# ----
|
|
157
|
+
**/node_modules/
|
|
158
|
+
|
|
159
|
+
# Coverage data
|
|
160
|
+
# -------------
|
|
161
|
+
**/coverage/
|
|
162
|
+
|
|
163
|
+
# Notebook and lab extensions
|
|
164
|
+
|
|
165
|
+
nbprint/extension/*
|
|
166
|
+
nbprint/templates/nbprint/static/*
|
|
167
|
+
nbprint/voila/static/*
|
|
168
|
+
tmp.html
|
|
169
|
+
examples/output/
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
hatch_cpp-0.1.6/PKG-INFO
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
[](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yml)
|
|
42
|
+
[](https://codecov.io/gh/python-project-templates/hatch-cpp)
|
|
43
|
+
[](https://github.com/python-project-templates/hatch-cpp)
|
|
44
|
+
[](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).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# hatch-cpp
|
|
2
|
+
|
|
3
|
+
Hatch plugin for C++ builds
|
|
4
|
+
|
|
5
|
+
[](https://github.com/python-project-templates/hatch-cpp/actions/workflows/build.yml)
|
|
6
|
+
[](https://codecov.io/gh/python-project-templates/hatch-cpp)
|
|
7
|
+
[](https://github.com/python-project-templates/hatch-cpp)
|
|
8
|
+
[](https://pypi.python.org/pypi/hatch-cpp)
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
A simple, extensible C++ build plugin for [hatch](https://hatch.pypa.io/latest/).
|
|
13
|
+
|
|
14
|
+
```toml
|
|
15
|
+
[tool.hatch.build.hooks.hatch-cpp]
|
|
16
|
+
libraries = [
|
|
17
|
+
{name = "project/extension", sources = ["cpp/project/basic.cpp"], include-dirs = ["cpp"]}
|
|
18
|
+
]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For more complete systems, see:
|
|
22
|
+
- [scikit-build-core](https://github.com/scikit-build/scikit-build-core)
|
|
23
|
+
- [setuptools](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html)
|
|
24
|
+
|
|
25
|
+
## Environment Variables
|
|
26
|
+
| Name | Default | Description |
|
|
27
|
+
|:-----|:--------|:------------|
|
|
28
|
+
|`CC`| | |
|
|
29
|
+
|`CXX`| | |
|
|
30
|
+
|`LD`| | |
|
|
31
|
+
|`HATCH_CPP_PLATFORM`| | |
|
|
32
|
+
|`HATCH_CPP_DISABLE_CCACHE`| | |
|
|
33
|
+
|
|
34
|
+
> [!NOTE]
|
|
35
|
+
> 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).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
import platform as sysplatform
|
|
6
|
+
import sys
|
|
7
|
+
import typing as t
|
|
8
|
+
|
|
9
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
10
|
+
|
|
11
|
+
from .structs import HatchCppBuildConfig, HatchCppBuildPlan
|
|
12
|
+
from .utils import import_string
|
|
13
|
+
|
|
14
|
+
__all__ = ("HatchCppBuildHook",)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
18
|
+
"""The hatch-cpp build hook."""
|
|
19
|
+
|
|
20
|
+
PLUGIN_NAME = "hatch-cpp"
|
|
21
|
+
_logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
def initialize(self, version: str, build_data: dict[str, t.Any]) -> None:
|
|
24
|
+
"""Initialize the plugin."""
|
|
25
|
+
# Log some basic information
|
|
26
|
+
self._logger.info("Initializing hatch-cpp plugin version %s", version)
|
|
27
|
+
self._logger.info("Running hatch-cpp")
|
|
28
|
+
|
|
29
|
+
# Only run if creating wheel
|
|
30
|
+
# TODO: Add support for specify sdist-plan
|
|
31
|
+
if self.target_name != "wheel":
|
|
32
|
+
self._logger.info("ignoring target name %s", self.target_name)
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
# Skip if SKIP_HATCH_CPP is set
|
|
36
|
+
# TODO: Support CLI once https://github.com/pypa/hatch/pull/1743
|
|
37
|
+
if os.getenv("SKIP_HATCH_CPP"):
|
|
38
|
+
self._logger.info("Skipping the build hook since SKIP_HATCH_CPP was set")
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
# Get build config class or use default
|
|
42
|
+
build_config_class = import_string(self.config["build-config-class"]) if "build-config-class" in self.config else HatchCppBuildConfig
|
|
43
|
+
|
|
44
|
+
# Instantiate build config
|
|
45
|
+
config = build_config_class(**self.config)
|
|
46
|
+
|
|
47
|
+
# Grab libraries and platform
|
|
48
|
+
libraries = config.libraries
|
|
49
|
+
platform = config.platform
|
|
50
|
+
|
|
51
|
+
# Get build plan class or use default
|
|
52
|
+
build_plan_class = import_string(self.config["build-plan-class"]) if "build-plan-class" in self.config else HatchCppBuildPlan
|
|
53
|
+
|
|
54
|
+
# Instantiate builder
|
|
55
|
+
build_plan = build_plan_class(libraries=libraries, platform=platform)
|
|
56
|
+
|
|
57
|
+
# Generate commands
|
|
58
|
+
build_plan.generate()
|
|
59
|
+
|
|
60
|
+
# Log commands if in verbose mode
|
|
61
|
+
if config.verbose:
|
|
62
|
+
for command in build_plan.commands:
|
|
63
|
+
self._logger.warning(command)
|
|
64
|
+
|
|
65
|
+
# Execute build plan
|
|
66
|
+
build_plan.execute()
|
|
67
|
+
|
|
68
|
+
# Perform any cleanup actions
|
|
69
|
+
build_plan.cleanup()
|
|
70
|
+
|
|
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
|
|
75
|
+
|
|
76
|
+
if libraries:
|
|
77
|
+
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:
|
|
83
|
+
os_name = "macosx_11_0"
|
|
84
|
+
elif "linux" in sys.platform:
|
|
85
|
+
os_name = "linux"
|
|
86
|
+
else:
|
|
87
|
+
os_name = "win"
|
|
88
|
+
if all([lib.py_limited_api for lib in libraries]):
|
|
89
|
+
build_data["tag"] = f"cp{version_major}{version_minor}-abi3-{os_name}_{machine}"
|
|
90
|
+
else:
|
|
91
|
+
build_data["tag"] = f"cp{version_major}{version_minor}-cp{version_major}{version_minor}-{os_name}_{machine}"
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from os import environ, system
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from re import match
|
|
6
|
+
from shutil import which
|
|
7
|
+
from sys import executable, platform as sys_platform
|
|
8
|
+
from sysconfig import get_path
|
|
9
|
+
from typing import Any, List, Literal, Optional
|
|
10
|
+
|
|
11
|
+
from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator
|
|
12
|
+
|
|
13
|
+
__all__ = (
|
|
14
|
+
"HatchCppBuildConfig",
|
|
15
|
+
"HatchCppLibrary",
|
|
16
|
+
"HatchCppPlatform",
|
|
17
|
+
"HatchCppBuildPlan",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
BuildType = Literal["debug", "release"]
|
|
21
|
+
CompilerToolchain = Literal["gcc", "clang", "msvc"]
|
|
22
|
+
Language = Literal["c", "c++"]
|
|
23
|
+
Binding = Literal["cpython", "pybind11", "nanobind"]
|
|
24
|
+
Platform = Literal["linux", "darwin", "win32"]
|
|
25
|
+
PlatformDefaults = {
|
|
26
|
+
"linux": {"CC": "gcc", "CXX": "g++", "LD": "ld"},
|
|
27
|
+
"darwin": {"CC": "clang", "CXX": "clang++", "LD": "ld"},
|
|
28
|
+
"win32": {"CC": "cl", "CXX": "cl", "LD": "link"},
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class HatchCppLibrary(BaseModel, validate_assignment=True):
|
|
33
|
+
"""A C++ library."""
|
|
34
|
+
|
|
35
|
+
name: str
|
|
36
|
+
sources: List[str]
|
|
37
|
+
language: Language = "c++"
|
|
38
|
+
|
|
39
|
+
binding: Binding = "cpython"
|
|
40
|
+
std: Optional[str] = None
|
|
41
|
+
|
|
42
|
+
include_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs", "include-dirs"))
|
|
43
|
+
library_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs", "library-dirs"))
|
|
44
|
+
libraries: List[str] = Field(default_factory=list)
|
|
45
|
+
|
|
46
|
+
extra_compile_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args", "extra-compile-args"))
|
|
47
|
+
extra_link_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args", "extra-link-args"))
|
|
48
|
+
extra_objects: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects", "extra-objects"))
|
|
49
|
+
|
|
50
|
+
define_macros: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros", "define-macros"))
|
|
51
|
+
undef_macros: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros", "undef-macros"))
|
|
52
|
+
|
|
53
|
+
export_symbols: List[str] = Field(default_factory=list, alias=AliasChoices("export_symbols", "export-symbols"))
|
|
54
|
+
depends: List[str] = Field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
py_limited_api: Optional[str] = Field(default="", alias=AliasChoices("py_limited_api", "py-limited-api"))
|
|
57
|
+
|
|
58
|
+
@field_validator("py_limited_api", mode="before")
|
|
59
|
+
@classmethod
|
|
60
|
+
def check_py_limited_api(cls, value: Any) -> Any:
|
|
61
|
+
if value:
|
|
62
|
+
if not match(r"cp3\d", value):
|
|
63
|
+
raise ValueError("py-limited-api must be in the form of cp3X")
|
|
64
|
+
return value
|
|
65
|
+
|
|
66
|
+
def get_qualified_name(self, platform):
|
|
67
|
+
if platform == "win32":
|
|
68
|
+
suffix = "dll" if self.binding == "none" else "pyd"
|
|
69
|
+
elif platform == "darwin":
|
|
70
|
+
suffix = "dylib" if self.binding == "none" else "so"
|
|
71
|
+
else:
|
|
72
|
+
suffix = "so"
|
|
73
|
+
if self.py_limited_api and platform != "win32":
|
|
74
|
+
return f"{self.name}.abi3.{suffix}"
|
|
75
|
+
return f"{self.name}.{suffix}"
|
|
76
|
+
|
|
77
|
+
@model_validator(mode="after")
|
|
78
|
+
def check_binding_and_py_limited_api(self):
|
|
79
|
+
if self.binding == "pybind11" and self.py_limited_api:
|
|
80
|
+
raise ValueError("pybind11 does not support Py_LIMITED_API")
|
|
81
|
+
return self
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class HatchCppPlatform(BaseModel):
|
|
85
|
+
cc: str
|
|
86
|
+
cxx: str
|
|
87
|
+
ld: str
|
|
88
|
+
platform: Platform
|
|
89
|
+
toolchain: CompilerToolchain
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def default() -> HatchCppPlatform:
|
|
93
|
+
platform = environ.get("HATCH_CPP_PLATFORM", sys_platform)
|
|
94
|
+
CC = environ.get("CC", PlatformDefaults[platform]["CC"])
|
|
95
|
+
CXX = environ.get("CXX", PlatformDefaults[platform]["CXX"])
|
|
96
|
+
LD = environ.get("LD", PlatformDefaults[platform]["LD"])
|
|
97
|
+
if "gcc" in CC and "g++" in CXX:
|
|
98
|
+
toolchain = "gcc"
|
|
99
|
+
elif "clang" in CC and "clang++" in CXX:
|
|
100
|
+
toolchain = "clang"
|
|
101
|
+
elif "cl" in CC and "cl" in CXX:
|
|
102
|
+
toolchain = "msvc"
|
|
103
|
+
else:
|
|
104
|
+
raise Exception(f"Unrecognized toolchain: {CC}, {CXX}")
|
|
105
|
+
|
|
106
|
+
# Customizations
|
|
107
|
+
if which("ccache") and not environ.get("HATCH_CPP_DISABLE_CCACHE"):
|
|
108
|
+
CC = f"ccache {CC}"
|
|
109
|
+
CXX = f"ccache {CXX}"
|
|
110
|
+
|
|
111
|
+
# https://github.com/rui314/mold/issues/647
|
|
112
|
+
# if which("ld.mold"):
|
|
113
|
+
# LD = which("ld.mold")
|
|
114
|
+
# elif which("ld.lld"):
|
|
115
|
+
# LD = which("ld.lld")
|
|
116
|
+
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=platform, toolchain=toolchain)
|
|
117
|
+
|
|
118
|
+
def get_compile_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
|
|
119
|
+
flags = ""
|
|
120
|
+
|
|
121
|
+
# Python.h
|
|
122
|
+
library.include_dirs.append(get_path("include"))
|
|
123
|
+
|
|
124
|
+
if library.binding == "pybind11":
|
|
125
|
+
import pybind11
|
|
126
|
+
|
|
127
|
+
library.include_dirs.append(pybind11.get_include())
|
|
128
|
+
if not library.std:
|
|
129
|
+
library.std = "c++11"
|
|
130
|
+
elif library.binding == "nanobind":
|
|
131
|
+
import nanobind
|
|
132
|
+
|
|
133
|
+
library.include_dirs.append(nanobind.include_dir())
|
|
134
|
+
if not library.std:
|
|
135
|
+
library.std = "c++17"
|
|
136
|
+
library.sources.append(str(Path(nanobind.include_dir()).parent / "src" / "nb_combined.cpp"))
|
|
137
|
+
library.include_dirs.append(str((Path(nanobind.include_dir()).parent / "ext" / "robin_map" / "include")))
|
|
138
|
+
|
|
139
|
+
if library.py_limited_api:
|
|
140
|
+
if library.binding == "pybind11":
|
|
141
|
+
raise ValueError("pybind11 does not support Py_LIMITED_API")
|
|
142
|
+
library.define_macros.append(f"Py_LIMITED_API=0x0{library.py_limited_api[2]}0{hex(int(library.py_limited_api[3:]))[2:]}00f0")
|
|
143
|
+
|
|
144
|
+
# Toolchain-specific flags
|
|
145
|
+
if self.toolchain == "gcc":
|
|
146
|
+
flags += " " + " ".join(f"-I{d}" for d in library.include_dirs)
|
|
147
|
+
flags += " -fPIC"
|
|
148
|
+
flags += " " + " ".join(library.extra_compile_args)
|
|
149
|
+
flags += " " + " ".join(f"-D{macro}" for macro in library.define_macros)
|
|
150
|
+
flags += " " + " ".join(f"-U{macro}" for macro in library.undef_macros)
|
|
151
|
+
if library.std:
|
|
152
|
+
flags += f" -std={library.std}"
|
|
153
|
+
elif self.toolchain == "clang":
|
|
154
|
+
flags += " ".join(f"-I{d}" for d in library.include_dirs)
|
|
155
|
+
flags += " -fPIC"
|
|
156
|
+
flags += " " + " ".join(library.extra_compile_args)
|
|
157
|
+
flags += " " + " ".join(f"-D{macro}" for macro in library.define_macros)
|
|
158
|
+
flags += " " + " ".join(f"-U{macro}" for macro in library.undef_macros)
|
|
159
|
+
if library.std:
|
|
160
|
+
flags += f" -std={library.std}"
|
|
161
|
+
elif self.toolchain == "msvc":
|
|
162
|
+
flags += " ".join(f"/I{d}" for d in library.include_dirs)
|
|
163
|
+
flags += " " + " ".join(library.extra_compile_args)
|
|
164
|
+
flags += " " + " ".join(library.extra_link_args)
|
|
165
|
+
flags += " " + " ".join(library.extra_objects)
|
|
166
|
+
flags += " " + " ".join(f"/D{macro}" for macro in library.define_macros)
|
|
167
|
+
flags += " " + " ".join(f"/U{macro}" for macro in library.undef_macros)
|
|
168
|
+
flags += " /EHsc /DWIN32"
|
|
169
|
+
if library.std:
|
|
170
|
+
flags += f" /std:{library.std}"
|
|
171
|
+
# clean
|
|
172
|
+
while flags.count(" "):
|
|
173
|
+
flags = flags.replace(" ", " ")
|
|
174
|
+
return flags
|
|
175
|
+
|
|
176
|
+
def get_link_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
|
|
177
|
+
flags = ""
|
|
178
|
+
if self.toolchain == "gcc":
|
|
179
|
+
flags += " -shared"
|
|
180
|
+
flags += " " + " ".join(library.extra_link_args)
|
|
181
|
+
flags += " " + " ".join(library.extra_objects)
|
|
182
|
+
flags += " " + " ".join(f"-l{lib}" for lib in library.libraries)
|
|
183
|
+
flags += " " + " ".join(f"-L{lib}" for lib in library.library_dirs)
|
|
184
|
+
flags += f" -o {library.get_qualified_name(self.platform)}"
|
|
185
|
+
if self.platform == "darwin":
|
|
186
|
+
flags += " -undefined dynamic_lookup"
|
|
187
|
+
if "mold" in self.ld:
|
|
188
|
+
flags += f" -fuse-ld={self.ld}"
|
|
189
|
+
elif "lld" in self.ld:
|
|
190
|
+
flags += " -fuse-ld=lld"
|
|
191
|
+
elif self.toolchain == "clang":
|
|
192
|
+
flags += " -shared"
|
|
193
|
+
flags += " " + " ".join(library.extra_link_args)
|
|
194
|
+
flags += " " + " ".join(library.extra_objects)
|
|
195
|
+
flags += " " + " ".join(f"-l{lib}" for lib in library.libraries)
|
|
196
|
+
flags += " " + " ".join(f"-L{lib}" for lib in library.library_dirs)
|
|
197
|
+
flags += f" -o {library.get_qualified_name(self.platform)}"
|
|
198
|
+
if self.platform == "darwin":
|
|
199
|
+
flags += " -undefined dynamic_lookup"
|
|
200
|
+
if "mold" in self.ld:
|
|
201
|
+
flags += f" -fuse-ld={self.ld}"
|
|
202
|
+
elif "lld" in self.ld:
|
|
203
|
+
flags += " -fuse-ld=lld"
|
|
204
|
+
elif self.toolchain == "msvc":
|
|
205
|
+
flags += " " + " ".join(library.extra_link_args)
|
|
206
|
+
flags += " " + " ".join(library.extra_objects)
|
|
207
|
+
flags += " /LD"
|
|
208
|
+
flags += f" /Fe:{library.get_qualified_name(self.platform)}"
|
|
209
|
+
flags += " /link /DLL"
|
|
210
|
+
if (Path(executable).parent / "libs").exists():
|
|
211
|
+
flags += f" /LIBPATH:{str(Path(executable).parent / 'libs')}"
|
|
212
|
+
flags += " " + " ".join(f"{lib}.lib" for lib in library.libraries)
|
|
213
|
+
flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in library.library_dirs)
|
|
214
|
+
# clean
|
|
215
|
+
while flags.count(" "):
|
|
216
|
+
flags = flags.replace(" ", " ")
|
|
217
|
+
return flags
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class HatchCppBuildPlan(BaseModel):
|
|
221
|
+
build_type: BuildType = "release"
|
|
222
|
+
libraries: List[HatchCppLibrary] = Field(default_factory=list)
|
|
223
|
+
platform: HatchCppPlatform = Field(default_factory=HatchCppPlatform.default)
|
|
224
|
+
commands: List[str] = Field(default_factory=list)
|
|
225
|
+
|
|
226
|
+
def generate(self):
|
|
227
|
+
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
|
+
)
|
|
234
|
+
return self.commands
|
|
235
|
+
|
|
236
|
+
def execute(self):
|
|
237
|
+
for command in self.commands:
|
|
238
|
+
system(command)
|
|
239
|
+
return self.commands
|
|
240
|
+
|
|
241
|
+
def cleanup(self):
|
|
242
|
+
if self.platform.platform == "win32":
|
|
243
|
+
for temp_obj in Path(".").glob("*.obj"):
|
|
244
|
+
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,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
|