Skip to content

Commit 57822a4

Browse files
committed
Make: Embed SZ_TARGET.env for PyPI sdists
1 parent d3ef8c8 commit 57822a4

File tree

4 files changed

+83
-18
lines changed

4 files changed

+83
-18
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,16 @@ uv pip install -r scripts/requirements.txt
489489

490490
### Packaging
491491

492-
For source distributions, make sure `MANIFEST.in` is up-to-date:
492+
For source distributions, make sure `MANIFEST.in` is up-to-date.
493+
When building `sdist`-s for the variant packages, you must set `SZ_TARGET` so the `sdist` metadata `Name` matches the package on PyPI.
494+
Use the backend helper to build all three correctly named `sdist`-s into `dist/`:
493495

494496
```bash
495-
uv build --sdist --out-dir dist
497+
uv pip install build
498+
uv build --sdist --out-dir dist # defaults to `stringzilla`
499+
SZ_TARGET=stringzilla uv run --no-project python build_backend.py build-sdists
500+
SZ_TARGET=stringzillas-cpus uv run --no-project python build_backend.py build-sdists
501+
SZ_TARGET=stringzillas-cuda uv run --no-project python build_backend.py build-sdists
496502
```
497503

498504
Before you ship, please make sure the `cibuilwheel` packaging works and tests pass on other platforms.

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ include VERSION
33
include LICENSE
44
include build_backend.py
55
include setup.py
6+
include SZ_TARGET.env
67

78
graft include
89
graft fork_union/include

build_backend.py

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
wheel test environment and to run the appropriate tests.
1111
1212
CLI Commands
13-
- pull-deps [PROJECT_DIR]: when testing parallel targets, installs
14-
the serial stringzilla into the test venv, and ensures test-only
13+
- pull-deps [PROJECT_DIR]: when testing parallel targets, installs
14+
the serial stringzilla into the test venv, and ensures test-only
1515
deps (NumPy, affine-gaps) are present.
1616
- run-tests [PROJECT_DIR]: runs scripts/test_stringzilla.py and,
1717
for parallel targets, also runs scripts/test_stringzillas.py.
@@ -30,15 +30,21 @@ def _build_meta():
3030
return _orig_build_meta
3131

3232

33+
def _detect_target() -> str:
34+
t = os.environ.get("SZ_TARGET")
35+
if t:
36+
return t
37+
try:
38+
return Path("SZ_TARGET.env").read_text(encoding="utf-8").strip() or "stringzilla"
39+
except FileNotFoundError:
40+
return "stringzilla"
41+
42+
3343
def get_requires_for_build_wheel(config_settings=None):
3444
"""Get build requirements, conditionally including numpy."""
3545
requirements = _build_meta().get_requires_for_build_wheel(config_settings)
36-
37-
# Add NumPy for variants that need it
38-
sz_target = os.environ.get("SZ_TARGET", "stringzilla")
39-
if sz_target in ("stringzillas-cpus", "stringzillas-cuda"):
46+
if _detect_target() in ("stringzillas-cpus", "stringzillas-cuda"):
4047
requirements.append("numpy")
41-
4248
return requirements
4349

4450

@@ -51,8 +57,7 @@ def get_requires_for_build_editable(config_settings=None):
5157
else:
5258
requirements = bm.get_requires_for_build_wheel(config_settings)
5359

54-
sz_target = os.environ.get("SZ_TARGET", "stringzilla")
55-
if sz_target in ("stringzillas-cpus", "stringzillas-cuda"):
60+
if _detect_target() in ("stringzillas-cpus", "stringzillas-cuda"):
5661
requirements.append("numpy")
5762
return requirements
5863

@@ -68,8 +73,21 @@ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
6873

6974

7075
def build_sdist(sdist_directory, config_settings=None):
71-
"""Build source distribution."""
72-
return _build_meta().build_sdist(sdist_directory, config_settings)
76+
"""Build source distribution and embed SZ_TARGET.env for installs from sdist."""
77+
target = os.environ.get("SZ_TARGET", "stringzilla")
78+
marker_path = Path("SZ_TARGET.env")
79+
created = False
80+
try:
81+
if not marker_path.exists():
82+
marker_path.write_text(f"{target}\n", encoding="utf-8")
83+
created = True
84+
return _build_meta().build_sdist(sdist_directory, config_settings)
85+
finally:
86+
if created and marker_path.exists():
87+
try:
88+
marker_path.unlink()
89+
except OSError:
90+
pass
7391

