hatch-cpp 0.2.2__py3-none-any.whl → 0.3.1__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 +1 -1
- hatch_cpp/config.py +4 -3
- hatch_cpp/plugin.py +8 -12
- hatch_cpp/tests/test_platform_specific.py +456 -0
- hatch_cpp/toolchains/common.py +182 -44
- hatch_cpp/toolchains/vcpkg.py +1 -0
- {hatch_cpp-0.2.2.dist-info → hatch_cpp-0.3.1.dist-info}/METADATA +85 -12
- {hatch_cpp-0.2.2.dist-info → hatch_cpp-0.3.1.dist-info}/RECORD +11 -10
- {hatch_cpp-0.2.2.dist-info → hatch_cpp-0.3.1.dist-info}/WHEEL +1 -1
- {hatch_cpp-0.2.2.dist-info → hatch_cpp-0.3.1.dist-info}/entry_points.txt +0 -0
- {hatch_cpp-0.2.2.dist-info → hatch_cpp-0.3.1.dist-info}/licenses/LICENSE +0 -0
hatch_cpp/__init__.py
CHANGED
hatch_cpp/config.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from logging import getLogger
|
|
4
3
|
from os import system as system_call
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from typing import List, Optional
|
|
7
6
|
|
|
7
|
+
from pkn import getSimpleLogger
|
|
8
8
|
from pydantic import BaseModel, Field, model_validator
|
|
9
9
|
|
|
10
10
|
from .toolchains import BuildType, HatchCppCmakeConfiguration, HatchCppLibrary, HatchCppPlatform, HatchCppVcpkgConfiguration, Toolchain
|
|
@@ -15,13 +15,14 @@ __all__ = (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
log = getSimpleLogger("hatch_cpp")
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class HatchCppBuildConfig(BaseModel):
|
|
22
22
|
"""Build config values for Hatch C++ Builder."""
|
|
23
23
|
|
|
24
24
|
verbose: Optional[bool] = Field(default=False)
|
|
25
|
+
skip: Optional[bool] = Field(default=False)
|
|
25
26
|
name: Optional[str] = Field(default=None)
|
|
26
27
|
libraries: List[HatchCppLibrary] = Field(default_factory=list)
|
|
27
28
|
cmake: Optional[HatchCppCmakeConfiguration] = Field(default=None)
|
|
@@ -76,7 +77,7 @@ class HatchCppBuildPlan(HatchCppBuildConfig):
|
|
|
76
77
|
|
|
77
78
|
if "vanilla" in self._active_toolchains:
|
|
78
79
|
if "vcpkg" in self._active_toolchains:
|
|
79
|
-
|
|
80
|
+
log.warning("vcpkg toolchain is active; ensure that your compiler is configured to use vcpkg includes and libs.")
|
|
80
81
|
|
|
81
82
|
for library in self.libraries:
|
|
82
83
|
compile_flags = self.platform.get_compile_flags(library, self.build_type)
|
hatch_cpp/plugin.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from logging import getLogger
|
|
4
|
-
from os import getenv
|
|
5
3
|
from pathlib import Path
|
|
6
4
|
from platform import machine as platform_machine
|
|
7
5
|
from sys import platform as sys_platform, version_info
|
|
@@ -10,7 +8,7 @@ from typing import Any
|
|
|
10
8
|
from hatch_build import parse_extra_args_model
|
|
11
9
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
12
10
|
|
|
13
|
-
from .config import HatchCppBuildConfig, HatchCppBuildPlan
|
|
11
|
+
from .config import HatchCppBuildConfig, HatchCppBuildPlan, log
|
|
14
12
|
from .utils import import_string
|
|
15
13
|
|
|
16
14
|
__all__ = ("HatchCppBuildHook",)
|
|
@@ -20,7 +18,7 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
|
20
18
|
"""The hatch-cpp build hook."""
|
|
21
19
|
|
|
22
20
|
PLUGIN_NAME = "hatch-cpp"
|
|
23
|
-
_logger =
|
|
21
|
+
_logger = log
|
|
24
22
|
|
|
25
23
|
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
26
24
|
"""Initialize the plugin."""
|
|
@@ -35,12 +33,6 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
|
35
33
|
self._logger.info("ignoring target name %s", self.target_name)
|
|
36
34
|
return
|
|
37
35
|
|
|
38
|
-
# Skip if SKIP_HATCH_CPP is set
|
|
39
|
-
# TODO: Support CLI once https://github.com/pypa/hatch/pull/1743
|
|
40
|
-
if getenv("SKIP_HATCH_CPP"):
|
|
41
|
-
self._logger.info("Skipping the build hook since SKIP_HATCH_CPP was set")
|
|
42
|
-
return
|
|
43
|
-
|
|
44
36
|
# Get build config class or use default
|
|
45
37
|
build_config_class = import_string(self.config["build-config-class"]) if "build-config-class" in self.config else HatchCppBuildConfig
|
|
46
38
|
|
|
@@ -60,10 +52,14 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
|
60
52
|
build_plan.generate()
|
|
61
53
|
|
|
62
54
|
# Log commands if in verbose mode
|
|
63
|
-
if
|
|
55
|
+
if build_plan.verbose:
|
|
64
56
|
for command in build_plan.commands:
|
|
65
57
|
self._logger.warning(command)
|
|
66
58
|
|
|
59
|
+
if build_plan.skip:
|
|
60
|
+
self._logger.warning("Skipping build")
|
|
61
|
+
return
|
|
62
|
+
|
|
67
63
|
# Execute build plan
|
|
68
64
|
build_plan.execute()
|
|
69
65
|
|
|
@@ -114,4 +110,4 @@ class HatchCppBuildHook(BuildHookInterface[HatchCppBuildConfig]):
|
|
|
114
110
|
build_data["force_include"][str(path)] = str(path)
|
|
115
111
|
|
|
116
112
|
for path in build_data["force_include"]:
|
|
117
|
-
self._logger.
|
|
113
|
+
self._logger.info(f"Force include: {path}")
|
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"""Tests for platform-specific library configuration fields."""
|
|
2
|
+
|
|
3
|
+
from hatch_cpp import HatchCppLibrary, HatchCppPlatform
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestPlatformSpecificFields:
|
|
7
|
+
"""Test suite for platform-specific field handling in HatchCppLibrary."""
|
|
8
|
+
|
|
9
|
+
def test_effective_include_dirs(self):
|
|
10
|
+
"""Test that include_dirs are properly merged with platform-specific dirs."""
|
|
11
|
+
library = HatchCppLibrary(
|
|
12
|
+
name="test",
|
|
13
|
+
sources=["test.cpp"],
|
|
14
|
+
include_dirs=["common/include"],
|
|
15
|
+
include_dirs_linux=["linux/include"],
|
|
16
|
+
include_dirs_darwin=["darwin/include"],
|
|
17
|
+
include_dirs_win32=["win32/include"],
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
linux_dirs = library.get_effective_include_dirs("linux")
|
|
21
|
+
assert "common/include" in linux_dirs
|
|
22
|
+
assert "linux/include" in linux_dirs
|
|
23
|
+
assert "darwin/include" not in linux_dirs
|
|
24
|
+
assert "win32/include" not in linux_dirs
|
|
25
|
+
|
|
26
|
+
darwin_dirs = library.get_effective_include_dirs("darwin")
|
|
27
|
+
assert "common/include" in darwin_dirs
|
|
28
|
+
assert "darwin/include" in darwin_dirs
|
|
29
|
+
assert "linux/include" not in darwin_dirs
|
|
30
|
+
|
|
31
|
+
win32_dirs = library.get_effective_include_dirs("win32")
|
|
32
|
+
assert "common/include" in win32_dirs
|
|
33
|
+
assert "win32/include" in win32_dirs
|
|
34
|
+
assert "linux/include" not in win32_dirs
|
|
35
|
+
|
|
36
|
+
def test_effective_library_dirs(self):
|
|
37
|
+
"""Test that library_dirs are properly merged with platform-specific dirs."""
|
|
38
|
+
library = HatchCppLibrary(
|
|
39
|
+
name="test",
|
|
40
|
+
sources=["test.cpp"],
|
|
41
|
+
library_dirs=["common/lib"],
|
|
42
|
+
library_dirs_linux=["linux/lib"],
|
|
43
|
+
library_dirs_darwin=["darwin/lib"],
|
|
44
|
+
library_dirs_win32=["win32/lib"],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
linux_dirs = library.get_effective_library_dirs("linux")
|
|
48
|
+
assert "common/lib" in linux_dirs
|
|
49
|
+
assert "linux/lib" in linux_dirs
|
|
50
|
+
assert "darwin/lib" not in linux_dirs
|
|
51
|
+
|
|
52
|
+
darwin_dirs = library.get_effective_library_dirs("darwin")
|
|
53
|
+
assert "common/lib" in darwin_dirs
|
|
54
|
+
assert "darwin/lib" in darwin_dirs
|
|
55
|
+
|
|
56
|
+
win32_dirs = library.get_effective_library_dirs("win32")
|
|
57
|
+
assert "common/lib" in win32_dirs
|
|
58
|
+
assert "win32/lib" in win32_dirs
|
|
59
|
+
|
|
60
|
+
def test_effective_libraries(self):
|
|
61
|
+
"""Test that libraries are properly merged with platform-specific libraries."""
|
|
62
|
+
library = HatchCppLibrary(
|
|
63
|
+
name="test",
|
|
64
|
+
sources=["test.cpp"],
|
|
65
|
+
libraries=["common"],
|
|
66
|
+
libraries_linux=["pthread", "dl"],
|
|
67
|
+
libraries_darwin=["objc"],
|
|
68
|
+
libraries_win32=["kernel32", "user32"],
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
linux_libs = library.get_effective_libraries("linux")
|
|
72
|
+
assert "common" in linux_libs
|
|
73
|
+
assert "pthread" in linux_libs
|
|
74
|
+
assert "dl" in linux_libs
|
|
75
|
+
assert "objc" not in linux_libs
|
|
76
|
+
|
|
77
|
+
darwin_libs = library.get_effective_libraries("darwin")
|
|
78
|
+
assert "common" in darwin_libs
|
|
79
|
+
assert "objc" in darwin_libs
|
|
80
|
+
assert "pthread" not in darwin_libs
|
|
81
|
+
|
|
82
|
+
win32_libs = library.get_effective_libraries("win32")
|
|
83
|
+
assert "common" in win32_libs
|
|
84
|
+
assert "kernel32" in win32_libs
|
|
85
|
+
assert "user32" in win32_libs
|
|
86
|
+
assert "pthread" not in win32_libs
|
|
87
|
+
|
|
88
|
+
def test_effective_compile_args(self):
|
|
89
|
+
"""Test that extra_compile_args are properly merged with platform-specific args."""
|
|
90
|
+
library = HatchCppLibrary(
|
|
91
|
+
name="test",
|
|
92
|
+
sources=["test.cpp"],
|
|
93
|
+
extra_compile_args=["-O2"],
|
|
94
|
+
extra_compile_args_linux=["-march=native"],
|
|
95
|
+
extra_compile_args_darwin=["-mmacosx-version-min=11"],
|
|
96
|
+
extra_compile_args_win32=["/O2"],
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
linux_args = library.get_effective_compile_args("linux")
|
|
100
|
+
assert "-O2" in linux_args
|
|
101
|
+
assert "-march=native" in linux_args
|
|
102
|
+
assert "-mmacosx-version-min=11" not in linux_args
|
|
103
|
+
|
|
104
|
+
darwin_args = library.get_effective_compile_args("darwin")
|
|
105
|
+
assert "-O2" in darwin_args
|
|
106
|
+
assert "-mmacosx-version-min=11" in darwin_args
|
|
107
|
+
|
|
108
|
+
win32_args = library.get_effective_compile_args("win32")
|
|
109
|
+
assert "-O2" in win32_args
|
|
110
|
+
assert "/O2" in win32_args
|
|
111
|
+
|
|
112
|
+
def test_effective_link_args(self):
|
|
113
|
+
"""Test that extra_link_args are properly merged with platform-specific args."""
|
|
114
|
+
library = HatchCppLibrary(
|
|
115
|
+
name="test",
|
|
116
|
+
sources=["test.cpp"],
|
|
117
|
+
extra_link_args=["-shared"],
|
|
118
|
+
extra_link_args_linux=["-Wl,-rpath,$ORIGIN/lib"],
|
|
119
|
+
extra_link_args_darwin=["-Wl,-rpath,@loader_path/lib"],
|
|
120
|
+
extra_link_args_win32=["/NODEFAULTLIB"],
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
linux_args = library.get_effective_link_args("linux")
|
|
124
|
+
assert "-shared" in linux_args
|
|
125
|
+
assert "-Wl,-rpath,$ORIGIN/lib" in linux_args
|
|
126
|
+
assert "-Wl,-rpath,@loader_path/lib" not in linux_args
|
|
127
|
+
|
|
128
|
+
darwin_args = library.get_effective_link_args("darwin")
|
|
129
|
+
assert "-shared" in darwin_args
|
|
130
|
+
assert "-Wl,-rpath,@loader_path/lib" in darwin_args
|
|
131
|
+
|
|
132
|
+
win32_args = library.get_effective_link_args("win32")
|
|
133
|
+
assert "-shared" in win32_args
|
|
134
|
+
assert "/NODEFAULTLIB" in win32_args
|
|
135
|
+
|
|
136
|
+
def test_effective_extra_objects(self):
|
|
137
|
+
"""Test that extra_objects are properly merged with platform-specific objects."""
|
|
138
|
+
library = HatchCppLibrary(
|
|
139
|
+
name="test",
|
|
140
|
+
sources=["test.cpp"],
|
|
141
|
+
extra_objects=["common.o"],
|
|
142
|
+
extra_objects_linux=["linux.o"],
|
|
143
|
+
extra_objects_darwin=["darwin.o"],
|
|
144
|
+
extra_objects_win32=["win32.obj"],
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
linux_objs = library.get_effective_extra_objects("linux")
|
|
148
|
+
assert "common.o" in linux_objs
|
|
149
|
+
assert "linux.o" in linux_objs
|
|
150
|
+
assert "darwin.o" not in linux_objs
|
|
151
|
+
|
|
152
|
+
darwin_objs = library.get_effective_extra_objects("darwin")
|
|
153
|
+
assert "common.o" in darwin_objs
|
|
154
|
+
assert "darwin.o" in darwin_objs
|
|
155
|
+
|
|
156
|
+
win32_objs = library.get_effective_extra_objects("win32")
|
|
157
|
+
assert "common.o" in win32_objs
|
|
158
|
+
assert "win32.obj" in win32_objs
|
|
159
|
+
|
|
160
|
+
def test_effective_define_macros(self):
|
|
161
|
+
"""Test that define_macros are properly merged with platform-specific macros."""
|
|
162
|
+
library = HatchCppLibrary(
|
|
163
|
+
name="test",
|
|
164
|
+
sources=["test.cpp"],
|
|
165
|
+
define_macros=["COMMON=1"],
|
|
166
|
+
define_macros_linux=["LINUX=1", "_GNU_SOURCE"],
|
|
167
|
+
define_macros_darwin=["DARWIN=1", "__APPLE__"],
|
|
168
|
+
define_macros_win32=["WIN32=1", "_WINDOWS"],
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
linux_macros = library.get_effective_define_macros("linux")
|
|
172
|
+
assert "COMMON=1" in linux_macros
|
|
173
|
+
assert "LINUX=1" in linux_macros
|
|
174
|
+
assert "_GNU_SOURCE" in linux_macros
|
|
175
|
+
assert "DARWIN=1" not in linux_macros
|
|
176
|
+
|
|
177
|
+
darwin_macros = library.get_effective_define_macros("darwin")
|
|
178
|
+
assert "COMMON=1" in darwin_macros
|
|
179
|
+
assert "DARWIN=1" in darwin_macros
|
|
180
|
+
assert "__APPLE__" in darwin_macros
|
|
181
|
+
|
|
182
|
+
win32_macros = library.get_effective_define_macros("win32")
|
|
183
|
+
assert "COMMON=1" in win32_macros
|
|
184
|
+
assert "WIN32=1" in win32_macros
|
|
185
|
+
assert "_WINDOWS" in win32_macros
|
|
186
|
+
|
|
187
|
+
def test_effective_undef_macros(self):
|
|
188
|
+
"""Test that undef_macros are properly merged with platform-specific macros."""
|
|
189
|
+
library = HatchCppLibrary(
|
|
190
|
+
name="test",
|
|
191
|
+
sources=["test.cpp"],
|
|
192
|
+
undef_macros=["COMMON_UNDEF"],
|
|
193
|
+
undef_macros_linux=["LINUX_UNDEF"],
|
|
194
|
+
undef_macros_darwin=["DARWIN_UNDEF"],
|
|
195
|
+
undef_macros_win32=["WIN32_UNDEF"],
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
linux_macros = library.get_effective_undef_macros("linux")
|
|
199
|
+
assert "COMMON_UNDEF" in linux_macros
|
|
200
|
+
assert "LINUX_UNDEF" in linux_macros
|
|
201
|
+
assert "DARWIN_UNDEF" not in linux_macros
|
|
202
|
+
|
|
203
|
+
darwin_macros = library.get_effective_undef_macros("darwin")
|
|
204
|
+
assert "COMMON_UNDEF" in darwin_macros
|
|
205
|
+
assert "DARWIN_UNDEF" in darwin_macros
|
|
206
|
+
|
|
207
|
+
win32_macros = library.get_effective_undef_macros("win32")
|
|
208
|
+
assert "COMMON_UNDEF" in win32_macros
|
|
209
|
+
assert "WIN32_UNDEF" in win32_macros
|
|
210
|
+
|
|
211
|
+
def test_empty_platform_specific_fields(self):
|
|
212
|
+
"""Test that empty platform-specific fields don't cause issues."""
|
|
213
|
+
library = HatchCppLibrary(
|
|
214
|
+
name="test",
|
|
215
|
+
sources=["test.cpp"],
|
|
216
|
+
include_dirs=["common/include"],
|
|
217
|
+
# No platform-specific fields set
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
linux_dirs = library.get_effective_include_dirs("linux")
|
|
221
|
+
assert linux_dirs == ["common/include"]
|
|
222
|
+
|
|
223
|
+
darwin_dirs = library.get_effective_include_dirs("darwin")
|
|
224
|
+
assert darwin_dirs == ["common/include"]
|
|
225
|
+
|
|
226
|
+
win32_dirs = library.get_effective_include_dirs("win32")
|
|
227
|
+
assert win32_dirs == ["common/include"]
|
|
228
|
+
|
|
229
|
+
def test_only_platform_specific_fields(self):
|
|
230
|
+
"""Test that only platform-specific fields work without common fields."""
|
|
231
|
+
library = HatchCppLibrary(
|
|
232
|
+
name="test",
|
|
233
|
+
sources=["test.cpp"],
|
|
234
|
+
# No common include_dirs
|
|
235
|
+
include_dirs_linux=["linux/include"],
|
|
236
|
+
include_dirs_darwin=["darwin/include"],
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
linux_dirs = library.get_effective_include_dirs("linux")
|
|
240
|
+
assert linux_dirs == ["linux/include"]
|
|
241
|
+
|
|
242
|
+
darwin_dirs = library.get_effective_include_dirs("darwin")
|
|
243
|
+
assert darwin_dirs == ["darwin/include"]
|
|
244
|
+
|
|
245
|
+
win32_dirs = library.get_effective_include_dirs("win32")
|
|
246
|
+
assert win32_dirs == []
|
|
247
|
+
|
|
248
|
+
def test_alias_hyphenated_names(self):
|
|
249
|
+
"""Test that hyphenated field names work as aliases."""
|
|
250
|
+
library = HatchCppLibrary(
|
|
251
|
+
name="test",
|
|
252
|
+
sources=["test.cpp"],
|
|
253
|
+
**{
|
|
254
|
+
"include-dirs": ["common/include"],
|
|
255
|
+
"include-dirs-linux": ["linux/include"],
|
|
256
|
+
"library-dirs-darwin": ["darwin/lib"],
|
|
257
|
+
"extra-compile-args-win32": ["/O2"],
|
|
258
|
+
"extra-link-args-linux": ["-Wl,-rpath,$ORIGIN"],
|
|
259
|
+
"define-macros-darwin": ["DARWIN=1"],
|
|
260
|
+
"undef-macros-win32": ["NDEBUG"],
|
|
261
|
+
},
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
assert library.include_dirs == ["common/include"]
|
|
265
|
+
assert library.include_dirs_linux == ["linux/include"]
|
|
266
|
+
assert library.library_dirs_darwin == ["darwin/lib"]
|
|
267
|
+
assert library.extra_compile_args_win32 == ["/O2"]
|
|
268
|
+
assert library.extra_link_args_linux == ["-Wl,-rpath,$ORIGIN"]
|
|
269
|
+
assert library.define_macros_darwin == ["DARWIN=1"]
|
|
270
|
+
assert library.undef_macros_win32 == ["NDEBUG"]
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class TestPlatformFlagsIntegration:
|
|
274
|
+
"""Integration tests for platform-specific fields in compile/link flags."""
|
|
275
|
+
|
|
276
|
+
def test_compile_flags_include_platform_specific_include_dirs(self):
|
|
277
|
+
"""Test that get_compile_flags includes platform-specific include dirs."""
|
|
278
|
+
library = HatchCppLibrary(
|
|
279
|
+
name="test",
|
|
280
|
+
sources=["test.cpp"],
|
|
281
|
+
binding="generic",
|
|
282
|
+
include_dirs=["common/include"],
|
|
283
|
+
include_dirs_linux=["linux/include"],
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Create a mock linux platform
|
|
287
|
+
platform = HatchCppPlatform(cc="gcc", cxx="g++", ld="ld", platform="linux", toolchain="gcc", disable_ccache=True)
|
|
288
|
+
|
|
289
|
+
flags = platform.get_compile_flags(library)
|
|
290
|
+
assert "-Icommon/include" in flags
|
|
291
|
+
assert "-Ilinux/include" in flags
|
|
292
|
+
|
|
293
|
+
def test_compile_flags_include_platform_specific_macros(self):
|
|
294
|
+
"""Test that get_compile_flags includes platform-specific define/undef macros."""
|
|
295
|
+
library = HatchCppLibrary(
|
|
296
|
+
name="test",
|
|
297
|
+
sources=["test.cpp"],
|
|
298
|
+
binding="generic",
|
|
299
|
+
define_macros=["COMMON=1"],
|
|
300
|
+
define_macros_linux=["LINUX_SPECIFIC=1"],
|
|
301
|
+
undef_macros=["OLD_MACRO"],
|
|
302
|
+
undef_macros_linux=["LINUX_OLD"],
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
platform = HatchCppPlatform(cc="gcc", cxx="g++", ld="ld", platform="linux", toolchain="gcc", disable_ccache=True)
|
|
306
|
+
|
|
307
|
+
flags = platform.get_compile_flags(library)
|
|
308
|
+
assert "-DCOMMON=1" in flags
|
|
309
|
+
assert "-DLINUX_SPECIFIC=1" in flags
|
|
310
|
+
assert "-UOLD_MACRO" in flags
|
|
311
|
+
assert "-ULINUX_OLD" in flags
|
|
312
|
+
|
|
313
|
+
def test_link_flags_include_platform_specific_libraries(self):
|
|
314
|
+
"""Test that get_link_flags includes platform-specific libraries."""
|
|
315
|
+
library = HatchCppLibrary(
|
|
316
|
+
name="test",
|
|
317
|
+
sources=["test.cpp"],
|
|
318
|
+
binding="generic",
|
|
319
|
+
libraries=["common"],
|
|
320
|
+
libraries_linux=["pthread", "dl"],
|
|
321
|
+
library_dirs=["common/lib"],
|
|
322
|
+
library_dirs_linux=["linux/lib"],
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
platform = HatchCppPlatform(cc="gcc", cxx="g++", ld="ld", platform="linux", toolchain="gcc", disable_ccache=True)
|
|
326
|
+
|
|
327
|
+
flags = platform.get_link_flags(library)
|
|
328
|
+
assert "-lcommon" in flags
|
|
329
|
+
assert "-lpthread" in flags
|
|
330
|
+
assert "-ldl" in flags
|
|
331
|
+
assert "-Lcommon/lib" in flags
|
|
332
|
+
assert "-Llinux/lib" in flags
|
|
333
|
+
|
|
334
|
+
def test_link_flags_include_platform_specific_link_args(self):
|
|
335
|
+
"""Test that get_link_flags includes platform-specific extra_link_args."""
|
|
336
|
+
library = HatchCppLibrary(
|
|
337
|
+
name="test",
|
|
338
|
+
sources=["test.cpp"],
|
|
339
|
+
binding="generic",
|
|
340
|
+
extra_link_args=["-shared"],
|
|
341
|
+
extra_link_args_linux=["-Wl,-rpath,$ORIGIN/lib"],
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
platform = HatchCppPlatform(cc="gcc", cxx="g++", ld="ld", platform="linux", toolchain="gcc", disable_ccache=True)
|
|
345
|
+
|
|
346
|
+
flags = platform.get_link_flags(library)
|
|
347
|
+
assert "-shared" in flags
|
|
348
|
+
assert "-Wl,-rpath,$ORIGIN/lib" in flags
|
|
349
|
+
|
|
350
|
+
def test_darwin_platform_uses_darwin_specific_fields(self):
|
|
351
|
+
"""Test that darwin platform uses darwin-specific fields."""
|
|
352
|
+
library = HatchCppLibrary(
|
|
353
|
+
name="test",
|
|
354
|
+
sources=["test.cpp"],
|
|
355
|
+
binding="generic",
|
|
356
|
+
libraries_linux=["pthread"],
|
|
357
|
+
libraries_darwin=["objc"],
|
|
358
|
+
extra_link_args_darwin=["-Wl,-rpath,@loader_path/lib"],
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
platform = HatchCppPlatform(cc="clang", cxx="clang++", ld="ld", platform="darwin", toolchain="clang", disable_ccache=True)
|
|
362
|
+
|
|
363
|
+
flags = platform.get_link_flags(library)
|
|
364
|
+
assert "-lobjc" in flags
|
|
365
|
+
assert "-lpthread" not in flags
|
|
366
|
+
assert "-Wl,-rpath,@loader_path/lib" in flags
|
|
367
|
+
|
|
368
|
+
def test_win32_platform_uses_win32_specific_fields(self):
|
|
369
|
+
"""Test that win32 platform uses win32-specific fields."""
|
|
370
|
+
library = HatchCppLibrary(
|
|
371
|
+
name="test",
|
|
372
|
+
sources=["test.cpp"],
|
|
373
|
+
binding="generic",
|
|
374
|
+
libraries=["common"],
|
|
375
|
+
libraries_win32=["kernel32"],
|
|
376
|
+
library_dirs=["common/lib"],
|
|
377
|
+
library_dirs_win32=["win32/lib"],
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
platform = HatchCppPlatform(cc="cl", cxx="cl", ld="link", platform="win32", toolchain="msvc", disable_ccache=True)
|
|
381
|
+
|
|
382
|
+
flags = platform.get_link_flags(library)
|
|
383
|
+
assert "common.lib" in flags
|
|
384
|
+
assert "kernel32.lib" in flags
|
|
385
|
+
assert "/LIBPATH:common/lib" in flags
|
|
386
|
+
assert "/LIBPATH:win32/lib" in flags
|
|
387
|
+
|
|
388
|
+
def test_msvc_compile_flags_use_platform_specific_fields(self):
|
|
389
|
+
"""Test that MSVC compile flags include platform-specific fields."""
|
|
390
|
+
library = HatchCppLibrary(
|
|
391
|
+
name="test",
|
|
392
|
+
sources=["test.cpp"],
|
|
393
|
+
binding="generic",
|
|
394
|
+
include_dirs=["common/include"],
|
|
395
|
+
include_dirs_win32=["win32/include"],
|
|
396
|
+
define_macros=["COMMON=1"],
|
|
397
|
+
define_macros_win32=["_WINDOWS"],
|
|
398
|
+
extra_compile_args_win32=["/W4"],
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
platform = HatchCppPlatform(cc="cl", cxx="cl", ld="link", platform="win32", toolchain="msvc", disable_ccache=True)
|
|
402
|
+
|
|
403
|
+
flags = platform.get_compile_flags(library)
|
|
404
|
+
assert "/Icommon/include" in flags
|
|
405
|
+
assert "/Iwin32/include" in flags
|
|
406
|
+
assert "/DCOMMON=1" in flags
|
|
407
|
+
assert "/D_WINDOWS" in flags
|
|
408
|
+
assert "/W4" in flags
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class TestPlatformFieldOrdering:
|
|
412
|
+
"""Test that platform-specific fields are appended after common fields."""
|
|
413
|
+
|
|
414
|
+
def test_include_dirs_ordering(self):
|
|
415
|
+
"""Test that platform-specific include dirs come after common dirs."""
|
|
416
|
+
library = HatchCppLibrary(
|
|
417
|
+
name="test",
|
|
418
|
+
sources=["test.cpp"],
|
|
419
|
+
include_dirs=["first", "second"],
|
|
420
|
+
include_dirs_linux=["third", "fourth"],
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
dirs = library.get_effective_include_dirs("linux")
|
|
424
|
+
assert dirs == ["first", "second", "third", "fourth"]
|
|
425
|
+
|
|
426
|
+
def test_libraries_ordering(self):
|
|
427
|
+
"""Test that platform-specific libraries come after common libraries."""
|
|
428
|
+
library = HatchCppLibrary(
|
|
429
|
+
name="test",
|
|
430
|
+
sources=["test.cpp"],
|
|
431
|
+
libraries=["common1", "common2"],
|
|
432
|
+
libraries_linux=["linux1", "linux2"],
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
libs = library.get_effective_libraries("linux")
|
|
436
|
+
assert libs == ["common1", "common2", "linux1", "linux2"]
|
|
437
|
+
|
|
438
|
+
def test_base_list_not_mutated(self):
|
|
439
|
+
"""Test that the base lists are not mutated when getting effective values."""
|
|
440
|
+
library = HatchCppLibrary(
|
|
441
|
+
name="test",
|
|
442
|
+
sources=["test.cpp"],
|
|
443
|
+
include_dirs=["common"],
|
|
444
|
+
include_dirs_linux=["linux"],
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
# Get effective dirs multiple times
|
|
448
|
+
dirs1 = library.get_effective_include_dirs("linux")
|
|
449
|
+
dirs2 = library.get_effective_include_dirs("linux")
|
|
450
|
+
|
|
451
|
+
# Both should be equal
|
|
452
|
+
assert dirs1 == dirs2
|
|
453
|
+
|
|
454
|
+
# Base list should not be modified
|
|
455
|
+
assert library.include_dirs == ["common"]
|
|
456
|
+
assert library.include_dirs_linux == ["linux"]
|
hatch_cpp/toolchains/common.py
CHANGED
|
@@ -47,15 +47,44 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
|
|
|
47
47
|
std: Optional[str] = None
|
|
48
48
|
|
|
49
49
|
include_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs", "include-dirs"))
|
|
50
|
+
include_dirs_linux: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_linux", "include-dirs-linux"))
|
|
51
|
+
include_dirs_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_darwin", "include-dirs-darwin"))
|
|
52
|
+
include_dirs_win32: List[str] = Field(default_factory=list, alias=AliasChoices("include_dirs_win32", "include-dirs-win32"))
|
|
53
|
+
|
|
50
54
|
library_dirs: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs", "library-dirs"))
|
|
55
|
+
library_dirs_linux: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_linux", "library-dirs-linux"))
|
|
56
|
+
library_dirs_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_darwin", "library-dirs-darwin"))
|
|
57
|
+
library_dirs_win32: List[str] = Field(default_factory=list, alias=AliasChoices("library_dirs_win32", "library-dirs-win32"))
|
|
58
|
+
|
|
51
59
|
libraries: List[str] = Field(default_factory=list)
|
|
60
|
+
libraries_linux: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_linux", "libraries-linux"))
|
|
61
|
+
libraries_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_darwin", "libraries-darwin"))
|
|
62
|
+
libraries_win32: List[str] = Field(default_factory=list, alias=AliasChoices("libraries_win32", "libraries-win32"))
|
|
52
63
|
|
|
53
64
|
extra_compile_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args", "extra-compile-args"))
|
|
65
|
+
extra_compile_args_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_linux", "extra-compile-args-linux"))
|
|
66
|
+
extra_compile_args_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_darwin", "extra-compile-args-darwin"))
|
|
67
|
+
extra_compile_args_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_compile_args_win32", "extra-compile-args-win32"))
|
|
68
|
+
|
|
54
69
|
extra_link_args: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args", "extra-link-args"))
|
|
70
|
+
extra_link_args_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_linux", "extra-link-args-linux"))
|
|
71
|
+
extra_link_args_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_darwin", "extra-link-args-darwin"))
|
|
72
|
+
extra_link_args_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_link_args_win32", "extra-link-args-win32"))
|
|
73
|
+
|
|
55
74
|
extra_objects: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects", "extra-objects"))
|
|
75
|
+
extra_objects_linux: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_linux", "extra-objects-linux"))
|
|
76
|
+
extra_objects_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_darwin", "extra-objects-darwin"))
|
|
77
|
+
extra_objects_win32: List[str] = Field(default_factory=list, alias=AliasChoices("extra_objects_win32", "extra-objects-win32"))
|
|
56
78
|
|
|
57
79
|
define_macros: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros", "define-macros"))
|
|
80
|
+
define_macros_linux: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_linux", "define-macros-linux"))
|
|
81
|
+
define_macros_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_darwin", "define-macros-darwin"))
|
|
82
|
+
define_macros_win32: List[str] = Field(default_factory=list, alias=AliasChoices("define_macros_win32", "define-macros-win32"))
|
|
83
|
+
|
|
58
84
|
undef_macros: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros", "undef-macros"))
|
|
85
|
+
undef_macros_linux: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_linux", "undef-macros-linux"))
|
|
86
|
+
undef_macros_darwin: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_darwin", "undef-macros-darwin"))
|
|
87
|
+
undef_macros_win32: List[str] = Field(default_factory=list, alias=AliasChoices("undef_macros_win32", "undef-macros-win32"))
|
|
59
88
|
|
|
60
89
|
export_symbols: List[str] = Field(default_factory=list, alias=AliasChoices("export_symbols", "export-symbols"))
|
|
61
90
|
depends: List[str] = Field(default_factory=list)
|
|
@@ -89,6 +118,94 @@ class HatchCppLibrary(BaseModel, validate_assignment=True):
|
|
|
89
118
|
raise ValueError("Generic binding can not support Py_LIMITED_API")
|
|
90
119
|
return self
|
|
91
120
|
|
|
121
|
+
def get_effective_link_args(self, platform: Platform) -> List[str]:
|
|
122
|
+
"""Get link args merged with platform-specific link args."""
|
|
123
|
+
args = list(self.extra_link_args)
|
|
124
|
+
if platform == "linux":
|
|
125
|
+
args.extend(self.extra_link_args_linux)
|
|
126
|
+
elif platform == "darwin":
|
|
127
|
+
args.extend(self.extra_link_args_darwin)
|
|
128
|
+
elif platform == "win32":
|
|
129
|
+
args.extend(self.extra_link_args_win32)
|
|
130
|
+
return args
|
|
131
|
+
|
|
132
|
+
def get_effective_include_dirs(self, platform: Platform) -> List[str]:
|
|
133
|
+
"""Get include dirs merged with platform-specific include dirs."""
|
|
134
|
+
dirs = list(self.include_dirs)
|
|
135
|
+
if platform == "linux":
|
|
136
|
+
dirs.extend(self.include_dirs_linux)
|
|
137
|
+
elif platform == "darwin":
|
|
138
|
+
dirs.extend(self.include_dirs_darwin)
|
|
139
|
+
elif platform == "win32":
|
|
140
|
+
dirs.extend(self.include_dirs_win32)
|
|
141
|
+
return dirs
|
|
142
|
+
|
|
143
|
+
def get_effective_library_dirs(self, platform: Platform) -> List[str]:
|
|
144
|
+
"""Get library dirs merged with platform-specific library dirs."""
|
|
145
|
+
dirs = list(self.library_dirs)
|
|
146
|
+
if platform == "linux":
|
|
147
|
+
dirs.extend(self.library_dirs_linux)
|
|
148
|
+
elif platform == "darwin":
|
|
149
|
+
dirs.extend(self.library_dirs_darwin)
|
|
150
|
+
elif platform == "win32":
|
|
151
|
+
dirs.extend(self.library_dirs_win32)
|
|
152
|
+
return dirs
|
|
153
|
+
|
|
154
|
+
def get_effective_libraries(self, platform: Platform) -> List[str]:
|
|
155
|
+
"""Get libraries merged with platform-specific libraries."""
|
|
156
|
+
libs = list(self.libraries)
|
|
157
|
+
if platform == "linux":
|
|
158
|
+
libs.extend(self.libraries_linux)
|
|
159
|
+
elif platform == "darwin":
|
|
160
|
+
libs.extend(self.libraries_darwin)
|
|
161
|
+
elif platform == "win32":
|
|
162
|
+
libs.extend(self.libraries_win32)
|
|
163
|
+
return libs
|
|
164
|
+
|
|
165
|
+
def get_effective_compile_args(self, platform: Platform) -> List[str]:
|
|
166
|
+
"""Get compile args merged with platform-specific compile args."""
|
|
167
|
+
args = list(self.extra_compile_args)
|
|
168
|
+
if platform == "linux":
|
|
169
|
+
args.extend(self.extra_compile_args_linux)
|
|
170
|
+
elif platform == "darwin":
|
|
171
|
+
args.extend(self.extra_compile_args_darwin)
|
|
172
|
+
elif platform == "win32":
|
|
173
|
+
args.extend(self.extra_compile_args_win32)
|
|
174
|
+
return args
|
|
175
|
+
|
|
176
|
+
def get_effective_extra_objects(self, platform: Platform) -> List[str]:
|
|
177
|
+
"""Get extra objects merged with platform-specific extra objects."""
|
|
178
|
+
objs = list(self.extra_objects)
|
|
179
|
+
if platform == "linux":
|
|
180
|
+
objs.extend(self.extra_objects_linux)
|
|
181
|
+
elif platform == "darwin":
|
|
182
|
+
objs.extend(self.extra_objects_darwin)
|
|
183
|
+
elif platform == "win32":
|
|
184
|
+
objs.extend(self.extra_objects_win32)
|
|
185
|
+
return objs
|
|
186
|
+
|
|
187
|
+
def get_effective_define_macros(self, platform: Platform) -> List[str]:
|
|
188
|
+
"""Get define macros merged with platform-specific define macros."""
|
|
189
|
+
macros = list(self.define_macros)
|
|
190
|
+
if platform == "linux":
|
|
191
|
+
macros.extend(self.define_macros_linux)
|
|
192
|
+
elif platform == "darwin":
|
|
193
|
+
macros.extend(self.define_macros_darwin)
|
|
194
|
+
elif platform == "win32":
|
|
195
|
+
macros.extend(self.define_macros_win32)
|
|
196
|
+
return macros
|
|
197
|
+
|
|
198
|
+
def get_effective_undef_macros(self, platform: Platform) -> List[str]:
|
|
199
|
+
"""Get undef macros merged with platform-specific undef macros."""
|
|
200
|
+
macros = list(self.undef_macros)
|
|
201
|
+
if platform == "linux":
|
|
202
|
+
macros.extend(self.undef_macros_linux)
|
|
203
|
+
elif platform == "darwin":
|
|
204
|
+
macros.extend(self.undef_macros_darwin)
|
|
205
|
+
elif platform == "win32":
|
|
206
|
+
macros.extend(self.undef_macros_win32)
|
|
207
|
+
return macros
|
|
208
|
+
|
|
92
209
|
|
|
93
210
|
class HatchCppPlatform(BaseModel):
|
|
94
211
|
cc: str
|
|
@@ -96,13 +213,13 @@ class HatchCppPlatform(BaseModel):
|
|
|
96
213
|
ld: str
|
|
97
214
|
platform: Platform
|
|
98
215
|
toolchain: CompilerToolchain
|
|
216
|
+
disable_ccache: bool = False
|
|
99
217
|
|
|
100
218
|
@staticmethod
|
|
101
219
|
def default() -> HatchCppPlatform:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
LD = environ.get("LD", PlatformDefaults[platform]["LD"])
|
|
220
|
+
CC = environ.get("CC", PlatformDefaults[sys_platform]["CC"])
|
|
221
|
+
CXX = environ.get("CXX", PlatformDefaults[sys_platform]["CXX"])
|
|
222
|
+
LD = environ.get("LD", PlatformDefaults[sys_platform]["LD"])
|
|
106
223
|
if "gcc" in CC and "g++" in CXX:
|
|
107
224
|
toolchain = "gcc"
|
|
108
225
|
elif "clang" in CC and "clang++" in CXX:
|
|
@@ -110,26 +227,34 @@ class HatchCppPlatform(BaseModel):
|
|
|
110
227
|
elif "cl" in CC and "cl" in CXX:
|
|
111
228
|
toolchain = "msvc"
|
|
112
229
|
# Fallback to platform defaults
|
|
113
|
-
elif
|
|
230
|
+
elif sys_platform == "linux":
|
|
114
231
|
toolchain = "gcc"
|
|
115
|
-
elif
|
|
232
|
+
elif sys_platform == "darwin":
|
|
116
233
|
toolchain = "clang"
|
|
117
|
-
elif
|
|
234
|
+
elif sys_platform == "win32":
|
|
118
235
|
toolchain = "msvc"
|
|
119
236
|
else:
|
|
120
237
|
toolchain = "gcc"
|
|
121
238
|
|
|
122
|
-
#
|
|
123
|
-
if which("ccache") and not environ.get("HATCH_CPP_DISABLE_CCACHE"):
|
|
124
|
-
CC = f"ccache {CC}"
|
|
125
|
-
CXX = f"ccache {CXX}"
|
|
126
|
-
|
|
239
|
+
# TODO:
|
|
127
240
|
# https://github.com/rui314/mold/issues/647
|
|
128
241
|
# if which("ld.mold"):
|
|
129
242
|
# LD = which("ld.mold")
|
|
130
243
|
# elif which("ld.lld"):
|
|
131
244
|
# LD = which("ld.lld")
|
|
132
|
-
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=
|
|
245
|
+
return HatchCppPlatform(cc=CC, cxx=CXX, ld=LD, platform=sys_platform, toolchain=toolchain)
|
|
246
|
+
|
|
247
|
+
@model_validator(mode="wrap")
|
|
248
|
+
@classmethod
|
|
249
|
+
def validate_model(cls, data, handler):
|
|
250
|
+
model = handler(data)
|
|
251
|
+
if which("ccache") and not model.disable_ccache:
|
|
252
|
+
if model.toolchain in ["gcc", "clang"]:
|
|
253
|
+
if not model.cc.startswith("ccache "):
|
|
254
|
+
model.cc = f"ccache {model.cc}"
|
|
255
|
+
if not model.cxx.startswith("ccache "):
|
|
256
|
+
model.cxx = f"ccache {model.cxx}"
|
|
257
|
+
return model
|
|
133
258
|
|
|
134
259
|
@staticmethod
|
|
135
260
|
def platform_for_toolchain(toolchain: CompilerToolchain) -> HatchCppPlatform:
|
|
@@ -140,54 +265,62 @@ class HatchCppPlatform(BaseModel):
|
|
|
140
265
|
def get_compile_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
|
|
141
266
|
flags = ""
|
|
142
267
|
|
|
268
|
+
# Get effective platform-specific values
|
|
269
|
+
effective_include_dirs = library.get_effective_include_dirs(self.platform)
|
|
270
|
+
effective_compile_args = library.get_effective_compile_args(self.platform)
|
|
271
|
+
effective_define_macros = library.get_effective_define_macros(self.platform)
|
|
272
|
+
effective_undef_macros = library.get_effective_undef_macros(self.platform)
|
|
273
|
+
effective_extra_objects = library.get_effective_extra_objects(self.platform)
|
|
274
|
+
effective_link_args = library.get_effective_link_args(self.platform)
|
|
275
|
+
|
|
143
276
|
# Python.h
|
|
144
277
|
if library.binding != "generic":
|
|
145
|
-
|
|
278
|
+
effective_include_dirs.append(get_path("include"))
|
|
146
279
|
|
|
147
280
|
if library.binding == "pybind11":
|
|
148
281
|
import pybind11
|
|
149
282
|
|
|
150
|
-
|
|
283
|
+
effective_include_dirs.append(pybind11.get_include())
|
|
151
284
|
if not library.std:
|
|
152
285
|
library.std = "c++11"
|
|
153
286
|
elif library.binding == "nanobind":
|
|
154
287
|
import nanobind
|
|
155
288
|
|
|
156
|
-
|
|
289
|
+
effective_include_dirs.append(nanobind.include_dir())
|
|
157
290
|
if not library.std:
|
|
158
291
|
library.std = "c++17"
|
|
159
292
|
library.sources.append(str(Path(nanobind.include_dir()).parent / "src" / "nb_combined.cpp"))
|
|
160
|
-
|
|
293
|
+
effective_include_dirs.append(str((Path(nanobind.include_dir()).parent / "ext" / "robin_map" / "include")))
|
|
161
294
|
|
|
162
295
|
if library.py_limited_api:
|
|
163
296
|
if library.binding == "pybind11":
|
|
164
297
|
raise ValueError("pybind11 does not support Py_LIMITED_API")
|
|
165
|
-
|
|
298
|
+
effective_define_macros.append(f"Py_LIMITED_API=0x0{library.py_limited_api[2]}0{hex(int(library.py_limited_api[3:]))[2:]}00f0")
|
|
166
299
|
|
|
167
300
|
# Toolchain-specific flags
|
|
168
301
|
if self.toolchain == "gcc":
|
|
169
|
-
flags += " " + " ".join(f"-I{d}" for d in
|
|
302
|
+
flags += " " + " ".join(f"-I{d}" for d in effective_include_dirs)
|
|
170
303
|
flags += " -fPIC"
|
|
171
|
-
flags += " " + " ".join(
|
|
172
|
-
flags += " " + " ".join(f"-D{macro}" for macro in
|
|
173
|
-
flags += " " + " ".join(f"-U{macro}" for macro in
|
|
304
|
+
flags += " " + " ".join(effective_compile_args)
|
|
305
|
+
flags += " " + " ".join(f"-D{macro}" for macro in effective_define_macros)
|
|
306
|
+
flags += " " + " ".join(f"-U{macro}" for macro in effective_undef_macros)
|
|
174
307
|
if library.std:
|
|
175
308
|
flags += f" -std={library.std}"
|
|
176
309
|
elif self.toolchain == "clang":
|
|
177
|
-
flags += " ".join(f"-I{d}" for d in
|
|
310
|
+
flags += " ".join(f"-I{d}" for d in effective_include_dirs)
|
|
178
311
|
flags += " -fPIC"
|
|
179
|
-
flags += " " + " ".join(
|
|
180
|
-
flags += " " + " ".join(f"-D{macro}" for macro in
|
|
181
|
-
flags += " " + " ".join(f"-U{macro}" for macro in
|
|
312
|
+
flags += " " + " ".join(effective_compile_args)
|
|
313
|
+
flags += " " + " ".join(f"-D{macro}" for macro in effective_define_macros)
|
|
314
|
+
flags += " " + " ".join(f"-U{macro}" for macro in effective_undef_macros)
|
|
182
315
|
if library.std:
|
|
183
316
|
flags += f" -std={library.std}"
|
|
184
317
|
elif self.toolchain == "msvc":
|
|
185
|
-
flags += " ".join(f"/I{d}" for d in
|
|
186
|
-
flags += " " + " ".join(
|
|
187
|
-
flags += " " + " ".join(
|
|
188
|
-
flags += " " + " ".join(
|
|
189
|
-
flags += " " + " ".join(f"/D{macro}" for macro in
|
|
190
|
-
flags += " " + " ".join(f"/U{macro}" for macro in
|
|
318
|
+
flags += " ".join(f"/I{d}" for d in effective_include_dirs)
|
|
319
|
+
flags += " " + " ".join(effective_compile_args)
|
|
320
|
+
flags += " " + " ".join(effective_link_args)
|
|
321
|
+
flags += " " + " ".join(effective_extra_objects)
|
|
322
|
+
flags += " " + " ".join(f"/D{macro}" for macro in effective_define_macros)
|
|
323
|
+
flags += " " + " ".join(f"/U{macro}" for macro in effective_undef_macros)
|
|
191
324
|
flags += " /EHsc /DWIN32"
|
|
192
325
|
if library.std:
|
|
193
326
|
flags += f" /std:{library.std}"
|
|
@@ -198,12 +331,17 @@ class HatchCppPlatform(BaseModel):
|
|
|
198
331
|
|
|
199
332
|
def get_link_flags(self, library: HatchCppLibrary, build_type: BuildType = "release") -> str:
|
|
200
333
|
flags = ""
|
|
334
|
+
effective_link_args = library.get_effective_link_args(self.platform)
|
|
335
|
+
effective_extra_objects = library.get_effective_extra_objects(self.platform)
|
|
336
|
+
effective_libraries = library.get_effective_libraries(self.platform)
|
|
337
|
+
effective_library_dirs = library.get_effective_library_dirs(self.platform)
|
|
338
|
+
|
|
201
339
|
if self.toolchain == "gcc":
|
|
202
340
|
flags += " -shared"
|
|
203
|
-
flags += " " + " ".join(
|
|
204
|
-
flags += " " + " ".join(
|
|
205
|
-
flags += " " + " ".join(f"-l{lib}" for lib in
|
|
206
|
-
flags += " " + " ".join(f"-L{lib}" for lib in
|
|
341
|
+
flags += " " + " ".join(effective_link_args)
|
|
342
|
+
flags += " " + " ".join(effective_extra_objects)
|
|
343
|
+
flags += " " + " ".join(f"-l{lib}" for lib in effective_libraries)
|
|
344
|
+
flags += " " + " ".join(f"-L{lib}" for lib in effective_library_dirs)
|
|
207
345
|
flags += f" -o {library.get_qualified_name(self.platform)}"
|
|
208
346
|
if self.platform == "darwin":
|
|
209
347
|
flags += " -undefined dynamic_lookup"
|
|
@@ -213,10 +351,10 @@ class HatchCppPlatform(BaseModel):
|
|
|
213
351
|
flags += " -fuse-ld=lld"
|
|
214
352
|
elif self.toolchain == "clang":
|
|
215
353
|
flags += " -shared"
|
|
216
|
-
flags += " " + " ".join(
|
|
217
|
-
flags += " " + " ".join(
|
|
218
|
-
flags += " " + " ".join(f"-l{lib}" for lib in
|
|
219
|
-
flags += " " + " ".join(f"-L{lib}" for lib in
|
|
354
|
+
flags += " " + " ".join(effective_link_args)
|
|
355
|
+
flags += " " + " ".join(effective_extra_objects)
|
|
356
|
+
flags += " " + " ".join(f"-l{lib}" for lib in effective_libraries)
|
|
357
|
+
flags += " " + " ".join(f"-L{lib}" for lib in effective_library_dirs)
|
|
220
358
|
flags += f" -o {library.get_qualified_name(self.platform)}"
|
|
221
359
|
if self.platform == "darwin":
|
|
222
360
|
flags += " -undefined dynamic_lookup"
|
|
@@ -225,15 +363,15 @@ class HatchCppPlatform(BaseModel):
|
|
|
225
363
|
elif "lld" in self.ld:
|
|
226
364
|
flags += " -fuse-ld=lld"
|
|
227
365
|
elif self.toolchain == "msvc":
|
|
228
|
-
flags += " " + " ".join(
|
|
229
|
-
flags += " " + " ".join(
|
|
366
|
+
flags += " " + " ".join(effective_link_args)
|
|
367
|
+
flags += " " + " ".join(effective_extra_objects)
|
|
230
368
|
flags += " /LD"
|
|
231
369
|
flags += f" /Fe:{library.get_qualified_name(self.platform)}"
|
|
232
370
|
flags += " /link /DLL"
|
|
233
371
|
if (Path(executable).parent / "libs").exists():
|
|
234
372
|
flags += f" /LIBPATH:{str(Path(executable).parent / 'libs')}"
|
|
235
|
-
flags += " " + " ".join(f"{lib}.lib" for lib in
|
|
236
|
-
flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in
|
|
373
|
+
flags += " " + " ".join(f"{lib}.lib" for lib in effective_libraries)
|
|
374
|
+
flags += " " + " ".join(f"/LIBPATH:{lib}" for lib in effective_library_dirs)
|
|
237
375
|
# clean
|
|
238
376
|
while flags.count(" "):
|
|
239
377
|
flags = flags.replace(" ", " ")
|
hatch_cpp/toolchains/vcpkg.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hatch-cpp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Hatch plugin for C++ builds
|
|
5
5
|
Project-URL: Repository, https://github.com/python-project-templates/hatch-cpp
|
|
6
6
|
Project-URL: Homepage, https://github.com/python-project-templates/hatch-cpp
|
|
@@ -20,8 +20,9 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
20
20
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
|
-
Requires-Dist: hatch-build<0.6,>=0.
|
|
23
|
+
Requires-Dist: hatch-build<0.6,>=0.5
|
|
24
24
|
Requires-Dist: hatchling
|
|
25
|
+
Requires-Dist: pkn
|
|
25
26
|
Requires-Dist: pydantic
|
|
26
27
|
Provides-Extra: develop
|
|
27
28
|
Requires-Dist: build; extra == 'develop'
|
|
@@ -32,7 +33,7 @@ Requires-Dist: hatch-build>=0.3.2; extra == 'develop'
|
|
|
32
33
|
Requires-Dist: hatchling; extra == 'develop'
|
|
33
34
|
Requires-Dist: mdformat-tables>=1; extra == 'develop'
|
|
34
35
|
Requires-Dist: mdformat<1.1,>=0.7.22; extra == 'develop'
|
|
35
|
-
Requires-Dist: nanobind<2.
|
|
36
|
+
Requires-Dist: nanobind<2.12.0; extra == 'develop'
|
|
36
37
|
Requires-Dist: pybind11; extra == 'develop'
|
|
37
38
|
Requires-Dist: pytest; extra == 'develop'
|
|
38
39
|
Requires-Dist: pytest-cov; extra == 'develop'
|
|
@@ -142,17 +143,89 @@ hatch-build \
|
|
|
142
143
|
--libraries.0.include-dirs cpp,another-dir
|
|
143
144
|
```
|
|
144
145
|
|
|
145
|
-
|
|
146
|
+
This CLI is aware of your `pyproject.toml`-configured setup.
|
|
147
|
+
To display help for this, run (note the passthrough `--`):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
hatch-build -- --help
|
|
151
|
+
```
|
|
146
152
|
|
|
147
|
-
|
|
153
|
+
For example, for the `test_project_basic` in this project's `tests` folder:
|
|
154
|
+
|
|
155
|
+
```raw
|
|
156
|
+
hatch-build --hooks-only -- --help
|
|
157
|
+
[sdist]
|
|
158
|
+
|
|
159
|
+
[wheel]
|
|
160
|
+
[2025-11-11T17:31:06-0500][p2a][WARNING]: Only dicts with str, int, float, bool, or enum values are supported - field `cmake_env_args` got value type typing.Dict[str, str]
|
|
161
|
+
usage: hatch-build-extras-model [-h] [--verbose] [--name NAME] [--libraries.0.name LIBRARIES.0.NAME]
|
|
162
|
+
[--libraries.0.sources.0 LIBRARIES.0.SOURCES.0] [--libraries.0.sources LIBRARIES.0.SOURCES]
|
|
163
|
+
[--libraries.0.language LIBRARIES.0.LANGUAGE] [--libraries.0.binding LIBRARIES.0.BINDING]
|
|
164
|
+
[--libraries.0.std LIBRARIES.0.STD] [--libraries.0.include-dirs.0 LIBRARIES.0.INCLUDE_DIRS.0]
|
|
165
|
+
[--libraries.0.include-dirs LIBRARIES.0.INCLUDE_DIRS]
|
|
166
|
+
[--libraries.0.library-dirs LIBRARIES.0.LIBRARY_DIRS]
|
|
167
|
+
[--libraries.0.libraries LIBRARIES.0.LIBRARIES]
|
|
168
|
+
[--libraries.0.extra-compile-args LIBRARIES.0.EXTRA_COMPILE_ARGS]
|
|
169
|
+
[--libraries.0.extra-link-args LIBRARIES.0.EXTRA_LINK_ARGS]
|
|
170
|
+
[--libraries.0.extra-objects LIBRARIES.0.EXTRA_OBJECTS]
|
|
171
|
+
[--libraries.0.define-macros LIBRARIES.0.DEFINE_MACROS]
|
|
172
|
+
[--libraries.0.undef-macros LIBRARIES.0.UNDEF_MACROS]
|
|
173
|
+
[--libraries.0.export-symbols LIBRARIES.0.EXPORT_SYMBOLS]
|
|
174
|
+
[--libraries.0.depends LIBRARIES.0.DEPENDS]
|
|
175
|
+
[--libraries.0.py-limited-api LIBRARIES.0.PY_LIMITED_API] [--cmake.root CMAKE.ROOT]
|
|
176
|
+
[--cmake.build CMAKE.BUILD] [--cmake.install CMAKE.INSTALL]
|
|
177
|
+
[--cmake.cmake-arg-prefix CMAKE.CMAKE_ARG_PREFIX] [--cmake.cmake-args CMAKE.CMAKE_ARGS]
|
|
178
|
+
[--cmake.include-flags CMAKE.INCLUDE_FLAGS] [--platform.cc PLATFORM.CC]
|
|
179
|
+
[--platform.cxx PLATFORM.CXX] [--platform.ld PLATFORM.LD] [--platform.platform PLATFORM.PLATFORM]
|
|
180
|
+
[--platform.toolchain PLATFORM.TOOLCHAIN] [--platform.disable-ccache] [--vcpkg.vcpkg VCPKG.VCPKG]
|
|
181
|
+
[--vcpkg.vcpkg-root VCPKG.VCPKG_ROOT] [--vcpkg.vcpkg-repo VCPKG.VCPKG_REPO]
|
|
182
|
+
[--vcpkg.vcpkg-triplet VCPKG.VCPKG_TRIPLET] [--build-type BUILD_TYPE] [--commands COMMANDS]
|
|
183
|
+
|
|
184
|
+
options:
|
|
185
|
+
-h, --help show this help message and exit
|
|
186
|
+
--verbose
|
|
187
|
+
--name NAME
|
|
188
|
+
--libraries.0.name LIBRARIES.0.NAME
|
|
189
|
+
--libraries.0.sources.0 LIBRARIES.0.SOURCES.0
|
|
190
|
+
--libraries.0.sources LIBRARIES.0.SOURCES
|
|
191
|
+
--libraries.0.language LIBRARIES.0.LANGUAGE
|
|
192
|
+
--libraries.0.binding LIBRARIES.0.BINDING
|
|
193
|
+
--libraries.0.std LIBRARIES.0.STD
|
|
194
|
+
--libraries.0.include-dirs.0 LIBRARIES.0.INCLUDE_DIRS.0
|
|
195
|
+
--libraries.0.include-dirs LIBRARIES.0.INCLUDE_DIRS
|
|
196
|
+
--libraries.0.library-dirs LIBRARIES.0.LIBRARY_DIRS
|
|
197
|
+
--libraries.0.libraries LIBRARIES.0.LIBRARIES
|
|
198
|
+
--libraries.0.extra-compile-args LIBRARIES.0.EXTRA_COMPILE_ARGS
|
|
199
|
+
--libraries.0.extra-link-args LIBRARIES.0.EXTRA_LINK_ARGS
|
|
200
|
+
--libraries.0.extra-objects LIBRARIES.0.EXTRA_OBJECTS
|
|
201
|
+
--libraries.0.define-macros LIBRARIES.0.DEFINE_MACROS
|
|
202
|
+
--libraries.0.undef-macros LIBRARIES.0.UNDEF_MACROS
|
|
203
|
+
--libraries.0.export-symbols LIBRARIES.0.EXPORT_SYMBOLS
|
|
204
|
+
--libraries.0.depends LIBRARIES.0.DEPENDS
|
|
205
|
+
--libraries.0.py-limited-api LIBRARIES.0.PY_LIMITED_API
|
|
206
|
+
--cmake.root CMAKE.ROOT
|
|
207
|
+
--cmake.build CMAKE.BUILD
|
|
208
|
+
--cmake.install CMAKE.INSTALL
|
|
209
|
+
--cmake.cmake-arg-prefix CMAKE.CMAKE_ARG_PREFIX
|
|
210
|
+
--cmake.cmake-args CMAKE.CMAKE_ARGS
|
|
211
|
+
--cmake.include-flags CMAKE.INCLUDE_FLAGS
|
|
212
|
+
--platform.cc PLATFORM.CC
|
|
213
|
+
--platform.cxx PLATFORM.CXX
|
|
214
|
+
--platform.ld PLATFORM.LD
|
|
215
|
+
--platform.platform PLATFORM.PLATFORM
|
|
216
|
+
--platform.toolchain PLATFORM.TOOLCHAIN
|
|
217
|
+
--platform.disable-ccache
|
|
218
|
+
--vcpkg.vcpkg VCPKG.VCPKG
|
|
219
|
+
--vcpkg.vcpkg-root VCPKG.VCPKG_ROOT
|
|
220
|
+
--vcpkg.vcpkg-repo VCPKG.VCPKG_REPO
|
|
221
|
+
--vcpkg.vcpkg-triplet VCPKG.VCPKG_TRIPLET
|
|
222
|
+
--build-type BUILD_TYPE
|
|
223
|
+
--commands COMMANDS
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Environment Variables
|
|
148
227
|
|
|
149
|
-
|
|
150
|
-
| :------------------------- | :------ | :-------------------- |
|
|
151
|
-
| `CC` | | C Compiler override |
|
|
152
|
-
| `CXX` | | C++ Compiler override |
|
|
153
|
-
| `LD` | | Linker override |
|
|
154
|
-
| `HATCH_CPP_PLATFORM` | | Platform to build |
|
|
155
|
-
| `HATCH_CPP_DISABLE_CCACHE` | | Disable CCache usage |
|
|
228
|
+
`hatch-cpp` will respect standard environment variables for compiler control, e.g. `CC`, `CXX`, `LD`, `CMAKE_GENERATOR`, `OSX_DEPLOYMENT_TARGET`, etc.
|
|
156
229
|
|
|
157
230
|
> [!NOTE]
|
|
158
231
|
> 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,9 +1,10 @@
|
|
|
1
|
-
hatch_cpp/__init__.py,sha256=
|
|
2
|
-
hatch_cpp/config.py,sha256=
|
|
1
|
+
hatch_cpp/__init__.py,sha256=NiHzyZHO9thWWlAsLinBL03KdZwgTXAKh3yDMnAIKRs,114
|
|
2
|
+
hatch_cpp/config.py,sha256=LlwDBmD1nir08Y5GOl4wa29h2iJBtNRSzYMGHRVFJUo,3698
|
|
3
3
|
hatch_cpp/hooks.py,sha256=SQkF5WJIgzw-8rvlTzuQvBqdP6K3fHgnh6CZOZFag50,203
|
|
4
|
-
hatch_cpp/plugin.py,sha256=
|
|
4
|
+
hatch_cpp/plugin.py,sha256=NcIDi7c9KH-_RkPeeCgWKoH5InIjw2eECswazwvGl_c,4304
|
|
5
5
|
hatch_cpp/utils.py,sha256=lxd3U3aMYsTS6DYMc1y17MR16LzgRzv92f_xh87LSg8,297
|
|
6
6
|
hatch_cpp/tests/test_hatch_build.py,sha256=q2IKTFi3Pq99UsOyL84V-C9VtFUs3ZcA9UlA8lpRW54,1553
|
|
7
|
+
hatch_cpp/tests/test_platform_specific.py,sha256=UaqYFoKfdxNG5p4ZlPsCJE50LB8HzzgVDRlYG03YHQM,17722
|
|
7
8
|
hatch_cpp/tests/test_projects.py,sha256=vs-kHdiHM7pCqM3oGQsSryq5blRi0HyK5QFfHxlJDi8,1773
|
|
8
9
|
hatch_cpp/tests/test_structs.py,sha256=cpzbPLneEbEONzXmPS1S9PL9mbhya4udc4eqTpU9w6w,2576
|
|
9
10
|
hatch_cpp/tests/test_project_basic/pyproject.toml,sha256=eqM1UVpNmJWDfsuO18ZG_VOV9I4tAWgsM5Dhf49X8Nc,694
|
|
@@ -56,10 +57,10 @@ hatch_cpp/tests/test_project_pybind_vcpkg/cpp/project/basic.hpp,sha256=LZSfCfhLY
|
|
|
56
57
|
hatch_cpp/tests/test_project_pybind_vcpkg/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
58
|
hatch_cpp/toolchains/__init__.py,sha256=anza4tXKxauobWMOUrxX3sEO0qs7sp6VdLXhLae3vkY,64
|
|
58
59
|
hatch_cpp/toolchains/cmake.py,sha256=VQYYqiOu0ZEF0IBuep35Xad7jryWy04-dHYYf7c0XgY,3331
|
|
59
|
-
hatch_cpp/toolchains/common.py,sha256=
|
|
60
|
-
hatch_cpp/toolchains/vcpkg.py,sha256=
|
|
61
|
-
hatch_cpp-0.
|
|
62
|
-
hatch_cpp-0.
|
|
63
|
-
hatch_cpp-0.
|
|
64
|
-
hatch_cpp-0.
|
|
65
|
-
hatch_cpp-0.
|
|
60
|
+
hatch_cpp/toolchains/common.py,sha256=a8Pp6K5ykR04ZGXirQGx-xDw9xFm65O2sqrZpUlUqws,18165
|
|
61
|
+
hatch_cpp/toolchains/vcpkg.py,sha256=Gwv3YNXBngpdebvRuYuUcWCzPyDbmDvy8c0K7uV4k38,2146
|
|
62
|
+
hatch_cpp-0.3.1.dist-info/METADATA,sha256=elXaQLudW-BbNb0B0ZL1YCbMCr39d7GpZUaSQRB_I40,9896
|
|
63
|
+
hatch_cpp-0.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
64
|
+
hatch_cpp-0.3.1.dist-info/entry_points.txt,sha256=RgXfjpD4iwomJQK5n7FnPkXzb5fOnF5v3DI5hbkgVcw,30
|
|
65
|
+
hatch_cpp-0.3.1.dist-info/licenses/LICENSE,sha256=FWyFTpd5xXEz50QpGDtsyIv6dgR2z_dHdoab_Nq_KMw,11452
|
|
66
|
+
hatch_cpp-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|