Skip to content

Cross building support#191

Merged
gophergogo merged 39 commits intomainfrom
dev_improve_client_fetch_tools_cross_build
Feb 13, 2026
Merged

Cross building support#191
gophergogo merged 39 commits intomainfrom
dev_improve_client_fetch_tools_cross_build

Conversation

@bettercallsaulj
Copy link
Collaborator

@bettercallsaulj bettercallsaulj commented Feb 6, 2026

This PR should be merged after PR: #185

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

❌ Code Formatting Check Failed

Some files in this PR are not properly formatted according to the project's clang-format rules.

To fix this issue:

make format

Then commit and push the changes.

@gophergogo
Copy link
Collaborator

gophergogo commented Feb 10, 2026

@bettercallsaulj please rebase this dev branch since #185 is merged and resolve code conflicts. ~thanks.

RahulHere added 25 commits February 11, 2026 10:41
Build scripts for compiling libgopher-mcp on different platforms:
- build-mac-x64.sh: macOS x86_64 (Intel) build
- build-mac-arm64.sh: macOS ARM64 (Apple Silicon) build with auto-dependency install
- build-linux-arm64.sh: Docker-based Linux ARM64 build
- Dockerfile.linux-arm64: Docker image for Linux ARM64 builds

Features:
- Auto-detect architecture and use correct Homebrew path
- Auto-install OpenSSL and libevent dependencies via brew
- Support for cached FetchContent dependencies (_deps-x64, _deps-arm64)
- Verification tool included in build output
Native build scripts (run directly on Linux):
- build-linux-x64.sh: Native build on x86_64 Linux
- build-linux-arm64.sh: Native build on ARM64 Linux
  - Auto-detect package manager (apt, dnf, yum, pacman, apk)
  - Auto-install dependencies (cmake, libssl-dev, libevent-dev)

Docker-based build scripts (cross-compilation):
- build-linux-x64-docker.sh: Build x64 from any platform
- build-linux-arm64-docker.sh: Build ARM64 from any platform
- Dockerfile.linux-x64: Docker image for x64 builds
- Dockerfile.linux-arm64: Docker image for ARM64 builds
Heredocs don't work in Dockerfiles - replaced with printf for
generating the verification tool C source code.
The code uses std::optional which requires C++17. Updated all build
scripts and Dockerfiles to use -DCMAKE_CXX_STANDARD=17.
Added missing include for std::runtime_error used in readLEInt()
and peekLEInt() methods.
Excludes build directories, IDE files, node_modules, and other
artifacts that shouldn't be copied into the Docker container.
Add conditional compilation guards for llhttp-dependent code and fix
Windows compatibility issues to enable cross-compilation for Windows
ARM64 using LLVM-MinGW.

Changes:
- Move https_sse_transport_factory.cc to conditional compilation when
  LLHTTP_FOUND to avoid linker errors when llhttp is disabled
- Add MCP_HAS_LLHTTP guards in http_codec_filter.cc around LLHttpParser
  usage with graceful fallback logging when llhttp unavailable
- Add MCP_HAS_LLHTTP guards in mcp_c_api_connection.cc for HTTP+SSE
  transport case with proper error handling
- Add POSIX type definitions (mode_t, pid_t, ssize_t, useconds_t) in
  compat.h for MSVC compatibility
- Add Windows socket libraries (ws2_32, crypt32, iphlpapi) linking
- Fix ioctl/ioctlsocket usage in connection_impl.cc for Windows
- Add missing mutex include in logger.h
- Add Docker build infrastructure for Windows ARM64 cross-compilation
Add workflow to build macOS ARM64 and x64 binaries using GitHub-hosted
runners with Apple Silicon (macos-14) and Intel (macos-13) respectively.

Changes:
- Use existing build scripts (build-mac-arm64.sh, build-mac-x64.sh)
- Upload build artifacts with 30-day retention
- Trigger on push to dev_cross_build or manual dispatch
Add GitHub Actions workflow to build libgopher-mcp for all supported
platforms (Linux, Windows, macOS) in both x64 and ARM64 architectures.

Features:
- Linux x64/ARM64: Docker-based builds with QEMU for ARM64
- Windows x64/ARM64: Docker cross-compilation with MinGW/LLVM-MinGW
- macOS x64/ARM64: Native builds on Intel (macos-13) and M1 (macos-14)
- Automatic release creation with versioned tags
- Build artifacts uploaded for 7 days
- Release archives (.tar.gz for Linux/macOS, .zip for Windows)
- Build summary report with platform matrix
The build-all.yml workflow now covers macOS builds for both x64 and ARM64.
Use build-linux-*-docker.sh scripts for cross-compilation on GitHub
runners since the native scripts require matching host architecture.
Add CMAKE_POLICY_VERSION_MINIMUM=3.5 to macOS build scripts to fix
compatibility issue with yaml-cpp's older CMakeLists.txt on GitHub
runners with newer CMake versions.
The macOS-13 runner images have been retired by GitHub Actions.
Update to use macos-14 for x64 builds, which uses cross-compilation
via CMAKE_OSX_ARCHITECTURES=x86_64.
Linux ARM64:
- Use cross-compilation instead of QEMU emulation (much faster)
- Add Dockerfile.linux-arm64-cross with aarch64-linux-gnu toolchain
- Install libssl-dev:arm64 and zlib1g-dev:arm64 for cross-compilation
- Remove QEMU setup from GitHub Actions (no longer needed)

