Skip to content

build, ipc, doc: fix the OpenBSD and FreeBSD builds, including multiprocess - #3267

Merged
jamescowens merged 3 commits into
gridcoin-community:developmentfrom
jamescowens:portability/openbsd-freebsd
Aug 20, 2026
Merged

build, ipc, doc: fix the OpenBSD and FreeBSD builds, including multiprocess#3267
jamescowens merged 3 commits into
gridcoin-community:developmentfrom
jamescowens:portability/openbsd-freebsd

Conversation

@jamescowens

@jamescowens jamescowens commented Aug 18, 2026

Copy link
Copy Markdown
Member

Neither BSD could be built as documented. FreeBSD failed to configure at all without a workaround flag, and OpenBSD could not compile the multiprocess build. Both turned out to be portability bugs in this tree rather than packaging problems on those systems.

Verified on OpenBSD 7.8 (amd64) and FreeBSD 15.0-RELEASE (amd64), 4 vCPU / 4 GB each.

FreeBSD — Boost was not found

CMake Error at BoostConfig.cmake:141 (find_package):
  No suitable build variant has been found.
  * libboost_filesystem.so.1.88.0 (release runtime, Boost_USE_DEBUG_RUNTIME=TRUE)
  * libboost_filesystem.a (static, default is shared, ...)

CMake's FindBoost defaults Boost_USE_DEBUG_RUNTIME to TRUE when the caller has not set it (FindBoost.cmake:1699). That selects the MSVC /MDd runtime and means nothing elsewhere — but Boost's own CMake config files honour it on every platform; each variant file opens with:

if(Boost_USE_DEBUG_RUNTIME)
  _BOOST_SKIPPED("libboost_foo.so" "release runtime, ...")

FreeBSD builds only release-runtime variants, so every variant was rejected. We reach that default because CMP0167 OLD routes the version probe through the FindBoost module.

Set OFF before the probe rather than cleared afterwards: FindBoost only assigns its default under if(NOT DEFINED ...), so a value set here survives, it also covers the pre-1.70 module-mode branch, and it doesn't discard a value the user passed with -D.

This only bites where FindBoost runs its own module search — it returns early when a BoostConfig.cmake is found, which is why the failure doesn't reproduce everywhere.

OpenBSD — multiprocess did not compile

src/ipc/peercred.cpp:58: error: variable has incomplete type 'struct ucred'

The peer-uid check selected the Linux path on #if defined(SO_PEERCRED), assuming that option implies Linux's struct ucred. OpenBSD also defines SO_PEERCRED (sys/socket.h:118) but its payload is struct sockpeercred (line 306). FreeBSD and macOS don't define it at all, which is why only OpenBSD broke.

The condition now keys on __linux__ and is defined once as GRIDCOIN_PEERCRED_SO_PEERCRED, because CheckPeerCredentials() and PeerCredentialEnforcement() must agree — the latter is what the startup log advertises as the enforcement mechanism in force, and a silent disagreement there would misstate a security property. Every non-Linux target we support provides getpeereid(3).

Documentation

Both guides claimed verification against 5.5.0.0, neither mentioned multiprocess or Cap'n Proto, and both pointed at the wrong output directory (build/src/... rather than build/bin/...). Beyond fixing those:

  • Cap'n Proto recorded as the multiprocess-only dependency on both.
  • OpenBSD needs ulimit -d raised before a multiprocess build. login.conf's default class caps datasize at 1536M and clang needs more for the generated Cap'n Proto proxies (one preprocessed TU is ~9 MB), dying with LLVM ERROR: out of memory. That's the per-process limit, not a RAM shortage — worth stating because the message reads like one. Fewer jobs than cores is also recommended: -j2 completed reliably on 4 vCPU / 4 GB, -j4 did not.
  • OpenBSD's clang accepts but ignores -fstack-clash-protection (many argument unused warnings), so that mitigation is not applied there despite being requested. Recorded so nobody assumes it is.
  • The FreeBSD guide's existing Boost workaround was wrong. It required -DBoost_USE_DEBUG_RUNTIME=OFF, described it as accepting release Boost "even when building with debug symbols", and offered Release as an alternative that avoids it. I tested all three build types — Release, RelWithDebInfo and Debug all failed identically; the build type is irrelevant. The flag is no longer needed and the note now says what actually happened.
  • FreeBSD 15.0's capnproto package warns of a kernel bug fixed in 15.1. Reproduced with the finding that Gridcoin's IPC worked anyway, so readers know why pkg shows it rather than assuming it blocks multiprocess.

Verification

OpenBSD 7.8 FreeBSD 15.0
Monolithic build
Multiprocess build
Binaries run
MP GUI attaches over IPC GUI loaded. GUI loaded.
Peer-cred mechanism getpeereid getpeereid

Linux reconfigured and rebuilt with these changes: 0 errors, Boost found identically, core suite No errors detected, Qt suite 8/8. Lint clean with a populated COMMIT_RANGE.

The hardening probe is fixed, not just documented