7492

7593
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
@@ -83,7 +101,7 @@ def prepare_metadata_for_build_editable(metadata_directory, config_settings=None
83101
if hasattr(bm, "prepare_metadata_for_build_editable"):
84102
return bm.prepare_metadata_for_build_editable(metadata_directory, config_settings)
85103
raise RuntimeError(
86-
"Editable installs require setuptools with PEP 660 support. "
104+
"Editable installs require setuptools with PEP 660 support. " #
87105
"Please upgrade setuptools (setuptools>=61)."
88106
)
89107

@@ -94,7 +112,7 @@ def build_editable(wheel_directory, config_settings=None, metadata_directory=Non
94112
if hasattr(bm, "build_editable"):
95113
return bm.build_editable(wheel_directory, config_settings, metadata_directory)
96114
raise RuntimeError(
97-
"Editable installs require setuptools with PEP 660 support. "
115+
"Editable installs require setuptools with PEP 660 support. " #
98116
"Please upgrade setuptools (setuptools>=61)."
99117
)
100118

@@ -103,9 +121,28 @@ def build_editable(wheel_directory, config_settings=None, metadata_directory=Non
103121
# CLI utilities for cibuildwheel
104122
# ------------------------------
105123

124+
106125
def _is_parallel_target() -> bool:
107-
t = os.environ.get("SZ_TARGET", "stringzilla")
108-
return t in ("stringzillas-cpus", "stringzillas-cuda")
126+
return _detect_target() in ("stringzillas-cpus", "stringzillas-cuda")
127+
128+
129+
def _build_sdist_for(target: str, outdir: str = "dist") -> None:
130+
"""Build a single sdist with the provided SZ_TARGET value."""
131+
env = os.environ.copy()
132+
env["SZ_TARGET"] = target
133+
subprocess.check_call([sys.executable, "-m", "build", "--sdist", "--outdir", outdir], env=env)
134+
135+
136+
def cli_build_sdists(outdir: str = "dist") -> None:
137+
"""Build sdists for stringzilla, stringzillas-cpus, stringzillas-cuda.
138+
139+
Ensures the PKG-INFO Name matches the intended PyPI package by setting
140+
SZ_TARGET for each build. Outputs to the provided directory (default: dist).
141+
"""
142+
Path(outdir).mkdir(exist_ok=True)
143+
for target in ("stringzilla", "stringzillas-cpus", "stringzillas-cuda"):
144+
print(f"Building sdist for target: {target}")
145+
_build_sdist_for(target, outdir)
109146

110147

111148
def cli_prepare_tests(project_dir: Optional[str] = None) -> None:
@@ -156,13 +193,19 @@ def _main(argv: List[str]) -> int:
156193
parser_run = sub.add_parser("run-tests", help="Run StringZilla test suites")
157194
parser_run.add_argument("project_dir", nargs="?", default=".")
158195

196+
parser_sdists = sub.add_parser("build-sdists", help="Build sdists for all targets with correct metadata")
197+
parser_sdists.add_argument("--outdir", default="dist", help="Output directory for sdists (default: dist)")
198+
159199
namespace = parser.parse_args(argv)
160200
if namespace.cmd == "pull-deps":
161201
cli_prepare_tests(namespace.project_dir)
162202
return 0
163203
if namespace.cmd == "run-tests":
164204
cli_run_tests(namespace.project_dir)
165205
return 0
206+
if namespace.cmd == "build-sdists":
207+
cli_build_sdists(namespace.outdir)
208+
return 0
166209
return 2
167210

168211

setup.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,23 @@ def _build_cuda_extension(self, ext):
155155
# will compile C/C++ sources per-language and link everything.
156156

157157

158+
def sz_target_name() -> str:
159+
# Prefer env var, then a simple marker file, else default
160+
val = os.environ.get("SZ_TARGET")
161+
if val:
162+
return val
163+
try:
164+
with open("SZ_TARGET.env", "r", encoding="utf-8") as f:
165+
v = f.read().strip()
166+
if v:
167+
return v
168+
except FileNotFoundError:
169+
pass
170+
return "stringzilla"
171+
172+
158173
using_cibuildwheel: Final[str] = os.environ.get("CIBUILDWHEEL", "0") == "1"
159-
sz_target: Final[str] = os.environ.get("SZ_TARGET", "stringzilla")
174+
sz_target: Final[str] = sz_target_name()
160175

161176

162177
def get_compiler() -> str:

0 commit comments

Comments
 (0)