Skip to content

Commit 0d0920a

Browse files
committed
Add support for conditionally processing headers
1 parent a81ea93 commit 0d0920a

File tree

8 files changed

+70
-4
lines changed

8 files changed

+70
-4
lines changed

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ dependencies = [
2525
"sphinxify >= 0.7.3",
2626
"validobj ~= 1.2",
2727
"cxxheaderparser[pcpp] ~= 1.5",
28+
"packaging",
2829
"tomli",
2930
"tomli_w",
3031
"toposort",

src/semiwrap/config/pyproject_toml.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import dataclasses
66
import re
7-
from typing import Dict, List, Optional
7+
from typing import Dict, List, Optional, Union
88

99
_arch_re = re.compile(r"\{\{\s*ARCH\s*\}\}")
1010
_os_re = re.compile(r"\{\{\s*OS\s*\}\}")
@@ -60,6 +60,28 @@ class TypeCasterConfig:
6060
headers: List[TypeCasterHeader] = dataclasses.field(default_factory=list)
6161

6262

63+
@dataclasses.dataclass
64+
class ConditionalHeader:
65+
"""
66+
Allows specifying that a header will only be autogenerated if the specified
67+
condition is true.
68+
69+
.. code-block:: toml
70+
71+
[tool.semiwrap.extension_modules."PACKAGE.NAME".headers]
72+
Name = { header="header.h", enable_if = "platform_machine == 'aarch64'" }
73+
74+
"""
75+
76+
#: Name of the header file
77+
header: str
78+
79+
#: This is a PEP 508 environment marker specification.
80+
#:
81+
#: The header will not be parsed if this does not evaluate to true
82+
enable_if: str
83+
84+
6385
@dataclasses.dataclass
6486
class ExtensionModuleConfig:
6587
"""
@@ -123,7 +145,9 @@ class ExtensionModuleConfig:
123145
#:
124146
#: .. seealso:: :ref:`autowrap`
125147
#:
126-
headers: Dict[str, str] = dataclasses.field(default_factory=dict)
148+
headers: Dict[str, Union[str, ConditionalHeader]] = dataclasses.field(
149+
default_factory=dict
150+
)
127151

128152
#: Path to a directory of yaml files. Generation data will be looked up
129153
#: using the key in the headers dictionary.

src/semiwrap/pyproject.py

+23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pathlib
22
import typing as T
33

4+
import packaging.markers
45
import tomli
56

67
from .config.util import parse_input
@@ -21,6 +22,19 @@ def __init__(self, pyproject_path: T.Optional[pathlib.Path] = None) -> None:
2122

2223
self._all_deps = None
2324

25+
self._evaluated_markers: T.Dict[str, bool] = {}
26+
27+
def _enable_if(self, condition: str) -> bool:
28+
"""
29+
Evaluates a string containing PEP 508 environment markers
30+
"""
31+
ok = self._evaluated_markers.get(condition)
32+
if ok is None:
33+
ok = packaging.markers.Marker(condition).evaluate()
34+
self._evaluated_markers[condition] = ok
35+
36+
return ok
37+
2438
@property
2539
def package_root(self) -> pathlib.Path:
2640
if self._package_root is None:
@@ -71,3 +85,12 @@ def get_extension_deps(self, extension: ExtensionModuleConfig) -> T.List[str]:
7185
deps.append(wrap)
7286
deps.extend(extension.depends)
7387
return deps
88+
89+
def get_extension_headers(
90+
self, extension: ExtensionModuleConfig
91+
) -> T.Generator[T.Tuple[str, str], None, None]:
92+
for yml, hdr in extension.headers.items():
93+
if isinstance(hdr, str):
94+
yield yml, hdr
95+
elif self._enable_if(hdr.enable_if):
96+
yield yml, hdr.header

src/semiwrap/tool/scan_headers.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,15 @@ def _should_ignore(f):
8080
all_present.add(inc / h.header)
8181

8282
for name, ext in project.extension_modules.items():
83-
if not ext.headers:
83+
files = []
84+
for _, f in ext.headers.items():
85+
if isinstance(f, str):
86+
files.append(Path(f))
87+
else:
88+
files.append(Path(f.header))
89+
90+
if not files:
8491
continue
85-
files = [Path(f) for f in ext.headers.values()]
8692
for incdir in search_paths[name]:
8793
incdir = Path(incdir)
8894
for f in files:

tests/cpp/sw-test/pyproject.toml

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ using2 = "using2.h"
6565
virtual_comma = "virtual_comma.h"
6666
virtual_xform = "virtual_xform.h"
6767

68+
# conditional headers
69+
cond_always_true = { header="cond_always_true.h", enable_if="python_version > '2'"}
70+
cond_never_true = { header="cond_never_true.h", enable_if="python_version < '2'"}
71+
6872
# Inheritance
6973
IBase = "inheritance/ibase.h"
7074
IChild = "inheritance/ichild.h"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
3+
functions:
4+
always_compiled:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
inline int always_compiled() { return 1; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#error "Should never be compiled"

0 commit comments

Comments
 (0)