Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
853d655
all github workflows are static now.
bendecaf Feb 28, 2026
fb3bc88
Switched everything to vcpkg.
bendecaf Feb 28, 2026
d8147d4
All builds running on vcpkg and ninja by default.
bendecaf Feb 28, 2026
4c62895
updated readme.
bendecaf Feb 28, 2026
dc00382
Update README.md
bendecaf Feb 28, 2026
1cc6ab7
cmakelists fixes adaptations to prevent using system installed packages.
bendecaf Feb 28, 2026
ec488f5
documentation fixes.
bendecaf Feb 28, 2026
1a3104e
build fix.
bendecaf Feb 28, 2026
fa95079
build fixes.
bendecaf Feb 28, 2026
5b5d5d1
readme fixes
bendecaf Feb 28, 2026
ab1af57
workflow fixes
bendecaf Feb 28, 2026
2af2337
cmake fixes.
bendecaf Feb 28, 2026
bd205ed
correct vcpkg baseline fetch
bendecaf Feb 28, 2026
ee9cd26
build fixes.
bendecaf Feb 28, 2026
953d210
caching a bit more conservative.
bendecaf Feb 28, 2026
096e79b
switched python example to uv.
bendecaf Feb 28, 2026
5e6de6d
github workflow fixes, java client windows job fixes.
bendecaf Feb 28, 2026
adbe36f
windows job objects cleanup for python
bendecaf Feb 28, 2026
b0d8032
cpp example windows job object cleanup
bendecaf Feb 28, 2026
9acbc4e
windows job object cleanups.
bendecaf Feb 28, 2026
8ac4152
linux/macos fix.
bendecaf Feb 28, 2026
730c415
workflow improvements.
bendecaf Feb 28, 2026
6cc4e22
github runner fixes
bendecaf Mar 1, 2026
27685c2
Update build.yml
bendecaf Mar 1, 2026
dcb5aa9
Update build.yml
bendecaf Mar 1, 2026
4bd4da1
Update build.yml
bendecaf Mar 1, 2026
04e7862
windows workflow fixes.
bendecaf Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 168 additions & 40 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,70 +13,187 @@ jobs:
include:
- os: ubuntu-latest
name: Linux x64
toolchain: clang
- os: macos-15
name: macOS Apple Silicon
toolchain: clang
# - os: windows-latest
# name: Windows MSVC
# toolchain: msvc
- os: windows-latest
name: Windows MSVC
name: Windows Clang
toolchain: clang

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Dependencies (Linux)
- name: Install Build Tools (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build g++ clang libsqlite3-dev git libgrpc++-dev protobuf-compiler-grpc libspdlog-dev
sudo apt-get install -y cmake ninja-build g++ clang pkg-config

- name: Install Dependencies (macOS)
- name: Install Build Tools (macOS)
if: runner.os == 'macOS'
run: |
brew install cmake ninja sqlite pkg-config grpc protobuf spdlog
brew install cmake ninja pkg-config

- name: Cache Boost
id: cache-boost
uses: actions/cache@v4
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
path: third_party/boost
key: boost-1.90.0-${{ runner.os }}
key: ${{ runner.os }}-${{ matrix.toolchain }}-ccache

- name: Setup ccache
- name: Setup MSVC Developer Command Prompt
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: Select Windows storage for vcpkg
if: runner.os == 'Windows'
id: win_storage
shell: pwsh
run: |
$candidates = @()
foreach ($p in @($env:RUNNER_TEMP, $env:GITHUB_WORKSPACE, 'D:\', 'C:\')) {
if (-not $p) { continue }
if (-not (Test-Path $p)) { continue }
$resolved = (Resolve-Path $p).Path
$qualifier = Split-Path -Qualifier $resolved
$driveName = $qualifier.TrimEnd('\').TrimEnd(':')
$drive = Get-PSDrive -Name $driveName -ErrorAction SilentlyContinue
if ($drive) {
$candidates += [pscustomobject]@{
Root = $qualifier
Free = [int64]$drive.Free
}
}
}

if (-not $candidates) {
throw "Could not determine a writable storage location for vcpkg."
}

$best = $candidates | Sort-Object Free -Descending | Select-Object -First 1
$base = Join-Path $best.Root "vcpkg-cache"

$archives = Join-Path $base "archives"
$downloads = Join-Path $base "downloads"
$buildtrees = Join-Path $base "buildtrees"
$packages = Join-Path $base "packages"

New-Item -ItemType Directory -Force -Path $archives, $downloads, $buildtrees, $packages | Out-Null

"VCPKG_DEFAULT_BINARY_CACHE=$archives" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"VCPKG_DOWNLOADS=$downloads" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

"vcpkg_cache_dir=$archives" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"vcpkg_downloads_dir=$downloads" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append

# --- THE FIX: Create Junctions to redirect C: to D: ---
# 1. Remove existing directories if GitHub pre-created them
Remove-Item -Path "C:\vcpkg\buildtrees" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "C:\vcpkg\packages" -Recurse -Force -ErrorAction SilentlyContinue

# 2. Create the junctions
New-Item -ItemType Junction -Path "C:\vcpkg\buildtrees" -Target $buildtrees | Out-Null
New-Item -ItemType Junction -Path "C:\vcpkg\packages" -Target $packages | Out-Null

# --- PROOF OF REDIRECTION ---
Write-Host "Testing the Junctions..."
Set-Content -Path "C:\vcpkg\buildtrees\proof.txt" -Value "This is actually on the D drive!"
if (Test-Path "$buildtrees\proof.txt") {
Write-Host "SUCCESS: C:\vcpkg\buildtrees is successfully routing to the D: drive!"
} else {
Write-Error "FAILURE: Junction didn't work."
}

$bestGb = [math]::Round($best.Free / 1GB, 2)
Write-Host "Selected vcpkg storage root: $($best.Root)"
Write-Host "Selected drive free space: $bestGb GB"

- name: Restore vcpkg binary archives (Unix)
if: runner.os != 'Windows'
uses: hendrikmuhs/ccache-action@v1.2
id: vcpkg_cache_restore_unix
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-ccache
path: ~/.cache/vcpkg/archives
key: vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }}
restore-keys: |
vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-

- name: Cache vcpkg dependencies
- name: Restore vcpkg binary archives (Windows)
if: runner.os == 'Windows'
uses: actions/cache@v4
id: vcpkg_cache_restore_windows
uses: actions/cache/restore@v4
with:
path: build/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
path: ${{ steps.win_storage.outputs.vcpkg_cache_dir }}
key: vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }}
restore-keys: |
vcpkg-${{ runner.os }}-
vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-

- name: Clone Boost
if: steps.cache-boost.outputs.cache-hit != 'true'
shell: bash
- name: Ensure vcpkg baseline commit is available (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p third_party
git clone --branch boost-1.90.0 https://github.com/boostorg/boost.git third_party/boost
cd third_party/boost
git submodule update --init --recursive
BASELINE=$(python3 -c "import json; print(json.load(open('vcpkg.json', encoding='utf-8'))['builtin-baseline'])")
git -C "$VCPKG_INSTALLATION_ROOT" fetch --no-tags origin "$BASELINE" || git -C "$VCPKG_INSTALLATION_ROOT" fetch --tags --prune origin
git -C "$VCPKG_INSTALLATION_ROOT" cat-file -e "${BASELINE}^{commit}"

- name: Ensure vcpkg baseline commit is available (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$baseline = (Get-Content vcpkg.json | ConvertFrom-Json).'builtin-baseline'
git -C "$env:VCPKG_INSTALLATION_ROOT" fetch --no-tags origin $baseline
if ($LASTEXITCODE -ne 0) {
git -C "$env:VCPKG_INSTALLATION_ROOT" fetch --tags --prune origin
}
git -C "$env:VCPKG_INSTALLATION_ROOT" cat-file -e "$baseline`^{commit}"

- name: Configure CMake (Unix)
if: runner.os != 'Windows'
run: cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DBOOST_SOURCE_DIR=${{ github.workspace }}/third_party/boost
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
TRIPLET="x64-linux" # vcpkg's x64-linux defaults to static libraries
else
TRIPLET="arm64-osx-release" # Force static linking on macOS
fi

cmake -G Ninja -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \
-DVCPKG_TARGET_TRIPLET=$TRIPLET

- name: Save vcpkg binary archives (Unix)
if: ${{ runner.os != 'Windows' && always() && steps.vcpkg_cache_restore_unix.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: ~/.cache/vcpkg/archives
key: vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }}

- name: Build (Unix)
if: runner.os != 'Windows'
run: cmake --build build --config Release

- name: Configure CMake (Windows)
if: runner.os == 'Windows'
run: cmake -B build -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static -DRPS_MSVC_STATIC_RUNTIME=ON -DBOOST_SOURCE_DIR="${{ github.workspace }}/third_party/boost"
- name: Configure CMake (Windows MSVC)
if: runner.os == 'Windows' && matrix.toolchain == 'msvc'
run: cmake -G Ninja -B build -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DRPS_MSVC_STATIC_RUNTIME=ON

- name: Configure CMake (Windows Clang)
if: runner.os == 'Windows' && matrix.toolchain == 'clang'
run: cmake -G Ninja -B build -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DRPS_MSVC_STATIC_RUNTIME=ON

- name: Save vcpkg binary archives (Windows)
if: ${{ runner.os == 'Windows' && always() && steps.vcpkg_cache_restore_windows.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: ${{ steps.win_storage.outputs.vcpkg_cache_dir }}
key: vcpkg-archives-${{ runner.os }}-${{ matrix.toolchain }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }}

- name: Build (Windows)
if: runner.os == 'Windows'
Expand All @@ -92,22 +209,33 @@ jobs:
cp build/apps/rps-vstscannermaster/vstscannermaster release_stage/
cp build/examples/cpp/rps-example-client release_stage/
cd release_stage
zip -r ../rps-binaries-${{ matrix.os }}.zip ./*
zip -r "../rps-binaries-${{ matrix.name }}.zip" ./*

- name: Stage & Zip Binaries (Windows)
if: runner.os == 'Windows'
- name: Stage & Zip Binaries (Windows MSVC)
if: runner.os == 'Windows' && matrix.toolchain == 'msvc'
run: |
New-Item -ItemType Directory -Force -Path release_stage
Copy-Item build\apps\rps-server\rps-server.exe release_stage\
Copy-Item build\apps\rps-standalone\rps-standalone.exe release_stage\
Copy-Item build\apps\rps-pluginscanner\rps-pluginscanner.exe release_stage\
Copy-Item build\apps\rps-vstscannermaster\vstscannermaster.exe release_stage\
Copy-Item build\examples\cpp\rps-example-client.exe release_stage\
Compress-Archive -Path release_stage\* -DestinationPath "rps-binaries-${{ matrix.name }}.zip"

- name: Stage & Zip Binaries (Windows Clang)
if: runner.os == 'Windows' && matrix.toolchain == 'clang'
run: |
New-Item -ItemType Directory -Force -Path release_stage
Copy-Item build\apps\rps-server\Release\rps-server.exe release_stage\
Copy-Item build\apps\rps-standalone\Release\rps-standalone.exe release_stage\
Copy-Item build\apps\rps-pluginscanner\Release\rps-pluginscanner.exe release_stage\
Copy-Item build\apps\rps-vstscannermaster\Release\vstscannermaster.exe release_stage\
Copy-Item build\examples\cpp\Release\rps-example-client.exe release_stage\
Compress-Archive -Path release_stage\* -DestinationPath rps-binaries-${{ matrix.os }}.zip
Copy-Item build\apps\rps-server\rps-server.exe release_stage\
Copy-Item build\apps\rps-standalone\rps-standalone.exe release_stage\
Copy-Item build\apps\rps-pluginscanner\rps-pluginscanner.exe release_stage\
Copy-Item build\apps\rps-vstscannermaster\vstscannermaster.exe release_stage\
Copy-Item build\examples\cpp\rps-example-client.exe release_stage\
Compress-Archive -Path release_stage\* -DestinationPath "rps-binaries-${{ matrix.name }}.zip"

- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: rps-binaries-${{ matrix.os }}
path: rps-binaries-${{ matrix.os }}.zip
name: rps-binaries-${{ matrix.name }}
path: rps-binaries-${{ matrix.name }}.zip
retention-days: 7
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@ kiloHearts.log

.vscode

plans/
plans/
build_ninja_msvc/vcpkg-manifest-install.log
build_ninja_msvc/CMakeCache.txt
build_ninja_msvc/CMakeFiles/cmake.check_cache

_private
69 changes: 40 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,28 @@ cmake_minimum_required(VERSION 3.25)
cmake_policy(SET CMP0167 NEW)

project(rps-plugin-scanner
VERSION 0.2.0
DESCRIPTION "Reliable Plugin Scanner"
VERSION 0.2.1
DESCRIPTION "RPS"
LANGUAGES C CXX
)

# x64-windows* vcpkg triplets produce MSVC-ABI binaries. Using GNU-targeting
# clang++ (e.g. MSYS2 clang64) with those libraries causes linker failures
# such as missing LIBCMTD/OLDNAMES import libs.
if(WIN32
AND VCPKG_TARGET_TRIPLET MATCHES "^x64-windows"
AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
AND NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
message(FATAL_ERROR
"Incompatible toolchain combination detected:\n"
" compiler: ${CMAKE_CXX_COMPILER}\n"
" triplet: ${VCPKG_TARGET_TRIPLET}\n\n"
"The selected vcpkg triplet uses MSVC ABI libraries, but this clang++ "
"targets GNU/MinGW. Use one of:\n"
" 1) clang-cl or cl.exe with -DVCPKG_TARGET_TRIPLET=x64-windows-static\n"
" 2) clang++ with a MinGW triplet (for example x64-mingw-static).")
endif()

# Enforce strictly C++23
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -21,11 +38,17 @@ else()
option(RPS_MSVC_STATIC_RUNTIME "Use static MSVC runtime (/MT)" OFF)
endif()

if(MSVC AND RPS_MSVC_STATIC_RUNTIME)
if(WIN32
AND RPS_MSVC_STATIC_RUNTIME
AND (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Resolve LNK4098 by ignoring the runtime we're not using for each config
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:LIBCMTD")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:LIBCMT")
# Resolve LNK4098 by ignoring the runtime we're not using for each config.
# Keep this only for cl.exe-style drivers; clang++ (MSVC target) does not
# accept raw '/NODEFAULTLIB:...' in CMAKE_EXE_LINKER_FLAGS.
if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:LIBCMTD")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:LIBCMT")
endif()
endif()

# Disable Boost Auto-Linking on Windows (CMake handles libraries explicitly)
Expand All @@ -35,7 +58,6 @@ add_definitions(-DBOOST_ALL_NO_LIB)
add_library(rps_warnings INTERFACE)
if(MSVC)
target_compile_options(rps_warnings INTERFACE /W4 /WX /permissive-)
target_compile_definitions(rps_warnings INTERFACE NOMINMAX WIN32_LEAN_AND_MEAN)
else()
target_compile_options(rps_warnings INTERFACE -Wall -Wextra -Wpedantic -Werror)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
Expand All @@ -44,33 +66,22 @@ else()
endif()
endif()

if(WIN32)
target_compile_definitions(rps_warnings INTERFACE
NOMINMAX
WIN32_LEAN_AND_MEAN
_CRT_SECURE_NO_WARNINGS
)
endif()

# Force static linking
if(WIN32 AND NOT MSVC)
if(WIN32 AND NOT MSVC AND NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
endif()

# Boost: build from local source tree via add_subdirectory
# Override with: cmake -DBOOST_SOURCE_DIR=/path/to/boost
# or: export BOOST_SOURCE_DIR=/path/to/boost && cmake -B build
if(DEFINED ENV{BOOST_SOURCE_DIR} AND NOT DEFINED BOOST_SOURCE_DIR)
set(BOOST_SOURCE_DIR "$ENV{BOOST_SOURCE_DIR}" CACHE PATH "Path to Boost source tree (requires Boost 1.90+)")
else()
set(BOOST_SOURCE_DIR "${CMAKE_SOURCE_DIR}/third_party/boost" CACHE PATH "Path to Boost source tree (requires Boost 1.90+)")
endif()
if(NOT EXISTS "${BOOST_SOURCE_DIR}/CMakeLists.txt")
message(FATAL_ERROR
"Boost CMake source tree not found at: ${BOOST_SOURCE_DIR}\n"
"Note: The official boost.org tarball does NOT include CMake support.\n"
"You must clone Boost from GitHub:\n"
" git clone https://github.com/boostorg/boost.git /path/to/boost\n"
" cd /path/to/boost && git checkout boost-1.90.0\n"
" git submodule update --init --recursive\n"
"Then pass: cmake -DBOOST_SOURCE_DIR=/path/to/boost\n"
)
endif()
set(BOOST_INCLUDE_LIBRARIES json program_options filesystem process interprocess uuid dll date_time)
add_subdirectory(${BOOST_SOURCE_DIR} ${CMAKE_BINARY_DIR}/_deps/boost EXCLUDE_FROM_ALL)
# Boost: managed entirely by vcpkg
find_package(Boost REQUIRED COMPONENTS json program_options filesystem process interprocess uuid dll date_time crc)

# Find SQLite3
# Prefer the static library; fall back to shared via find_package
Expand Down
Loading
Loading