macOS x64:
- Install x86_64 Homebrew and dependencies when cross-compiling on Apple Silicon
- Point CMake to use /usr/local (x86_64) instead of /opt/homebrew (ARM64)
- Add workflow step to install x86_64 OpenSSL and libevent
The build scripts and Dockerfiles had an INSTALL_DIR path mismatch that
caused headers to not be copied to the build output. CMake installed to
${BUILD_DIR}/install but the scripts tried to copy from install_prefix_dir.

Also added header verification to the GitHub workflow to ensure headers
are always included in prebuilt packages.

Changes:
- Fix INSTALL_DIR path in build-mac-x64.sh, build-mac-arm64.sh,
  build-linux-x64.sh, build-linux-arm64.sh
- Fix CMAKE_INSTALL_PREFIX and copy paths in Dockerfile.linux-x64,
  Dockerfile.linux-arm64, Dockerfile.linux-arm64-cross
- Add header verification step to build-all.yml workflow for all platforms
The previous code unconditionally set CMAKE_INSTALL_PREFIX, which
overrode any command-line -DCMAKE_INSTALL_PREFIX=... settings.
This caused Docker builds to install to the wrong directory.

Now uses CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT to only set
the default when the user hasn't specified a custom install prefix.
The event library uses recv/send socket functions which require linking
against ws2_32 on Windows.
Wrap googletest FetchContent in BUILD_TESTS check to avoid
fetching and building googletest when tests are disabled.
This fixes cross-compilation issues where googletest fails
to build due to threading model differences.
Static library targets now use PRIVATE linking for logging and fmt
dependencies to prevent transitive dependencies on shared libraries.
This allows downstream projects using BUILD_BUNDLED_SHARED to create
truly self-contained shared libraries without runtime dependencies on
gopher-mcp shared libraries.

Changes:
- gopher-mcp-logging-static: Link fmt as PRIVATE instead of PUBLIC
- gopher-mcp-event-static: Use static deps with PRIVATE linking
- gopher-mcp-echo-advanced-static: Use static deps with PRIVATE linking
Static library target now explicitly prefers gopher-mcp-logging-static
over gopher-mcp-logging to avoid transitive dependency on shared
logging library.
Add out-of-class definition for McpClient::kConnectionIdleTimeoutSec.
In C++14, static constexpr members require explicit out-of-class
definitions when ODR-used (e.g., passed by reference to functions).
This is only implicitly inline in C++17+.
Set BUILD_SHARED_LIBS=OFF before fetching fmt to ensure it builds
as a static library. This allows fmt symbols to be properly embedded
when creating bundled shared libraries for SDK distribution, eliminating
the runtime dependency on libfmt.dylib.
Move add_subdirectory(src/logging) earlier in the file, before the
gopher-mcp library linking configuration. This ensures gopher-mcp-logging
target exists when gopher-mcp attempts to link against it.

Previously, the logging subdirectory was added at the end of the file
(line 884), but the linking loop ran at line 575. Since CMake processes
directives in order, TARGET gopher-mcp-logging was FALSE during the
linking configuration, causing gopher-mcp shared library to be built
without linking gopher-mcp-logging.
Convert all debug std::cerr statements to use GOPHER_LOG_DEBUG/WARN/ERROR
macros. This enables runtime log level control via the logging framework
instead of compile-time #ifndef NDEBUG guards.

Changes:
- http_codec_filter.cc: Replace debug output with GOPHER_LOG_DEBUG
- mcp_connection_manager.cc: Replace debug output with GOPHER_LOG_DEBUG
- listener_impl.cc: Replace debug output with GOPHER_LOG_DEBUG
- sse_codec_filter.cc: Replace debug output with GOPHER_LOG_DEBUG
- http_sse_transport_socket.cc: Replace error output with GOPHER_LOG_ERROR
- connection_impl.cc: Replace error/debug output with GOPHER_LOG macros
- filter_chain_assembler.cc: Replace output with GOPHER_LOG_DEBUG/ERROR
- enhanced_filter_chain_factory.cc: Replace output with GOPHER_LOG macros
- mcp_server_enhanced_filters.cc: Replace output with GOPHER_LOG macros
- filter_order_validator.cc: Remove redundant std::cerr (already logged)
Files that were converted to use GOPHER_LOG_DEBUG/ERROR/WARN
were missing the log_macros.h include.

