Migrate Windows build to MSYS2 UCRT64 (draft, in-progress)#22535
Migrate Windows build to MSYS2 UCRT64 (draft, in-progress)#22535vkalintiris wants to merge 6 commits into
Conversation
The Windows MSYS2/UCRT64 build path installs the Rust toolchain (mingw-w64-ucrt-x86_64-rust) and passes -DRust_COMPILER=/ucrt64/bin/rustc to CMake, but no actual Rust code is ever compiled there because every Rust-using plugin (OTEL/journal/NetFlow/signal-viewer) is disabled in packaging/windows/compile-on-windows.sh. That leaves us blind to whether the Windows toolchain can build Rust at all. This adds a tiny self-contained staticlib crate at src/crates/rust-demo exposing nd_rust_add() and nd_rust_version() via the C ABI, gated behind a new CMake option ENABLE_RUST_DEMO (default ON). The crate is linked into the main netdata target and called from netdata_main() right after the NETDATA STARTUP log line, so a draft PR through the existing packaging workflows will exercise the Rust toolchain on Windows. The crate is its own workspace root (no runtime dependencies, no cbindgen) to keep compile time and dependency surface minimal -- the goal is to test whether Rust can be built, not whether a heavy workspace builds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The investigation in SOW-0032 showed the Windows build runs in the MSYS shell with /usr/bin/gcc linking against msys-2.0.dll (Cygwin POSIX emulation, LP64), while /ucrt64/bin/rustc produces UCRT-linked LLP64 objects. The mismatch is harmless for the trivial smoke crate but blocks any non-trivial in-process Rust use. Since the project intends to write "a lot of Rust code", the rwin worktree pivots from a one-shot smoke PR to the full UCRT64 migration: switch the C side to /ucrt64/bin/gcc so it shares the same C runtime and data model as Rust, drop the bundled MSYS2 root from the installer, and end with the smoke crate re-enabled on Windows to validate the migration. This commit only sets up the pivot: - packaging/windows/compile-on-windows.sh: pass -DENABLE_RUST_DEMO=Off so Windows CI is not noised by Rust-toolchain output while migration phases iterate. The override will be removed at the end of the migration (Phase 7 of SOW-0033). Linux/macOS keep the default-on smoke build. - CMakeLists.txt: clarify the smoke option's comment to point at the Windows opt-out path during the migration. - SOW-0032: status paused; sub-state explains the pivot and the resume condition. - SOW-0033: new, in-progress, with a filled pre-implementation gate and an 8-phase plan from shell switch through installer slim-down through final smoke re-enable. Implementation gated on user confirmation of phase sequencing. No source code is migrated in this commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Windows MSYS2 shell defaults to MSYSTEM=MSYS, which makes the C side
of the agent link against msys-2.0.dll (Cygwin POSIX emulation, LP64).
The Rust toolchain at /ucrt64/bin/rustc produces UCRT-linked LLP64
objects. The mismatch blocks in-process Rust FFI and forces the
installer to ship the entire MSYS2 root just to provide msys-2.0.dll.
This commit pins the Windows build to MSYSTEM=UCRT64. The C compiler
and all runtime DLLs now come from the UCRT64 toolchain, matching the
Rust toolchain. Other MSYS2 environments (MSYS, MINGW64, CLANG64) are
deliberately rejected with a FATAL_ERROR so the failure mode is loud
rather than silent.
Changes:
- packaging/windows/{build,install-dependencies,invoke-msys2,package}.ps1:
set $env:MSYSTEM = 'UCRT64' before invoking msysbash so /etc/profile
picks the UCRT64 PATH (adds /ucrt64/bin, /ucrt64/lib/pkgconfig, etc.)
- packaging/cmake/Modules/NetdataPlatform.cmake:
- drop CYGWIN and MSYS CMAKE_SYSTEM_NAME branches; only Windows now
- require MSYSTEM=UCRT64 at configure time, FATAL_ERROR otherwise
- collapse CLion include_directories branches to ucrt64 only
- packaging/windows/compile-on-windows.sh: drop the explicit
-DRust_COMPILER=/ucrt64/bin/rustc; Corrosion finds rustc/cargo on
PATH under UCRT64 (see Corrosion's FindRust.cmake)
- packaging/windows/clion-msys-{msys,mingw64}-environment.bat: deleted
- packaging/windows/clion-msys-ucrt64-environment.bat: added as the
sole supported CLion developer entry point
This commit does not migrate any C source code; the next CI run is
expected to fail on the cygwin_conv_path() call sites and POSIX header
mismatches. Those failures define the work for Phases 3 and 4 of
SOW-0033.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 17 files
Confidence score: 4/5
- This PR appears safe to merge, with risk mainly limited to documentation/state clarity rather than runtime behavior.
- The most significant issue is in
.agents/sow/current/SOW-0033-20260522-windows-ucrt64-migration.md: the sub-state says implementation is waiting on user confirmation, but Phase 2 is already implemented here, which can mislead contributors about current migration status. - Because the issue is concrete but non-functional (severity 5/10), merge risk is minimal to moderate rather than blocking.
- Pay close attention to
.agents/sow/current/SOW-0033-20260522-windows-ucrt64-migration.md- update the sub-state to match the actual implementation progress.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".agents/sow/current/SOW-0033-20260522-windows-ucrt64-migration.md">
<violation number="1" location=".agents/sow/current/SOW-0033-20260522-windows-ucrt64-migration.md:7">
P2: Sub-state claims "awaiting user confirmation before implementation begins" but Phase 2 is already implemented and in this PR. Stale sub-state misleads readers about the migration's current status.</violation>
</file>
Architecture diagram
sequenceDiagram
participant PS as PowerShell Entry Points
participant MSYS2 as MSYS2 UCRT64 Shell
participant CMake as CMake Configure
participant Corrosion as Corrosion Rust
participant RustC as rustc/Cargo (UCRT64)
participant GCC as gcc (UCRT64)
participant Netdata as netdata.exe
participant Log as Agent Log
Note over PS,Log: Windows Build & Runtime Flow (UCRT64)
PS->>PS: Export MSYSTEM=UCRT64
PS->>MSYS2: Invoke bash with MSYSTEM=UCRT64
MSYS2->>CMake: cmake -DENABLE_RUST_DEMO=Off ...
CMake->>CMake: Validate MSYSTEM==UCRT64
alt MSYSTEM != UCRT64
CMake-->>MSYS2: FATAL_ERROR
else MSYSTEM == UCRT64
CMake->>CMake: Set include dirs (ucrt64)
CMake->>CMake: Skip Rust corrosion (RUST_DEMO=Off)
end
CMake->>GCC: Build C sources (UCRT runtime)
GCC-->>CMake: Object files (.o)
CMake-->>MSYS2: Build complete
Note over MSYS2,Netdata: Rust Demo (when enabled, future phase)
alt ENABLE_RUST_DEMO=On (Linux/macOS now, Windows post-migration)
MSYS2->>CMake: cmake -DENABLE_RUST_DEMO=On
CMake->>Corrosion: corrosion_import_crate(rust_demo)
Corrosion->>RustC: cargo build (UCRT64 staticlib)
RustC-->>Corrosion: librust_demo.a (LLP64)
Corrosion-->>CMake: Link rust_demo target
CMake->>GCC: Compile with HAVE_RUST_DEMO
GCC->>Netdata: Link librust_demo.a into netdata.exe
end
Note over Netdata,Log: Runtime Execution
Netdata->>Netdata: Initialize agent
alt HAVE_RUST_DEMO defined
Netdata->>Netdata: nd_rust_add(2, 3)
Netdata->>Log: "RUST FFI smoke: rust-demo 0.1.0 reports nd_rust_add(2, 3) = 5"
end
Netdata->>Log: "NETDATA STARTUP" (unchanged)
Note over PS,CMake: Key Environment Contract
Note over PS,CMake: MSYSTEM=UCRT64 required<br/>No more MSYS/MINGW64 variants<br/>No explicit Rust_COMPILER (found via PATH)
Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.
Re-trigger cubic
|
|
||
| Status: in-progress | ||
|
|
||
| Sub-state: Pre-impl gate filled; investigation evidence inherited from |
There was a problem hiding this comment.
P2: Sub-state claims "awaiting user confirmation before implementation begins" but Phase 2 is already implemented and in this PR. Stale sub-state misleads readers about the migration's current status.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .agents/sow/current/SOW-0033-20260522-windows-ucrt64-migration.md, line 7:
<comment>Sub-state claims "awaiting user confirmation before implementation begins" but Phase 2 is already implemented and in this PR. Stale sub-state misleads readers about the migration's current status.</comment>
<file context>
@@ -0,0 +1,519 @@
+
+Status: in-progress
+
+Sub-state: Pre-impl gate filled; investigation evidence inherited from
+SOW-0032. Phase plan drafted; awaiting user confirmation on phase
+sequencing before implementation begins. The `rwin` worktree is dedicated
</file context>
Linux developers need a local way to validate Windows builds without waiting on GitHub CI, especially while iterating on SOW-0033 (the UCRT64 migration) where many phases will produce expected breakage that needs to be observed and fixed in short cycles. packaging/windows/LOCAL_DEV_LINUX.md walks through: - Setting up a Windows 11 VM with quickemu/QEMU/KVM (one-time cost, ~1 hour to first boot). - One-time Windows tweaks (long paths, OpenSSH server, default-shell -> PowerShell, the admin authorized_keys ACL gotcha). - Installing MSYS2 inside the VM by running the repo's own install-dependencies.ps1 over SSH (one command from the host). - Mounting the host's worktree into the VM at Z:\ via SSHFS-Win, so the host editor and the VM build see the same files live and the VM's build artifacts land directly under the host's build/ dir. - Driving the VM from a Linux shell (or from an LLM assistant like Claude Code) via SSH, with a small wrapper script. - A .claude/settings.json snippet that allowlists the wrapper, so a coding assistant can run ./packaging/windows/dev-vm.sh build, read the resulting errors, edit on the host, and re-build -- the VM is just another subshell from the assistant's perspective. packaging/windows/dev-vm.sh is the wrapper the walkthrough references: - build, package, deps, shell -- canned actions that map to the existing .ps1 entry points in packaging/windows/. - run -- '<ps>' -- run an arbitrary PowerShell command. - msys -- '<sh>' -- run an arbitrary command in a UCRT64 login bash, matching what build.ps1 sets up. Defaults are overridable via VM_HOST and REPO_IN_VM env vars so each developer can target their own VM without editing the script. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First CI run on draft PR netdata#22535 surfaced two distinct failures unrelated to the C source migration: 1. Windows build: NetdataPlatform.cmake rejected CMAKE_SYSTEM_NAME=MSYS even with MSYSTEM=UCRT64 set, because packaging/windows/compile-on-windows.sh hard-coded /usr/bin/cmake -- which is the MSYS-runtime cmake and always self-reports as MSYS regardless of $MSYSTEM. Setting MSYSTEM=UCRT64 changed PATH for gcc/pkg-config but the absolute path to cmake bypassed it. 2. Linux source-tarball builds across all distros, plus the LibreSSL and Clang Checks jobs, failed with `rustc not found in PATH`. Root cause: the previous default ENABLE_RUST_DEMO=On in CMake forced Corrosion to require rustc in every build environment, including ones that never needed a Rust toolchain. Fixes: - packaging/windows/compile-on-windows.sh: /usr/bin/cmake -> cmake so PATH (with /ucrt64/bin in front under MSYSTEM=UCRT64) resolves to the UCRT64 cmake. - packaging/windows/msys2-dependencies.sh: install mingw-w64-ucrt-x86_64-cmake and mingw-w64-ucrt-x86_64-ninja so the UCRT64 build tools are actually present. - CMakeLists.txt: flip ENABLE_RUST_DEMO default to Off. The smoke crate stays in tree; opt in per build. compile-on-windows.sh still passes -DENABLE_RUST_DEMO=Off explicitly during the migration (will flip to =On at Phase 7 to validate Rust on Windows end-to-end). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
3 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packaging/windows/dev-vm.sh">
<violation number="1" location="packaging/windows/dev-vm.sh:63">
P2: `run` embeds raw `$*` inside nested quotes, so PowerShell commands containing quotes are parsed incorrectly. Pass the command as a direct argument instead of interpolating into a quoted command string.</violation>
<violation number="2" location="packaging/windows/dev-vm.sh:69">
P2: `msys` also interpolates raw `$*` into nested quotes, which can break or misparse valid shell commands that include quoting.</violation>
</file>
<file name="packaging/windows/LOCAL_DEV_LINUX.md">
<violation number="1" location="packaging/windows/LOCAL_DEV_LINUX.md:224">
P2: Replace the real username (`vk`) and developer-specific path (`/home/vk/repos/nd/rwin`) with generic placeholders (e.g., `your-username` and `/home/your-username/path/to/repo`). Documentation should not include the author's personal development environment details.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| shift | ||
| [ "${1:-}" = "--" ] && shift | ||
| # Force MSYSTEM=UCRT64 so this matches what build.ps1 sets up. | ||
| ssh "$VM_HOST" "C:\\msys64\\usr\\bin\\bash.exe -lc \"MSYSTEM=UCRT64 $*\"" |
There was a problem hiding this comment.
P2: msys also interpolates raw $* into nested quotes, which can break or misparse valid shell commands that include quoting.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packaging/windows/dev-vm.sh, line 69:
<comment>`msys` also interpolates raw `$*` into nested quotes, which can break or misparse valid shell commands that include quoting.</comment>
<file context>
@@ -0,0 +1,79 @@
+ shift
+ [ "${1:-}" = "--" ] && shift
+ # Force MSYSTEM=UCRT64 so this matches what build.ps1 sets up.
+ ssh "$VM_HOST" "C:\\msys64\\usr\\bin\\bash.exe -lc \"MSYSTEM=UCRT64 $*\""
+ ;;
+ -h|--help|help)
</file context>
| run) | ||
| shift | ||
| [ "${1:-}" = "--" ] && shift | ||
| ssh "$VM_HOST" "powershell -NoProfile -ExecutionPolicy Bypass -Command \"$*\"" |
There was a problem hiding this comment.
P2: run embeds raw $* inside nested quotes, so PowerShell commands containing quotes are parsed incorrectly. Pass the command as a direct argument instead of interpolating into a quoted command string.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packaging/windows/dev-vm.sh, line 63:
<comment>`run` embeds raw `$*` inside nested quotes, so PowerShell commands containing quotes are parsed incorrectly. Pass the command as a direct argument instead of interpolating into a quoted command string.</comment>
<file context>
@@ -0,0 +1,79 @@
+ run)
+ shift
+ [ "${1:-}" = "--" ] && shift
+ ssh "$VM_HOST" "powershell -NoProfile -ExecutionPolicy Bypass -Command \"$*\""
+ ;;
+ msys)
</file context>
|
|
||
| ```powershell | ||
| $mountpoint = "Z:" | ||
| $host_user = "vk" |
There was a problem hiding this comment.
P2: Replace the real username (vk) and developer-specific path (/home/vk/repos/nd/rwin) with generic placeholders (e.g., your-username and /home/your-username/path/to/repo). Documentation should not include the author's personal development environment details.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packaging/windows/LOCAL_DEV_LINUX.md, line 224:
<comment>Replace the real username (`vk`) and developer-specific path (`/home/vk/repos/nd/rwin`) with generic placeholders (e.g., `your-username` and `/home/your-username/path/to/repo`). Documentation should not include the author's personal development environment details.</comment>
<file context>
@@ -0,0 +1,378 @@
+
+```powershell
+$mountpoint = "Z:"
+$host_user = "vk"
+$host_ip = "192.168.122.1" # host as seen from the VM
+$host_path = "/home/vk/repos/nd/rwin"
</file context>
The previous follow-up commit (bffb496) successfully switched the Windows build to the UCRT64 cmake, confirmed by CI: CMAKE_SYSTEM_NAME now reports Windows and _nd_windows_config() is reached. One step deeper, a new error surfaced: CMake Error at packaging/cmake/Modules/NetdataPlatform.cmake:16: CMAKE_INSTALL_PREFIX must be set to /opt/netdata, but it is set to C:/msys64/opt/netdata Root cause: the UCRT64 cmake is a native Windows binary; when given -DCMAKE_INSTALL_PREFIX=/opt/netdata on the command line, it interprets the path as MSYS2-mounted POSIX and canonicalises it to the equivalent native Windows path C:/msys64/opt/netdata. Both forms refer to the same on-disk install location -- only the string differs from what the MSYS-cmake would have kept verbatim. Fix: relax the equality check to accept either the exact /opt/netdata (Linux and MSYS-cmake) or anything ending in /opt/netdata (UCRT64-cmake canonical form). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|



Summary
rust-demostaticlib smoke crate (src/crates/rust-demo/) wired into the mainnetdatatarget via a newENABLE_RUST_DEMOoption (default ON on Linux/macOS, explicitly OFF on Windows during migration). At the end of the migration the Windows opt-out gets removed and the crate becomes the canary that proves Rust now builds and links on Windows.<sys/cygwin.h>/cygwin_conv_path()calls and POSIX↔Winsock2 type mismatches — that failure list is exactly the backlog for the next phases.What's in the PR
Three commits, each independently reviewable:
8733eadfrust-demosmoke crate (Cargo.toml, src/lib.rs, hand-written rust_demo.h) and wire it intoCMakeLists.txtbehind a newENABLE_RUST_DEMOoption (default ON). Adds onenetdata_log_info(\"RUST FFI smoke: …\")call next to the existingNETDATA STARTUPlog line.0b022181packaging/windows/compile-on-windows.shnow passes-DENABLE_RUST_DEMO=Offso the Windows path is not noised by Rust output while the migration phases iterate. Documents the pivot in SOWs.da82bd03MSYSTEM=UCRT64in every PowerShell entry point; require it inNetdataPlatform.cmakewith aFATAL_ERRORotherwise; drop the explicit-DRust_COMPILER(Corrosion finds rustc/cargo on PATH under UCRT64); replace the MSYS and MINGW64 CLion.batfiles with a single UCRT64 variant.Background
Investigation in SOW-0032 showed:
MSYSTEMis never set; permsys2/MSYS2-packagesfilesystem/msystemit defaults toMSYS).msys-2.0.dll(Cygwin POSIX emulation, LP64:longis 8 bytes)./ucrt64/bin/rustcproduces UCRT-linked LLP64 (longis 4 bytes) objects.long-bearing struct cannot safely cross the FFI boundary. For trivial smoke-crate FFI (onlyint32_tand static pointers) it's harmless, but it blocks the project's plan to ship "a lot of Rust code" via in-process integration.The migration plan is documented in SOW-0033, with eight phases. The remaining phases include replacing the ~10
cygwin_conv_path()call sites in 5 files with a Win32-native helper (Phase 3), auditing POSIX↔Winsock2 across the codebase (Phase 4), slimming the installer from ~100 MB of bundled MSYS2 down to just the UCRT64 runtime DLLs (Phase 6), and removing the Windows opt-out so the smoke crate validates Rust-on-Windows end-to-end (Phase 7).Why draft
Test plan
cygwin_conv_path()no longer referenced from netdata C sources.ntldd netdata.exeagainst the staged installer payload confirms no transitively-required DLL is missed.RUST FFI smoke: rust-demo 0.1.0 reports nd_rust_add(2, 3) = 5.🤖 Generated with Claude Code
Summary by cubic
Switch Windows builds to MSYS2
UCRT64and enforce it at configure time; add a small, opt‑in Rust FFI smoke crate to validate toolchain integration. Also adds a Linux→Windows dev workflow and fixes the CMake install prefix check for UCRT64 CMake.Migration
MSYSTEM=UCRT64inNetdataPlatform.cmake(fail fast); dropCYGWIN/MSYSbranches and collapse CLion includes to UCRT64.MSYSTEM=UCRT64; callcmakevia PATH to use UCRT64 tools; install UCRT64cmake/ninjainmsys2-dependencies.sh.-DRust_COMPILER;Corrosionfindsrustc/cargoon PATH; replace MSYS/MINGW CLion envs with a single UCRT64 variant.CMAKE_INSTALL_PREFIXcheck to accept/opt/netdataand the UCRT64‑CMake canonical form (e.g.C:/msys64/opt/netdata).packaging/windows/LOCAL_DEV_LINUX.mdanddev-vm.shfor driving a Windows VM from Linux during the migration.New Features
src/crates/rust-demo(staticlib) andENABLE_RUST_DEMO(default OFF).netdatabehindHAVE_RUST_DEMO; startup logs “RUST FFI smoke…” withnd_rust_add(2, 3). Keep-DENABLE_RUST_DEMO=Offon Windows during the migration and re‑enable at the end to validate the move.Written for commit d46fba1. Summary will update on new commits. Review in cubic