StreamTxDemo: fix mingw/Windows-GCC build and binary stdin#100
Conversation
Building the stream-link TX demo with mingw (GCC on Windows) was broken two ways:
1. The Windows include block (io.h/fcntl.h) and the
`_setmode(_fileno(stdin), _O_BINARY)` call were gated on `_MSC_VER`, but
mingw/GCC defines `_WIN32`, not `_MSC_VER`. So mingw fell into the POSIX
`#else` branch, left stdin in TEXT mode, and a 0x1A or CRLF byte in the
binary length-prefixed PSDU stream truncated the first record
("short read on stdin (76/269); record truncated mid-PSDU") before a single
frame was transmitted. Add a `__MINGW32__/__MINGW64__` include branch
(io.h + fcntl.h + unistd.h + libusb) and gate `_setmode` on `_WIN32`
(identical on MSVC, now also correct on mingw).
2. CMakeLists unconditionally set CMAKE_TOOLCHAIN_FILE to
"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" on WIN32; with
VCPKG_ROOT unset (the mingw/pkg-config case) it expands to the bogus
"/scripts/buildsystems/vcpkg.cmake" and configuration aborts. Only set it
when VCPKG_ROOT is non-empty.
Verified on mingw-w64 (libusb 1.0.28 via pkg-config): StreamTxDemo.exe now
reads the full binary stream and radiates every frame
("TX #N ok=1 ... done; sent 512 PSDUs").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
josephnef
left a comment
There was a problem hiding this comment.
Reviewed the diff against the source and CI. Both fixes are correct and minimal:
_setmoderegate_MSC_VER→_WIN32+ the__MINGW32__/__MINGW64__include branch — correct. mingw needsio.h+fcntl.hfor_setmode/_O_BINARYandunistd.hforsleep()(used at L214);pid_tand<windows.h>aren't referenced in this file, so their absence from the new branch is harmless. MSVC is unchanged — it defines both_MSC_VERand_WIN32, so it still takes the first include branch and still calls_setmode.- CMake vcpkg guard — correct, and correctly placed before
project()(required forCMAKE_TOOLCHAIN_FILEto take effect). CI's Windows job always setsVCPKG_ROOT, so there's no CI behavior change; the only effect is the unset-VCPKG_ROOT(mingw) case, which is the intent.
One gap before merge: txdemo/stream_duplex_demo/main.cpp has the byte-for-byte identical pattern — include block gated on _MSC_VER (L38) and _setmode gated on _MSC_VER (L202–204) — and it reads the same <u32_le len><PSDU> binary stream via read_exact. So it hits the exact first-frame text-mode truncation this PR fixes for StreamTxDemo. Worse: this PR's CMake change is what makes the duplex demo buildable under mingw in the first place, so as written this PR effectively ships a buildable-but-broken StreamDuplexDemo (mingw isn't in CI, so nothing catches it).
Please mirror the same _WIN32 gate + mingw include branch into stream_duplex_demo/main.cpp so the two stdin-driven stream demos stay in lockstep.
For completeness: precoder_demo/main.cpp and txdemo/main.cpp also gate includes on _MSC_VER, but neither reads length-prefixed stdin nor calls _setmode, so they're unaffected — no change needed there.
Per review: stream_duplex_demo/main.cpp had the byte-identical _MSC_VER-gated
include block + _setmode and reads the same <u32_le len><PSDU> binary stream,
so it hit the same first-frame text-mode truncation — and this PR's CMake guard
is what makes it buildable under mingw in the first place. Mirror the
StreamTxDemo fix (__MINGW32__/__MINGW64__ include branch + _setmode gated on
_WIN32) so the two stdin-driven stream demos stay in lockstep.
Verified on mingw-w64: StreamDuplexDemo now reads all 512 length-prefixed FEC
PSDUs from stdin without truncation ("tx OpenIPC#1..#500 ok=1 ... tx EOF after 512").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Good catch — fixed in 2880c0d.
Verified on mingw-w64 (libusb 1.0.28) with the real RTL8812AU — (pre-fix it died at Agreed on |
## Problem CI builds the Windows target with MSVC + vcpkg only — mingw-w64 (GCC on Windows) is never exercised. That's the toolchain the recent stream-demo binary-stdin fix (#100) targets: mingw defines `_WIN32` but not `_MSC_VER`, and gets libusb from pkg-config rather than vcpkg. Two gaps follow: - Nothing catches a mingw build/link break (e.g. the CMake `VCPKG_ROOT` guard, or a missing include branch). - Worse, the actual runtime bug class is invisible to a build-only check: reverting the `_setmode` gate from `_WIN32` back to `_MSC_VER` compiles clean on mingw and only truncates the first PSDU at runtime. ## Change **1. `build-mingw` CI job** — MSYS2 / MINGW64, libusb via `pkgconf`, `VCPKG_ROOT` unset (so CMake takes the pkg-config path). Builds all targets and runs `ctest`. **2. Headless stdin-binary regression test** - `txdemo/stream_stdin.h` — single source of truth for the `_WIN32`-gated `set_stdin_binary()` plus a tri-state `read_exact()`. Both stream demos now use it (removes two duplicate `read_exact` copies; behavior preserved — `StreamTxDemo` aborts on a truncated record, `StreamDuplexDemo` stops its TX thread and keeps RX running). - `StreamStdinSelftest` + `tests/stream_stdin_test.cmake` — pipes a canonical `<u32_le len><PSDU>` stream containing `0x1A`/CRLF through the same gate the demos use and asserts the round-trip. No libusb, no radio. Registered as the `stream_stdin_binary` ctest. Because the demos and the self-test share the gate, a regression fails `ctest` on the Windows/mingw jobs instead of only surfacing on hardware. `ctest` now runs in every job, so a total gate removal is also caught on the MSVC cell. ## Verification Local (macOS): all targets build, `ctest` passes (`records=5 bytes=20 OK`), and a truncated-at-`0x1A` stream correctly fails the test. The mingw job and Windows text-mode behavior validate in CI. ## Notes - `build-mingw` is intentionally **not** a required status check yet — suggest landing it non-required and promoting once it's proven stable. - The now-redundant `io.h`/`fcntl.h` in the demos' `_MSC_VER`/`__MINGW32__` include branches were left in place to keep this diff off the just-merged #100 include structure; trivial follow-up to tidy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem
Building
StreamTxDemo(the stream-link TX demo) with mingw-w64 (GCC on Windows) is broken in two independent ways. Both are mingw-only and do not affect the MSVC/vcpkg build.1. Binary stdin not set on mingw → first frame truncated
txdemo/stream_tx_demo/main.cppgates both the Windows includes (io.h/fcntl.h) and the_setmode(_fileno(stdin), _O_BINARY)call on#if defined(_MSC_VER). mingw/GCC defines_WIN32but not_MSC_VER, so it falls into the POSIX#elsebranch and leaves stdin in text mode. A0x1A(or CRLF) byte in the binary<u32_le len><PSDU>stream then triggers:and the demo exits before transmitting a single frame.
2. CMake aborts under mingw (no vcpkg)
CMakeLists.txtunconditionally setsCMAKE_TOOLCHAIN_FILEto"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"onWIN32. WithVCPKG_ROOTunset (the normal mingw / pkg-config case) this expands to the bogus/scripts/buildsystems/vcpkg.cmakeand configuration fails with "Could not find toolchain file".Fix
__MINGW32__ || __MINGW64__include branch (io.h + fcntl.h + unistd.h + libusb) and gate_setmodeon_WIN32— identical behavior on MSVC, now also correct on mingw.VCPKG_ROOTis non-empty.Verification
mingw-w64, libusb 1.0.28 via pkg-config, real RTL8812AU. After the fix
StreamTxDemo.exereads the full binary stream and radiates every frame:🤖 Generated with Claude Code