os: add support for windows - #38810
Draft
AmyJeanes wants to merge 14 commits into
Draft
Conversation
This was referenced Sep 8, 2026
Contributor
Process replay diff reportReplays driving segments through this PR and compares the behavior to master. ✅ 0 changed, 66 passed, 0 errors |
AmyJeanes
force-pushed
the
windows
branch
4 times, most recently
from
September 9, 2026 02:01
235758d to
7054a07
Compare
Merged
Development builds only: the daemons, modeld, pandad, v4l and socketcan stay Linux. SCons runs build commands through MSYS2 bash so the SConscripts' POSIX shell syntax keeps working. Portable forms replace dirent, readlink, socketpair, aligned_alloc and the rm -rf shell-outs on every platform; what the CRT still spells differently is shimmed in common/util.h. replace_file retries the rename a Windows reader blocks. teleoprtc has no Windows wheels yet, so it is marked off there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
url_file: os.register_at_fork does not exist on Windows. ui: the Windows CRT has no vasprintf for the log callback; a missing AF_UNIX family degrades WifiManager like a missing system D-Bus, and the init worker is skipped then instead of failing on the None router. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
currentSeconds() subtracted two uint64 timestamps that start 1 ns apart in the wrong order; the wrapped result made ctime() return NULL on the UCRT. winpthreads' clock_nanosleep rejects CLOCK_MONOTONIC, which the sleep loop took as "done sleeping": precise_nano_sleep now sleeps in slices and polls the interrupt flag on every platform, which also replaces the SIGUSR1 wake-up. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
is_termresized() stays true until resize_term() acknowledges it, so every frame rebuilt the screen; chgat() takes a pair number and never changes the character, so the markers were pair 255 blanks; 16-colour terminals reject the 256-colour indices; wbkgd() paints an attribute-only background just on the cells it clears itself. The bookmark and alert markers now draw '_' like the legend, on ncurses too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
/tmp/comma_download_cache resolved to <drive>:\tmp on Windows. The cache now lives under Path::tmp_dir() / hw.TMP_DIR: $TEMP, /tmp when unset. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
time.monotonic() on Windows Python 3.12 ticks every 15.6 ms, so SubMaster measured dt=0 and its frequency checks divided by zero. perf_counter is the same CLOCK_MONOTONIC on Linux and macOS, and on Windows the QueryPerformanceCounter clock 3.13 moved monotonic to. The tests that time SubMaster and logMonoTime read the same clock. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
SwaglogState's destructor runs from DllMain during ExitProcess, after the zmq I/O thread is gone, and zmq_ctx_destroy() then waits forever. The process is going away, so leak the context. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
Windows spawns instead of forking, so child targets live at module level; NamedTemporaryFile handles close before another process opens the file; binaries are launched by absolute path (CreateProcess resolves ./name against the parent's cwd) and test_native adds the .exe suffix; the hardcoded /tmp becomes TMP_DIR; manager.helpers imports fcntl lazily, since common/test.py imports the manager; a sleep measured with the 15.6 ms monotonic tick can read short, so recv_one_retry's timing uses perf_counter. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
The MSYS2 CLANG64 shell is the build environment: pacman installs the toolchain, uv and MSYS2's native git (the venv's git-lfs mis-resolves the POSIX paths the Cygwin-style git package reports). The venv lives in Scripts/ and gets a python3.exe for the build's shebangs. pycapnp's wheel links the Visual C++ runtime, so the setup checks for it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
A build_windows job next to build_mac: op.sh setup and build in the MSYS2 CLANG64 shell the README describes, then the tests that cover what Windows is for (common, messaging, cabana, jotpluggler, tools/lib, the UI library). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
Contributor
Quote paths so an install directory containing spaces works. op.sh and setup.sh quote $OPENPILOT_ROOT; the cabana and jotpluggler string defines use escaped double quotes rather than '"..."', whose outer single quotes SCons' argument quoting drops and splits the path; the acados and modeld build commands quote their embedded paths. Cross-platform: the same paths break on Linux, spaces are just far more common on Windows. The PC tools (cabana, replay, jotpluggler, the UI) build and run from a spaced path; on Linux a full build, modeld and acados codegen included, does too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
AmyJeanes
force-pushed
the
windows
branch
2 times, most recently
from
September 10, 2026 14:16
4a67bb1 to
4899422
Compare
Three things broke op lint on Windows, all latent on Linux too: - lint.sh passed the whole openpilot/ file list (~48k of paths) as one argv, over Windows' ~32k command-line limit, so the file-list checks failed with "Argument list too long". Batch the arguments through xargs. - check_shebang_format flagged the LFS-tracked updater zipapp, whose real "#!/usr/bin/env python3" line sits over a ZIP payload, as a bad shebang because grep reported the binary as a match. Skip binaries with grep -I. - A spaced install path broke `cd $ROOT` and the check invocations. Quote $ROOT and $DIR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
…ies#107 publishes --- TODO REMOVE AFTER DEPENDENCY PR MERGES (commaai/dependencies#107) --- Until the win_amd64 wheels are on PyPI, uv resolves the comma-deps packages openpilot names for sys_platform == 'win32' from a GitHub release of the same wheels on my fork. Linux and macOS resolve from PyPI as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
--- TODO REMOVE AFTER THE SUBMODULE PRS MERGE (commaai/msgq#709, commaai/panda#2427, commaai/rednose#61, commaai/opendbc#3724) --- Until the four submodule PRs merge, the pointers move to the windows-tidy branches on my fork and .gitmodules fetches them from there: panda and opendbc just below their own TEMP index commits (their uv sources would leak into this lockfile), rednose at its TEMP commit (its source supplies comma-deps-eigen for Windows), msgq at its tip. The lock follows the submodules' metadata. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016AgqYZYWLpwE2T5vS3nVEt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Native Windows development build of openpilot on an MSYS2 CLANG64 toolchain (clang/lld/libc++) with a uv-managed CPython. Covers the build and the PC dev tools: the UI, cabana, replay, PlotJuggler, msgq/params, plus panda firmware build and flash. No on-road support, and the manager/daemon stack is out of scope (as on macOS); those pieces are kept as possible follow-ups.
Prefers cross-platform code (std::filesystem, std::chrono, portable Python) over Windows-only branches, so most of the diff changes existing lines rather than adding platform forks. Linux and macOS are unchanged. Line endings were split into a separate change that comma has already merged.
The two
TEMPcommits at the tip (both markedTODO REMOVE) drop before this is marked ready: one points uv at a pre-release wheel index until commaai/dependencies#107 publishes the win_amd64 wheels, the other points the submodules at my fork until the four submodule PRs merge.Part of a six-repo series: commaai/msgq#709, commaai/panda#2427, commaai/opendbc#3724, commaai/rednose#61, commaai/dependencies#107. dependencies merges first; the others merge independently; only openpilot depends on all of them.
Generated with Claude, human-reviewed and tested end to end, locally and in CI (comma's suite on Linux plus a Windows build-and-tool-test job).