Skip to content

fix(liquid-dsp): guard -lc/-lm link flags against WIN32 platforms#3220

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
NF0T:fix/liquid-dsp-windows-lc
May 27, 2026
Merged

fix(liquid-dsp): guard -lc/-lm link flags against WIN32 platforms#3220
ten9876 merged 1 commit into
aethersdr:mainfrom
NF0T:fix/liquid-dsp-windows-lc

Conversation

@NF0T
Copy link
Copy Markdown
Collaborator

@NF0T NF0T commented May 27, 2026

Problem

target_link_libraries(${target} c m) at line 468 of
third_party/liquid-dsp/CMakeLists.txt is a POSIX/Linux convention.
On Windows the C runtime is linked automatically by both MinGW-w64 and
MSVC — passing -lc/-lm explicitly causes MinGW ld to fail at
link time:

cannot find -lc: No such file or directory

This regression was introduced when liquid-dsp was vendored in #3046.

Fix

Wrap the target_link_libraries call in if(NOT WIN32) … endif().
WIN32 is true for both MinGW-w64 and MSVC on Windows (it is a
platform variable, not a compiler variable), so this correctly suppresses
the flag for all Windows toolchains while leaving Linux and macOS
behaviour unchanged.

This is a stopgap that restores a clean Windows build. The full
Windows/MSVC solution (ExternalProject with mingw-w64) is tracked
in #3049.

Testing

  • Built cleanly on Windows 11 with MinGW GCC 13.1.0 / Qt 6.11.0 /
    Ninja — no linker errors.
  • Linux and macOS paths are unchanged; the guard only fires on WIN32.

Related: #3049

🤖 Generated with Claude Code

`target_link_libraries(${target} c m)` is a POSIX/Linux convention.
On Windows, the C runtime is linked automatically by both MinGW-w64 ld
and MSVC — passing `-lc`/`-lm` explicitly causes MinGW ld to error
with "cannot find -lc: No such file or directory" because there is no
standalone libc.a in the MinGW sysroot.

Wrap the call in `if(NOT WIN32)` so MinGW and MSVC builds skip the
redundant link flags while Linux/macOS behaviour is unchanged.

Fixes build on Windows with MinGW GCC 13.1.0 introduced when
liquid-dsp was vendored in PR aethersdr#3046. Tracks upstream issue aethersdr#3049.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix, @NF0T — clean, surgical, and the rationale in the inline comment + PR body is exactly what a future reader needs.

A couple of confirming notes:

  • WIN32 is the right gate. It's set by CMake based on the target platform regardless of the toolchain, so both MinGW-w64 and MSVC are covered. No need to also test MSVC / MINGW.
  • The line target_link_libraries(${target} c m) at third_party/liquid-dsp/CMakeLists.txt:468 is upstream liquid-dsp's POSIX assumption — leaving Linux/macOS untouched preserves upstream behavior, and the guard is the standard idiomatic fix used by other CMake-based ports of liquid-dsp.
  • Scope is appropriately tight: a single vendored-CMakeLists patch. Cleanly labelled as a stopgap until the proper Windows path lands via #3049.

One minor optional suggestion (non-blocking — feel free to ignore): since the if (fftw3f_FOUND) target_link_libraries(${target} fftw3f) block immediately below is unaffected on Windows, the current placement is fine. If you ever wanted to fold the guard, target_link_libraries(${target} $<$<NOT:$<BOOL:${WIN32}>>:c> $<$<NOT:$<BOOL:${WIN32}>>:m>) would work but is strictly less readable than what you have. The explicit if(NOT WIN32) block is the better choice here.

LGTM.


🤖 aethersdr-agent · cost: $3.9241 · model: claude-opus-4-7

@ten9876 ten9876 merged commit bc0011d into aethersdr:main May 27, 2026
5 checks passed
ten9876 pushed a commit that referenced this pull request May 27, 2026
…ign encoding (#3221)

## Summary

Implements a unified RADE TX pipeline that correctly transmits
End-of-Over (EOO) frames with an LDPC-encoded operator callsign,
matching the behaviour of FreeDV-GUI through the same DAX TX path.
Five root-cause fixes were required; EOO+callsign transmission is now
OTA-confirmed against a FreeDV-GUI station (see Test plan).

## Constitution principle honored

**Principle VIII — Evidence Over Assertion**: the EOO fix claim is
backed
by measured `Dtmax12_eoo` values (previously stuck at ~0.21, now
reliably
crossing the ~0.45 detection threshold), `rade_demod_wav -v 2` output
reporting frame-level EOO detection, and OTA callsign decode ("NF0T")
at the far end. The behavior change is demonstrated independently of the
implementing agent's description.

**Principle XI — Fixes Are Demonstrated**: the fix was demonstrated OTA
against a FreeDV-GUI station before this PR was opened; the test
criteria
listed below were all met and are reproducible.

**Principle X — Claims Are Atomic And Mortal**: branch rebased against
current `main` (including the 109-commit upstream batch from 2026-05-27)
before this PR was opened; no stale-snapshot overwrites.

## Changes

### Core pipeline (`src/core/`)
- `RADEEngine`: three-layer PTT intercept — `PttOffHook` holds TX open
  while `setEooRequested(true)` → `rade_tx_eoo()` + callsign encoding
  → FIR flush → 60 ms silence tail → `eooFinished` signal → 254 ms
  transport timer → `set_mox=0`
- `RADEEngine::setTxCallsign()` pre-encodes callsign via
  `rade_text_generate_tx_string()` / `rade_tx_set_eoo_bits()`
- Named timing constants on the class:
  `kEooFrameMs` (144) + `kEooSilenceTailMs` (60) +
  `kEooTransportMarginMs` (50) = 254 ms total
- `Resampler`: removed dead `flush()` stub; added `prewarm()` to
  stabilise FIR state before first audio block

### GUI (`src/gui/`)
- `MainWindow`: three-layer PTT intercept wired up; `PttOffHook`
intercepts MOX button, serial/MIDI, and CAT PTT paths; `kEooPlaybackMs`
  composed from named constants; DAX stream registration uses
  `qCDebug(lcRade)`; VFO signals explicitly disconnected on
  `deactivateRADE()`

### Diagnostics (`#ifdef RADE_WAV_TAP`, off by default)
- Six TAP points (A–F) write per-PTT WAV files for offline analysis
- `rade_demod_wav` build target (wrapped in `EXISTS` guard) for
  verifying EOO frame detectability with `rade_demod_wav -v 2`

### Docs
- `docs/architecture/audio-pipeline.md`: EOO transmission and
three-layer PTT intercept documented; TX flowchart and path table
updated

> **Architecture note:** the three-layer PTT intercept touches
> `MainWindow.cpp` (maintainer-only CODEOWNERS tier). This is an
> architectural change — flagging for maintainer review per
CONTRIBUTING.md.

## Test plan

- [x] Local build passes (`cmake --build build`) — MinGW/Windows clean
- [x] `Dtmax12_eoo` crosses detection threshold (~0.45; was stuck at
~0.21)
- [x] `rade_demod_wav -v 2` reports "End-of-over at modem frame N"
- [x] OTA: far-end FreeDV-GUI station decodes "EOO callsign: NF0T"
- [x] No regression in voice RX/TX quality
- [ ] CI (Linux build — will run on PR open)

> **Note:** FreeDV-GUI only decodes the EOO callsign when Reporting is
> enabled (Tools → Options). `textPtr_` is null when reporting is off;
> the EOO pilot is still detected but the callsign is silently skipped.
> RC4 (output burst cadence) deferred — RC1–RC3/RC5 proved sufficient
OTA.

## Checklist

- [x] Commits are signed (`docs/COMMIT-SIGNING.md`)
- [x] No new flat-key `AppSettings` calls — EOO timing constants are
      `static constexpr` on `RADEEngine` (Principle V)
- [x] No new meter UI — `MeterSmoother` not applicable (Principle II)
- [x] `docs/architecture/audio-pipeline.md` updated

## Related

- Upstream issue #3049 (liquid-dsp Windows build) — stopgap in
  progress via PR #3220; that fix is not included here

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@NF0T NF0T deleted the fix/liquid-dsp-windows-lc branch May 27, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants