Skip to content

Commit 6f2952f

Browse files
authored
fix(doctor): actionable Windows install hints, consistent search paths (#180)
* fix(doctor): actionable Windows install hints, consistent search paths - _make_build_hint(): replace bare `python scripts/build_renderdoc.py` with step-by-step git clone + uv run commands for Windows; use `uv run` for macOS; update docs URL to /docs/install/ on all platforms - _check_win_renderdoc_install(): delegate to _platform.renderdoc_search_paths() instead of hardcoded candidate list, aligning with _check_win_python_version() - renderdoccmd_search_paths(): add %LOCALAPPDATA%\rdc\renderdoc\ so the build script install dir is discovered - build_renderdoc.py: copy renderdoccmd.exe (optional) on Windows builds - Update tests for new hint text and search path delegation * docs(install): add Windows bootstrap commands to README and docs site Add step-by-step Windows renderdoc build instructions (git clone + uv run) to PyPI install section, RenderDoc bootstrap section, and Astro docs page. Update Module Discovery to list platform-specific search paths. * fix: address PR review feedback - Replace %TEMP% with relative path in Windows hint (shell-agnostic) - Add git clone step to macOS hint for PyPI users - List uv in prerequisites for Windows/macOS hints - Use _OPTIONAL_ARTIFACTS constant instead of hardcoded string - Fix docs search paths to match actual _platform.py code
1 parent a5866c0 commit 6f2952f

7 files changed

Lines changed: 106 additions & 35 deletions

File tree

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ bash <(curl -fsSL https://raw.githubusercontent.com/BANANASJIM/rdc-cli/master/sc
3737
rdc doctor # verify everything works
3838
```
3939

40-
**PyPI — Windows**
40+
**PyPI — Windows** (requires git, uv, Visual Studio Build Tools)
4141

4242
```bash
4343
uv tool install rdc-cli # or: pipx install rdc-cli
44-
rdc doctor # prints renderdoc setup instructions
44+
git clone --depth 1 https://github.com/BANANASJIM/rdc-cli.git rdc-cli
45+
uv run rdc-cli\scripts\build_renderdoc.py
46+
rdc doctor # verify everything works
4547
```
4648

4749
**PyPI — macOS** (Split client only)
@@ -77,12 +79,21 @@ pixi run setup-renderdoc # build renderdoc (pixi installs toolchain
7779
| macOS | ❌ (not supported yet) | ✅ (recommended) |
7880
| Windows |||
7981

80-
### RenderDoc bootstrap (Linux)
82+
### RenderDoc bootstrap
83+
84+
**Linux** (one-liner, no repo clone needed):
8185

8286
```bash
8387
bash <(curl -fsSL https://raw.githubusercontent.com/BANANASJIM/rdc-cli/master/scripts/build-renderdoc.sh)
8488
```
8589

90+
**Windows** (requires git, uv, Visual Studio 2022 Build Tools with C++ workload):
91+
92+
```bash
93+
git clone --depth 1 https://github.com/BANANASJIM/rdc-cli.git rdc-cli
94+
uv run rdc-cli\scripts\build_renderdoc.py
95+
```
96+
8697
If building from source, use the pixi wrapper instead: `pixi run setup-renderdoc`
8798

8899
## Quickstart

docs-astro/src/pages/docs/install.astro

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,16 @@ rdc open --connect host:54321 --token TOKEN</code></pre>
8383

8484
<h3>Bootstrap (Recommended)</h3>
8585
<p>
86-
One-liner for Linux (no repo clone needed):
86+
<strong>Linux</strong> one-liner (no repo clone needed):
8787
</p>
8888
<pre><code>bash &lt;(curl -fsSL https://raw.githubusercontent.com/BANANASJIM/rdc-cli/master/scripts/build-renderdoc.sh)</code></pre>
8989

90+
<p>
91+
<strong>Windows</strong> (requires git, uv, Visual Studio 2022 Build Tools with C++ workload):
92+
</p>
93+
<pre><code>git clone --depth 1 https://github.com/BANANASJIM/rdc-cli.git rdc-cli
94+
uv run rdc-cli\scripts\build_renderdoc.py</code></pre>
95+
9096
<p>
9197
If you are building from source, use the pixi wrapper task:
9298
</p>
@@ -103,8 +109,9 @@ export RENDERDOC_PYTHON_PATH=$PWD/build/lib</code></pre>
103109
<p>rdc-cli searches for the renderdoc module in this order:</p>
104110
<ol>
105111
<li><code>RENDERDOC_PYTHON_PATH</code> environment variable</li>
106-
<li><code>~/.local/renderdoc</code> (where the bootstrap installs)</li>
107-
<li><code>/usr/lib/renderdoc</code>, <code>/usr/local/lib/renderdoc</code></li>
112+
<li><strong>macOS:</strong> <code>~/.local/renderdoc</code>, <code>/opt/homebrew/opt/renderdoc/lib</code>, <code>/usr/local/opt/renderdoc/lib</code></li>
113+
<li><strong>Windows:</strong> <code>C:\Program Files\RenderDoc</code>, <code>%LOCALAPPDATA%\renderdoc</code>, <code>%LOCALAPPDATA%\rdc\renderdoc</code></li>
114+
<li><strong>Linux:</strong> <code>/usr/lib/renderdoc</code>, <code>/usr/local/lib/renderdoc</code></li>
108115
<li>Sibling directory of <code>renderdoccmd</code> on PATH</li>
109116
</ol>
110117

scripts/build_renderdoc.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ def default_install_dir() -> Path:
6666
return Path.home() / ".local" / "renderdoc"
6767

6868

69+
_OPTIONAL_ARTIFACTS = frozenset({"renderdoccmd.exe"})
70+
71+
6972
def _artifact_names(plat: str) -> list[str]:
7073
if plat == "windows":
71-
return ["renderdoc.pyd", "renderdoc.dll"]
74+
return ["renderdoc.pyd", "renderdoc.dll", "renderdoccmd.exe"]
7275
return ["renderdoc.so", "librenderdoc.so"]
7376

7477

@@ -396,12 +399,15 @@ def copy_artifacts(build_dir: Path, install_dir: Path, plat: str) -> None:
396399
install_dir.mkdir(parents=True, exist_ok=True)
397400

398401
for name in names:
399-
# On Windows, renderdoc.dll lives in x64/Release/ (parent of pymodules)
400-
if plat == "windows" and name == "renderdoc.dll":
402+
# On Windows, renderdoc.dll and renderdoccmd.exe live in x64/Release/ (parent of pymodules)
403+
if plat == "windows" and name in ("renderdoc.dll", "renderdoccmd.exe"):
401404
artifact = src.parent / name
402405
else:
403406
artifact = src / name
404407
if not artifact.exists():
408+
if name in _OPTIONAL_ARTIFACTS:
409+
_log(f"WARNING: {name} not found at {artifact}, skipping")
410+
continue
405411
# macOS may produce .dylib instead of .so for librenderdoc
406412
if plat == "macos" and name == "librenderdoc.so":
407413
alt = src / "librenderdoc.dylib"
@@ -458,7 +464,8 @@ def _install_vulkan_layer(install_dir: Path, build_dir: Path) -> None:
458464

459465

460466
def _artifacts_present(install_dir: Path, plat: str) -> bool:
461-
return all((install_dir / n).exists() for n in _artifact_names(plat))
467+
required = [n for n in _artifact_names(plat) if n not in _OPTIONAL_ARTIFACTS]
468+
return all((install_dir / n).exists() for n in required)
462469

463470

464471
def main(argv: list[str] | None = None) -> None:

src/rdc/_platform.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ def renderdoccmd_search_paths() -> list[Path]:
213213
"""Return candidate paths for the renderdoccmd binary."""
214214
if _WIN: # pragma: no cover
215215
paths = [Path(r"C:\Program Files\RenderDoc\renderdoccmd.exe")]
216+
localappdata = os.environ.get("LOCALAPPDATA", "")
217+
if localappdata:
218+
paths.append(Path(localappdata) / "rdc" / "renderdoc" / "renderdoccmd.exe")
216219
userprofile = os.environ.get("USERPROFILE", "")
217220
if userprofile:
218221
paths.append(

src/rdc/commands/doctor.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,28 @@ def _make_build_hint(platform: str) -> str:
4242
if platform == "win32":
4343
return (
4444
" renderdoc is not available on PyPI and must be built from source.\n"
45-
" Build script: python scripts/build_renderdoc.py\n"
46-
" Full instructions: https://bananasjim.github.io/rdc-cli/\n"
45+
" Quick setup (requires git, uv, Visual Studio Build Tools):\n"
46+
" git clone --depth 1 https://github.com/BANANASJIM/rdc-cli.git rdc-cli\n"
47+
" uv run rdc-cli\\scripts\\build_renderdoc.py\n"
48+
" Full instructions: https://bananasjim.github.io/rdc-cli/docs/install/\n"
4749
" Then re-run: rdc doctor"
4850
)
4951
if platform == "darwin":
5052
return (
5153
" renderdoc is not available on PyPI and must be built from source.\n"
5254
" Build prerequisites: brew install cmake ninja\n"
53-
" Build script: python scripts/build_renderdoc.py\n"
54-
" Full instructions: https://bananasjim.github.io/rdc-cli/\n"
55+
" Quick setup (requires git, uv):\n"
56+
" git clone --depth 1 https://github.com/BANANASJIM/rdc-cli.git rdc-cli\n"
57+
" uv run rdc-cli/scripts/build_renderdoc.py\n"
58+
" Full instructions: https://bananasjim.github.io/rdc-cli/docs/install/\n"
5559
" Then re-run: rdc doctor"
5660
)
5761
return (
5862
" renderdoc is not available on PyPI and must be built from source.\n"
5963
" Quick build script (no pixi required):\n"
6064
" bash <(curl -fsSL"
6165
" https://raw.githubusercontent.com/BANANASJIM/rdc-cli/master/scripts/build-renderdoc.sh)\n"
62-
" Full instructions: https://bananasjim.github.io/rdc-cli/\n"
66+
" Full instructions: https://bananasjim.github.io/rdc-cli/docs/install/\n"
6367
" Then re-run: rdc doctor"
6468
)
6569

@@ -225,17 +229,16 @@ def _check_win_renderdoc_install() -> CheckResult:
225229
if sys.platform != "win32":
226230
return CheckResult("win-renderdoc-install", True, "n/a")
227231

228-
candidates: list[Path] = [
229-
Path(r"C:\Program Files\RenderDoc\renderdoc.dll"),
230-
]
231-
localappdata = os.environ.get("LOCALAPPDATA", "")
232-
if localappdata:
233-
candidates.append(Path(localappdata) / "renderdoc" / "renderdoc.dll")
234-
candidates.append(Path(localappdata) / "RenderDoc" / "renderdoc.dll")
232+
from rdc import _platform
233+
234+
candidates: list[Path] = []
235235

236236
env_path = os.environ.get("RENDERDOC_PYTHON_PATH")
237237
if env_path:
238-
candidates.insert(0, Path(env_path) / "renderdoc.dll")
238+
candidates.append(Path(env_path) / "renderdoc.dll")
239+
240+
for search_dir in _platform.renderdoc_search_paths():
241+
candidates.append(Path(search_dir) / "renderdoc.dll")
239242

240243
for p in candidates:
241244
if p.exists():

tests/unit/test_build_renderdoc.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,23 @@ def test_copy_artifacts_windows(tmp_path: Path) -> None:
405405
br.copy_artifacts(build_dir, out, "windows")
406406
assert (out / "renderdoc.pyd").exists()
407407
assert (out / "renderdoc.dll").exists()
408+
assert not (out / "renderdoccmd.exe").exists()
409+
410+
411+
def test_copy_artifacts_windows_with_renderdoccmd(tmp_path: Path) -> None:
412+
build_dir = tmp_path / "build"
413+
release = build_dir / "renderdoc" / "x64" / "Release"
414+
pymodules = release / "pymodules"
415+
pymodules.mkdir(parents=True)
416+
(pymodules / "renderdoc.pyd").write_text("fake")
417+
(release / "renderdoc.dll").write_text("fake")
418+
(release / "renderdoccmd.exe").write_text("fake")
419+
420+
out = tmp_path / "install"
421+
br.copy_artifacts(build_dir, out, "windows")
422+
assert (out / "renderdoc.pyd").exists()
423+
assert (out / "renderdoc.dll").exists()
424+
assert (out / "renderdoccmd.exe").exists()
408425

409426

410427
def test_copy_artifacts_missing_source(tmp_path: Path) -> None:

tests/unit/test_doctor.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_doctor_shows_build_hint_when_renderdoc_missing(monkeypatch: pytest.Monk
7979
" Quick build script (no pixi required):\n"
8080
" bash <(curl -fsSL"
8181
" https://raw.githubusercontent.com/BANANASJIM/rdc-cli/master/scripts/build-renderdoc.sh)\n"
82-
" Full instructions: https://bananasjim.github.io/rdc-cli/\n"
82+
" Full instructions: https://bananasjim.github.io/rdc-cli/docs/install/\n"
8383
" Then re-run: rdc doctor",
8484
)
8585
monkeypatch.setattr("rdc.commands.doctor.find_renderdoc", lambda: None)
@@ -95,7 +95,7 @@ def test_doctor_shows_build_hint_when_renderdoc_missing(monkeypatch: pytest.Monk
9595
def test_doctor_hint_contains_docs_url() -> None:
9696
from rdc.commands.doctor import _RENDERDOC_BUILD_HINT
9797

98-
assert "https://bananasjim.github.io/rdc-cli/" in _RENDERDOC_BUILD_HINT
98+
assert "https://bananasjim.github.io/rdc-cli/docs/install/" in _RENDERDOC_BUILD_HINT
9999

100100

101101
# ── Group W: _check_win_python_version() ─────────────────────────────
@@ -273,8 +273,11 @@ def test_non_windows_returns_ok(self, monkeypatch: pytest.MonkeyPatch) -> None:
273273
def test_found_at_program_files(self, monkeypatch: pytest.MonkeyPatch) -> None:
274274
"""TP-W3-012: renderdoc.dll found at Program Files."""
275275
monkeypatch.setattr("rdc.commands.doctor.sys.platform", "win32")
276-
env = {"LOCALAPPDATA": r"C:\Users\test\AppData\Local"}
277-
monkeypatch.setattr("rdc.commands.doctor.os.environ", env)
276+
monkeypatch.setattr("rdc.commands.doctor.os.environ", {})
277+
monkeypatch.setattr(
278+
"rdc._platform.renderdoc_search_paths",
279+
lambda: [r"C:\Program Files\RenderDoc"],
280+
)
278281

279282
original_exists = Path.exists
280283

@@ -292,17 +295,32 @@ def test_found_via_env(self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path) ->
292295
"""TP-W3-013: renderdoc.dll found via RENDERDOC_PYTHON_PATH."""
293296
monkeypatch.setattr("rdc.commands.doctor.sys.platform", "win32")
294297
(tmp_path / "renderdoc.dll").write_text("fake")
295-
env = {"RENDERDOC_PYTHON_PATH": str(tmp_path), "LOCALAPPDATA": ""}
298+
env = {"RENDERDOC_PYTHON_PATH": str(tmp_path)}
296299
monkeypatch.setattr("rdc.commands.doctor.os.environ", env)
300+
monkeypatch.setattr("rdc._platform.renderdoc_search_paths", lambda: [])
297301
r = _check_win_renderdoc_install()
298302
assert r.ok is True
299303
assert str(tmp_path) in r.detail
300304

305+
def test_found_at_localappdata_rdc(
306+
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
307+
) -> None:
308+
"""renderdoc.dll found at %LOCALAPPDATA%\\rdc\\renderdoc via search paths."""
309+
monkeypatch.setattr("rdc.commands.doctor.sys.platform", "win32")
310+
rdc_dir = tmp_path / "rdc" / "renderdoc"
311+
rdc_dir.mkdir(parents=True)
312+
(rdc_dir / "renderdoc.dll").write_text("fake")
313+
monkeypatch.setattr("rdc.commands.doctor.os.environ", {})
314+
monkeypatch.setattr("rdc._platform.renderdoc_search_paths", lambda: [str(rdc_dir)])
315+
r = _check_win_renderdoc_install()
316+
assert r.ok is True
317+
assert "renderdoc.dll" in r.detail
318+
301319
def test_not_found_anywhere(self, monkeypatch: pytest.MonkeyPatch) -> None:
302320
"""TP-W3-014: renderdoc.dll not found anywhere."""
303321
monkeypatch.setattr("rdc.commands.doctor.sys.platform", "win32")
304-
env: dict[str, str] = {"LOCALAPPDATA": ""}
305-
monkeypatch.setattr("rdc.commands.doctor.os.environ", env)
322+
monkeypatch.setattr("rdc.commands.doctor.os.environ", {})
323+
monkeypatch.setattr("rdc._platform.renderdoc_search_paths", lambda: [])
306324
monkeypatch.setattr("rdc.commands.doctor.Path.exists", lambda _self: False)
307325
r = _check_win_renderdoc_install()
308326
assert r.ok is False
@@ -319,13 +337,16 @@ def test_linux_hint_contains_bash_script(self) -> None:
319337
"""TP-W3-015: Linux hint has bash script URL."""
320338
hint = _make_build_hint("linux")
321339
assert "build-renderdoc.sh" in hint
322-
assert "https://bananasjim.github.io/rdc-cli/" in hint
340+
assert "https://bananasjim.github.io/rdc-cli/docs/install/" in hint
323341

324-
def test_windows_hint_contains_py_script(self) -> None:
325-
"""TP-W3-016: Windows hint has Python build script."""
342+
def test_windows_hint_contains_actionable_commands(self) -> None:
343+
"""TP-W3-016: Windows hint has actionable git clone + uv run commands."""
326344
hint = _make_build_hint("win32")
345+
assert "git clone" in hint
346+
assert "uv run" in hint
327347
assert "build_renderdoc.py" in hint
328-
assert "https://bananasjim.github.io/rdc-cli/" in hint
348+
assert "%TEMP%" not in hint
349+
assert "https://bananasjim.github.io/rdc-cli/docs/install/" in hint
329350

330351

331352
# ── TP-W3-017: run_doctor() result count ─────────────────────────────
@@ -602,8 +623,10 @@ class TestMakeBuildHintDarwin:
602623
def test_darwin_hint_contains_homebrew(self) -> None:
603624
hint = _make_build_hint("darwin")
604625
assert "brew install cmake ninja" in hint
626+
assert "git clone" in hint
627+
assert "uv run" in hint
605628
assert "build_renderdoc.py" in hint
606-
assert "https://bananasjim.github.io/rdc-cli/" in hint
629+
assert "https://bananasjim.github.io/rdc-cli/docs/install/" in hint
607630

608631

609632
class TestImportRenderdocDiagnostics:

0 commit comments

Comments
 (0)