Changes:
- filter_chain_assembler.cc: Add log_macros.h include
- http_sse_transport_socket.cc: Add log_macros.h include
- listener_impl.cc: Add log_macros.h include
RahulHere added 12 commits February 11, 2026 10:41
Enables CI builds on the dev_improve_client_fetch_tools_cross_build branch.
Add ws2_32, crypt32, and iphlpapi link libraries to the ARM64
toolchain file, matching the x64 configuration. Also improve
build logging for easier debugging.

Changes:
- Add Windows socket libraries to linker flags
- Add libevent include directory
- Save cmake and make logs for debugging
- Copy logs to output directory
The C API was incorrectly checking for a non-existent gopher-mcp-shared
target, causing it to try linking against static libraries that don't
exist when BUILD_STATIC_LIBS=OFF.

Changes:
- Check BUILD_SHARED_LIBS variable instead of non-existent target
- Prefer shared libraries when available
- Fall back to static only when shared libs not built
The http_sse_transport_socket.cc and https_sse_transport_factory.cc
files don't actually depend on llhttp - only llhttp_parser.cc does.
Moving them out of the conditional fixes Windows ARM64 build which
doesn't use llhttp.
The shouldLog() function was returning false immediately when the bloom
filter didn't contain a logger name (because the logger hadn't been
created yet). This prevented new component loggers from ever logging.

Changes:
- Fix shouldLog() to fall back to global level check when logger doesn't exist
- Enable default sink initialization in initializeDefaults()
- Attach default sink to new loggers in getOrCreateLogger()
The HttpSse transport case was extracting the path from the URL but
discarding it, causing the client to default to /rpc instead of using
the correct path (e.g., /sse) specified in the server URL.

Changes:
- Extract and set config.http_path from URL for HttpSse transport
- Set config.http_host for proper Host header
- Add SSL configuration for HTTPS URLs (matching StreamableHttp behavior)
Internal initialization messages should not be shown to end users by
default. Changed GOPHER_LOG_INFO to GOPHER_LOG_DEBUG for application
lifecycle logs (startup, workers, shutdown).
Internal SDK logs (filter registration, configuration loading, etc.)
should not appear by default. Users can still enable Info/Debug levels
explicitly when needed.
Use static initializer to call evthread_use_pthreads() at program startup,
before any other code (including curl) can initialize libevent. This fixes
the "evthread initialization must be called BEFORE anything else!" error
on systems where curl is compiled with libevent support.

Changes:
- Remove event_enable_debug_mode() which can only be called once and
  causes issues with shared libraries
- Use simple static initializer instead of constructor priority attribute
- evthread_use_pthreads() is safe to call multiple times
Add _WIN32_WINNT=0x0600 compile definition for Windows builds to
ensure inet_ntop and inet_pton are declared. These functions require
Windows Vista or later.
@bettercallsaulj bettercallsaulj force-pushed the dev_improve_client_fetch_tools_cross_build branch from 459e078 to dfec887 Compare February 11, 2026 02:42
@gophergogo
Copy link
Collaborator

gophergogo commented Feb 11, 2026

@bettercallsaulj I have build error even with make clean & make, please fix.

'fmt/format.h' file not found
#include <fmt/format.h>
         ^~~~~~~~~~~~~~

@bettercallsaulj
Copy link
Collaborator Author

@bettercallsaulj I have build error even with make clean & make, please fix.

'fmt/format.h' file not found
#include <fmt/format.h>
         ^~~~~~~~~~~~~~

On my side, there was a building error about gopher-mcp-logging library,
not about <fmt/format.h>.
And I can build it now by:

make clean && make build

RahulHere added 2 commits February 12, 2026 17:17
Add missing gopher-mcp-logging library to test_filter_chain_assembler
target. The filter_chain_assembler.cc uses mcp::logging::LoggerRegistry
methods which require linking against the logging library.
Fixes FileConfigSourceEnhancedTest, test_logger_registry, and
FilterChainEventHubTest that were failing due to various issues.

Changes:
- Fix LoggerRegistry constructor to use LogLevel::Info (was Warning)
- Fix thread safety data race in FilterChainEventHubTest by adding
  mutex protection for shared vector access
- Convert printf-style format strings (%s, %d, %zu) to fmt-style ({})
  in file_config_source.cc to fix "invalid format string" exceptions
@bettercallsaulj bettercallsaulj force-pushed the dev_improve_client_fetch_tools_cross_build branch from 6db7d9e to 610a390 Compare February 12, 2026 09:17
@gophergogo gophergogo merged commit d2d896e into main Feb 13, 2026
9 checks passed
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