Source build · Apple silicon and Intel
Building on macOS
Nobody has finished this build yet. FoxSDR is developed on Windows and has a Linux CI job that passes on every commit. macOS has never been attempted. Everything on this page is derived from the actual build files and that working Linux recipe — but the build itself is unverified. Expect to hit something this page does not mention, and please tell us when you do.
The hard part is already done. The project builds and passes its full test suite on Linux in CI, so the non-Windows code path is genuinely exercised rather than theoretical. What follows is the difference between that path and a Mac.
What you need
Everything except SoapySDR and OpenSSL is vendored in third_party/:
GLFW 3.4, Dear ImGui, PortAudio, pffft, nlohmann/json, tweetnacl and cpp-httplib all
build from source in-tree. Vendored GLFW and PortAudio have real macOS support of their own
— Cocoa and CoreAudio — so they should need nothing from you.
xcode-select --install # Apple Clang, needs C++20
brew install cmake ninja soapysdr openssl@3
CMake 3.20 or newer. The project is C++20 with CMAKE_CXX_STANDARD_REQUIRED ON,
so an old Xcode fails at configure rather than mysteriously later.
SoapySDR is what talks to radios. FoxSDR has no device-specific code at all —
every receiver arrives through SoapySDR::Device::enumerate(), so whatever
SoapySDR modules you install are what it can use. brew install soapyrtlsdr,
soapyairspy, soapyhackrf and so on, as suits your hardware. FoxSDR
runs perfectly well with none of them, using the built-in signal generator or I/Q file
playback.
Build
git clone https://github.com/wonderingStars/foxsdr.git
cd foxsdr
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3)"
cmake --build build -j"$(sysctl -n hw.ncpu)"
OPENSSL_ROOT_DIR is the one flag Linux does not need. macOS ships LibreSSL rather
than OpenSSL, and Homebrew deliberately keeps openssl@3 off the default search
path, so find_package(OpenSSL REQUIRED) will not find it on its own. OpenSSL is
used for the password digest primitives and for the plugin catalogue's HTTPS client; Windows
uses CNG and WinHTTP instead, which is why it is not a dependency there.
Then:
ctest --test-dir build --output-on-failure
./build/cascade --selftest
Run --selftest before concluding anything works. It drives the real DSP
chain headlessly and asserts a known spectrum peak, so it catches a build that links cleanly,
passes its unit tests, and computes wrong numbers.
One test opens a real window. On Linux CI that needs Xvfb; on macOS just run the tests from a normal logged-in GUI session and it should be fine.
The one patch you will almost certainly need
Two functions find the executable's own directory using Linux's /proc,
which does not exist on macOS:
src/core/band_plan.cpp, inBandPlan::defaultDir()src/core/plugin_host.cpp, around line 888
Both do:
const fs::path link = fs::read_symlink("/proc/self/exe", ec);
On macOS that fails, ec is set, the path stays empty, and both fall back to a
path relative to the current directory. Nothing crashes — but the app will not find its
band plans or its plugins unless you happen to launch it from the build directory. The fix is
an __APPLE__ branch using _NSGetExecutablePath, and both files
already have the #ifdef structure to hang it on:
#elif defined(__APPLE__)
char buf[PATH_MAX];
uint32_t size = sizeof(buf);
if (_NSGetExecutablePath(buf, &size) == 0) {
std::error_code rc;
const fs::path resolved = fs::canonical(fs::path(buf), rc);
exe = rc ? fs::path(buf) : resolved;
}
#else
// existing Linux /proc branch
#endif
with #include <mach-o/dyld.h> and #include <climits>
alongside the other platform headers. _NSGetExecutablePath can return a path
containing symlinks and .., which is why it is worth running through
fs::canonical.
There is a test for the first one — test_band_plan asserts that
defaultDir() ends in bandplans and is never a plain file — so
you get a signal either way.
What will not work, and is not worth chasing
- No crash reports. The crash handler is built on dbghelp and is Windows-only.
- No usage reporting. The sender is WinHTTP-only, so a Mac build reports nothing — the same is already true of the Linux build.
- The window keeps its title bar.
src/gui/win_frame.cppimplements the frameless window throughWM_NCCALCSIZEandWM_NCHITTEST; its whole body sits inside#ifdef _WIN32, so it compiles to nothing elsewhere and the window simply looks normal. Cosmetic only.
None of these stop the receiver working.
Band plans
0.81.0 ships nine band plans — world, the three ITU regions, and the UK, US, Canada, Japan and Australia. CMake stages them next to the built binary on every platform, so after a build you should have:
build/resources/bandplans/*.json
Pick your region in the app under Display → Region. If the picker is empty or the
overlay never draws, that is the /proc/self/exe problem above rather than a
missing file — check build/resources/bandplans/ exists first.
Reference: the Linux CI recipe
.github/workflows/build.yml builds on ubuntu-latest and is the
closest thing to a known-good non-Windows build. Its dependency list translates like this:
| Linux | macOS |
|---|---|
build-essential | Xcode Command Line Tools |
cmake ninja-build | brew install cmake ninja |
libsoapysdr-dev | brew install soapysdr |
libssl-dev | brew install openssl@3 + OPENSSL_ROOT_DIR |
libgl1-mesa-dev | in the macOS SDK already |
libx11-dev, libwayland-dev, libxkbcommon-dev, … | not needed — GLFW uses Cocoa |
libasound2-dev | not needed — PortAudio uses CoreAudio |
xvfb | not needed in a GUI session |
Configure and build commands are otherwise identical.
If you get it working
Tell us. A Mac build that somebody has actually run is worth more than this page, and the first person to do it turns "unverified" into a supported platform. The beta programme is where to say so, or write to [email protected].
Licence
FoxSDR is PolyForm Noncommercial — free for noncommercial
use, and building it for yourself is squarely within that.
Commercial use needs a separate licence. The vendored
third-party components keep their own licences, listed in
third_party/THIRD_PARTY.md.