An earlier revision of this PR documented that OpenBSD's clang silently ignores
-fstack-clash-protection and left it at that. That was the weaker answer: the build was
still requesting a mitigation it did not get, and emitting 316 warnings saying so.

check_cxx_compiler_flag only proves the driver did not reject a flag's spelling. The
probes now run with -Werror=unused-command-line-argument, so a flag the compiler accepts
and then ignores fails the check and is not applied — reported once at configure time
instead of once per translation unit:

-- Hardening: -fstack-clash-protection not applied (compiler accepts no working
   implementation for this target)

GCC has no such warning and errors on the option, so it is probed for first. Setting it
unconditionally would make every hardening probe fail on GCC and silently disable
hardening on Linux
— the exact opposite of the intent, and the thing most worth getting
wrong here.

This does not replace the Mach-O platform gate. -mbranch-protection=standard on
macOS arm64 is accepted and honoured and wrong — it emits real pointer-authentication
code that defeats libunwind. No probe can see that, so it stays gated by platform.

Verified on three toolchains

Toolchain probe stack-protector cf-protection stack-clash
Linux GCC 15.3 Failed (required)
Linux clang 19.1.7 Success
OpenBSD 7.8 clang 19.1.7 Success correctly withheld

On OpenBSD a 208-object build produced 0 "argument unused" warnings (down from 316
across a full build) with 0 errors, and the compile options carry only the two flags that
actually work there. Linux is unchanged on both compilers.

Not addressed

Neither BSD is in CI, so nothing here is regression-protected — the guides still say so. The -fstack-clash-protection gap is now fixed rather than documented (see above), but the mitigation itself remains unavailable on OpenBSD — that is a toolchain property the build cannot work around.

…rocess

Neither BSD could be built as documented. FreeBSD failed to configure at all
without a workaround flag, and OpenBSD could not compile the multiprocess build.
Both are portability bugs in this tree, not packaging problems on those systems.

FreeBSD: Boost was reported as not found.

    CMake Error at BoostConfig.cmake:141 (find_package):
      No suitable build variant has been found.
      * libboost_filesystem.so.1.88.0 (release runtime, Boost_USE_DEBUG_RUNTIME=TRUE)

CMake's FindBoost defaults Boost_USE_DEBUG_RUNTIME to TRUE when the caller has not
set it (FindBoost.cmake:1699). That selects the MSVC /MDd runtime and means nothing
elsewhere, but Boost's own CMake config files honour it on every platform: each
variant file opens with "if(Boost_USE_DEBUG_RUNTIME) _BOOST_SKIPPED(...)". FreeBSD
builds only release-runtime variants, so every variant was rejected. We reach that
default because CMP0167 OLD sends the version probe through the FindBoost module.

Setting it OFF before the probe rather than clearing it afterwards: FindBoost only
assigns its default under if(NOT DEFINED ...), so a value set here survives, it also
covers the pre-1.70 module-mode branch, and it does not discard a value the user set
with -D. Note this only bites where FindBoost runs its own module search -- it
returns early when a BoostConfig.cmake is found, which is why the failure does not
reproduce on every system.

OpenBSD: the multiprocess build did not compile.

    src/ipc/peercred.cpp:58: error: variable has incomplete type 'struct ucred'

The peer-uid check selected the Linux path on "#if defined(SO_PEERCRED)", assuming
that option implies Linux's struct ucred. OpenBSD also defines SO_PEERCRED
(sys/socket.h:118) but its payload is struct sockpeercred (line 306). FreeBSD and
macOS do not define SO_PEERCRED at all, which is why only OpenBSD was affected. The
condition now keys on __linux__ and is defined once as
GRIDCOIN_PEERCRED_SO_PEERCRED, because CheckPeerCredentials() and
PeerCredentialEnforcement() must agree -- the latter is what the startup log
advertises as the enforcement mechanism in force. Every non-Linux target we support
provides getpeereid(3), which OpenBSD now uses.

Documentation. Both guides claimed verification against 5.5.0.0, neither mentioned
multiprocess or Cap'n Proto, and both pointed at the wrong output directory
(build/src/... instead of build/bin/...). Corrected, plus:

  * Cap'n Proto is recorded as the multiprocess-only dependency on both.
  * OpenBSD needs ulimit -d raised before a multiprocess build. login.conf's default
    class caps datasize at 1536M, and clang needs more than that for the generated
    Cap'n Proto proxies (one preprocessed TU is ~9 MB); it dies with "LLVM ERROR: out
    of memory". That is the per-process limit, not a RAM shortage. Fewer build jobs
    than cores is also recommended there -- -j2 completed reliably on 4 vCPU / 4 GB,
    -j4 did not.
  * OpenBSD's clang accepts but ignores -fstack-clash-protection, so that mitigation
    is not applied there despite being requested. Recorded so nobody assumes it is.
  * The FreeBSD guide previously required -DBoost_USE_DEBUG_RUNTIME=OFF and explained
    it as accepting release Boost "even when building with debug symbols", suggesting
    Release as an alternative. That was wrong: Release, RelWithDebInfo and Debug all
    failed identically. The flag is no longer needed and the note now says what
    actually happened.
  * FreeBSD 15.0-RELEASE's capnproto package warns of a kernel bug fixed in 15.1. The
    warning is reproduced along with the finding that Gridcoin's IPC worked anyway, so
    readers know why pkg shows it rather than assuming it blocks multiprocess.

Verified on OpenBSD 7.8 (amd64) and FreeBSD 15.0-RELEASE (amd64), 4 vCPU / 4 GB each:
monolithic and multiprocess both build, the binaries run, and in multiprocess the GUI
attaches to a separately started daemon over IPC ("GUI loaded.") and shuts down
cleanly. Both log "getpeereid (connections from another OS user are refused)". Linux
reconfigured and rebuilt with these changes: 0 errors, core suite "No errors
detected", Qt suite 8/8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves BSD portability for Gridcoin’s CMake-based build and multiprocess IPC credential handling, and updates the OpenBSD/FreeBSD build guides to reflect the corrected build steps and multiprocess requirements.

Changes:

  • Fix Boost discovery on platforms where CMake falls back to FindBoost by setting Boost_USE_DEBUG_RUNTIME=OFF only when the user hasn’t specified it.
  • Fix OpenBSD multiprocess compilation by gating the Linux SO_PEERCRED/struct ucred path on __linux__ instead of SO_PEERCRED alone.
  • Update OpenBSD/FreeBSD build documentation for multiprocess (Cap’n Proto), correct output paths, and add platform-specific notes.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
CMakeLists.txt Sets Boost_USE_DEBUG_RUNTIME up-front (when unspecified) to avoid Boost variant rejection during module-mode FindBoost resolution.
src/ipc/peercred.cpp Introduces a single Linux-only SO_PEERCRED gate macro to avoid OpenBSD’s incompatible SO_PEERCRED payload type.
src/ipc/peercred.h Updates platform-coverage documentation to match the Linux-only SO_PEERCRED/ucred usage.
doc/build-openbsd.md Documents multiprocess prerequisites and OpenBSD-specific build constraints; corrects run paths.
doc/build-freebsd.md Updates guidance for Boost and adds multiprocess/Cap’n Proto notes; corrects run paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread doc/build-openbsd.md Outdated
jamescowens and others added 2 commits August 18, 2026 22:06
…t four

Both guides closed their first code fence with ```` instead of ```, which ends the
block with a fence Markdown does not match and leaves the rest of the page rendering
as if it were still inside code. Pre-existing on development in both files
(build-openbsd.md:15, build-freebsd.md:13), and fixed here because this PR rewrites
both documents and adds the Cap'n Proto lines to the very block that was broken.

Found by Copilot review on the OpenBSD guide; the FreeBSD guide has the identical
defect and is fixed with it.

Verified: no fences of four or more backticks remain in either file, and the fence
count in each is even.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
check_cxx_compiler_flag only proves the driver did not reject a flag's spelling. Clang
accepts a flag it has no implementation for on the current target and then reports

    argument unused during compilation: '-fstack-clash-protection'

on every translation unit. The flag is requested, the mitigation is absent, and the
build gains several hundred warnings saying so -- 316 in a full OpenBSD/amd64 build.
Worse than the noise, the build believes a mitigation is in force that is not.

The probes now run with -Werror=unused-command-line-argument, which turns "accepted but
ignored" into a failed check, so such a flag is simply not added and the omission is
reported at configure time. GCC has no such warning and errors on the option, so it is
probed for first: setting it unconditionally would make every hardening probe fail on
GCC and silently disable hardening on Linux, which is the opposite of the intent.

This does not replace the Mach-O platform gate. -mbranch-protection=standard on macOS
arm64 is accepted AND honoured AND wrong -- it emits real pointer-authentication code
that defeats libunwind. No probe can see that, so it stays gated by platform. The gate's
-fstack-clash-protection entry is now redundant on Darwin (the probe would reject it
there too) but is left in place deliberately rather than churn a macOS configuration
that was expensive to get green.

Verified on three toolchains:

  Linux GCC 15.3      probe Failed (as required); stack-protector, cf-protection and
                      stack-clash all still applied -- no change from before.
  Linux clang 19.1.7  probe Success; same three flags applied, stack-clash included,
                      because clang honours it on this target.
  OpenBSD 7.8 clang   probe Success; stack-clash correctly withheld. A 208-object build
    19.1.7            produced 0 "argument unused" warnings, down from 316 across a full
                      build, with 0 errors. Compile options carry only the two flags that
                      actually work there.

doc/build-openbsd.md previously told readers to expect the warnings and to be aware the
mitigation was silently absent. The warnings are gone, so that note now explains that the
flag is unavailable on OpenBSD, shows the configure-time line that reports it, and states
which mitigations do apply.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jamescowens
jamescowens merged commit b1e242c into gridcoin-community:development Aug 20, 2026
27 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants