Skip to content

Windows/MSVC port of the core packages (SysRap, CSG, QUDArap, CSGOptiX) - #438

Open
wenaus wants to merge 4 commits into
BNLNPPS:synradfrom
wenaus:windows-port
Open

Windows/MSVC port of the core packages (SysRap, CSG, QUDArap, CSGOptiX)#438
wenaus wants to merge 4 commits into
BNLNPPS:synradfrom
wenaus:windows-port

Conversation

@wenaus

@wenaus wenaus commented Aug 20, 2026

Copy link
Copy Markdown
Member

Native Windows build of the four core packages with MSVC v143, CUDA 12.6 and OptiX 8.1, validated against the synchrotron-radiation reference set on an RTX A4500: all six statistical checks of optiphy/ana/synrad_test.py pass against the Linux service hits (chi2/ndf 0.00; wall-absorbed 500000/500000, reflected 362156; 0.24 us/photon).

Four commits, separable by concern:

  1. Build system: BUILD_SHARED_LIBS defaults OFF on Windows (static core), CMAKE_CUDA_STANDARD 20 to match CXX (shared headers use C++20 designated initializers, which GNU-mode nvcc tolerates in C++17 but MSVC-host nvcc rejects), viz-conditional CSGOptiX test targets, and a package config whose dependency set follows the build options (GLEW/glfw3 only with viz, Geant4/CLHEP only for the full build).
  2. Export headers: __declspec branch alongside the GCC visibility attributes.
  3. sysrap/CSG source port: s_windows.h maps POSIX spellings onto the Windows CRT and undefines windows.h macro claims on identifiers the tree uses as C++ names; std::filesystem directory iteration; MSVC intrinsics for ffs/clz; /proc reads via psapi; header-defined statics become C++17 inline variables.
  4. Two portability fixes that also affect Linux static builds: directory-existence checks no longer rely on ifstream being able to open a directory (glibc-only behavior), and the SLOG_INIT macros skip adding a logger to itself as an appender, which in a fully static build made every log record recurse to stack overflow. Both are no-ops for the shared Linux build.

The GLEW/glfw decoupling in the build-system commit also relieves headless Linux workers of windowing-library dependencies: no library source in the four core packages references GL symbols.

?? Generated with Claude Code

https://claude.ai/code/session_01WPwvNpFqo5SrCbrN3wKXra

wenaus and others added 4 commits August 20, 2026 12:20
…t targets, option-aware package config

BUILD_SHARED_LIBS defaults OFF on Windows and the CSGOptiX library follows it.
CMAKE_CUDA_STANDARD 20 matches CMAKE_CXX_STANDARD: shared headers use C++20
designated initializers, which GNU-mode nvcc tolerates in C++17 but MSVC-host
nvcc rejects. MSVC builds define _USE_MATH_DEFINES, NOMINMAX and
WIN32_LEAN_AND_MEAN globally. The generated simphonyConfig.cmake requires
GLEW/glfw3 only with SIMPHONY_WITH_VIZ and Geant4/CLHEP only without
SIMPHONY_CORE_ONLY. CSGOptiX viz tests are guarded by SIMPHONY_WITH_VIZ and
test executables link the CUDA runtime flavor the core was built with.
sysrap installs SSimulator.h and s_windows.h with the other headers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPwvNpFqo5SrCbrN3wKXra
…ttributes

MSVC emits C2143/C2059/C2447 cascades on __attribute__((visibility)) in class
declarations; each *_API macro now selects __declspec(dllexport/dllimport) or
empty (static) under _MSC_VER. 17 sysrap files failed from this single cause.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPwvNpFqo5SrCbrN3wKXra
s_windows.h maps the POSIX spellings the utility layer uses onto the Windows
CRT (getcwd/chdir/popen/pclose/getpid/mkdir, wait-status macros,
gettimeofday, strndup, S_ISDIR/S_ISREG) and undefines the windows.h macro
claims on identifiers the tree uses as C++ names (near, far, CONST,
MOD_SHIFT/MOD_CONTROL/MOD_ALT). Directory iteration moves to std::filesystem
(NPU.hh, SDir.h, sdirectory.h). ffs/ffsll/__builtin_clz map to
_BitScanForward/_BitScanReverse (SBit.cc, sseq.h, csg_postorder.h). /proc
reads become psapi/GetModuleFileNameW (sproc.h). environ maps to the CRT
_environ (ssys.h). gethostname uses GetComputerNameA to avoid the WSAStartup
requirement; unsetenv maps to _putenv_s (SSys.cc). Header-defined statics
that MSVC will not fold across translation units become C++17 inline
variables (SRecord, sseq_record, SLabel::Load, SGLM::TITLE).
spath::is_readable answers directories via std::filesystem since ifstream
cannot open a directory on Windows. NP.hh includes <numeric> for std::iota
and guards M_PI; ssys::popen null-checks the stream and ssys::which shells
out to where with the nul device on Windows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPwvNpFqo5SrCbrN3wKXra
…rence set

SLOG_INIT macros skip adding a logger to itself as an appender: package
logger hookup passes the main plog instance as an appender, and in a fully
static build both are the same object, so every record recursed to stack
overflow (the OPTICKS_SYSRAP consumer define triggered this through
OPTICKS_LOG_::Initialize). Shared-library builds have distinct instances and
are unchanged. PLOG_LOCAL is exported only for shared builds, matching its
per-shared-library purpose. NP::Exists, NPU::is_readable, SPath::IsReadable
and SPath::Exists answer directories via std::filesystem: ifstream-opening a
directory succeeds on Linux (glibc) but always fails on Windows, which left
persisted NPFold trees without subfolds and CSGFoundry geometry unresolvable.

With these, the Windows static synrad service transports the 500k-photon
reference set on an RTX A4500 and matches the Linux service hits across all
six statistical checks (chi2/ndf 0.00; wall-absorbed 500000, reflected
362156; 0.24 us/photon).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPwvNpFqo5SrCbrN3wKXra
Copilot AI lite review requested due to automatic review settings August 20, 2026 17:56

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

Adds a native Windows/MSVC port of Simphony’s core GPU packages (SysRap, CSG, QUDArap, CSGOptiX) by introducing Windows/POSIX compatibility shims, MSVC export macros, and build-system options to support static core builds and optional visualization dependencies.

Changes:

  • Updates CMake configuration to support Windows-static defaults, core-only builds, and viz-conditional dependencies/targets.
  • Adds/uses s_windows.h for MSVC portability and replaces POSIX directory iteration and /proc reads with Windows/std::filesystem equivalents where needed.
  • Adjusts header-defined statics and logging initialization to avoid static-build pitfalls (ODR and logger recursion).

Reviewed changes

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

Show a summary per file
File Description
CMakeLists.txt Sets CUDA standard to C++20, adds core-only/viz options, and changes Windows default to static builds with MSVC-specific defines.
cmake/Config.cmake.in Makes installed config dependencies conditional on viz/core-only options.
sysrap/CMakeLists.txt Makes GLEW/glfw conditional, installs s_windows.h, and gates PLOG_LOCAL by shared builds.
sysrap/SYSRAP_API_EXPORT.hh Adds MSVC __declspec(dllexport/dllimport) export handling for shared builds.
qudarap/QUDARAP_API_EXPORT.hh Adds MSVC __declspec(dllexport/dllimport) export handling for shared builds.
CSG/CSG_API_EXPORT.hh Adds MSVC __declspec(dllexport/dllimport) export handling for shared builds.
CSGOptiX/CSGOPTIX_API_EXPORT.hh Adds MSVC __declspec(dllexport/dllimport) export handling for shared builds.
CSGOptiX/CMakeLists.txt Honors BUILD_SHARED_LIBS and gates PLOG_LOCAL by shared builds.
CSGOptiX/tests/CMakeLists.txt Handles cudart flavor for Windows-static and gates viz test dependencies/targets.
sysrap/s_windows.h New MSVC compatibility header providing POSIX-like APIs/macros and Windows replacements.
sysrap/ssystime.h Uses s_windows.h for gettimeofday on MSVC.
sysrap/s_time.h Uses s_windows.h for gettimeofday and adapts localtime_* usage for MSVC.
sysrap/ssys.h Adds MSVC environment table handling and improves popen error handling / Windows which equivalent.
sysrap/SSys.cc Adds MSVC wait/popen support and implements hostname/unsetenv behavior for Windows.
sysrap/sseq.h Adds MSVC intrinsics-based ffs equivalents when not compiling with CUDA.
sysrap/SBit.cc Adds MSVC intrinsics-based ffs/ffsll implementations.
CSG/csg_postorder.h Adds MSVC intrinsic implementations for ffs/clz-dependent macros.
sysrap/sproc.h Replaces /proc memory query with Windows GetProcessMemoryInfo; implements executable path via GetModuleFileNameA.
sysrap/spath.h Uses std::filesystem::is_directory to make directory readability behavior portable.
sysrap/SPath.cc Uses std::filesystem::is_directory for portable readability/existence checks.
sysrap/NPU.hh Replaces dir iteration with std::filesystem and adds portable directory readability handling; MSVC inet header adjustments.
sysrap/NP.hh Adds missing MSVC headers and portable directory existence/readability behavior.
sysrap/sdirectory.h Replaces dirent usage with std::filesystem directory iteration.
sysrap/SDir.h Replaces dirent usage with std::filesystem directory iteration.
sysrap/SGLM_Modifiers.h Undefines winuser.h macro collisions for modifier enum names.
sysrap/SMath.cc Provides M_PI fallback definition for MSVC builds lacking it.
sysrap/SLOG_INIT.hh Adds guards to prevent self-appending logger recursion in fully static builds.
sysrap/sseq_record.h Converts header-defined static to C++17 inline variable to avoid ODR issues.
sysrap/SRecord.h Converts header-defined static to C++17 inline variable to avoid ODR issues.
sysrap/SLabel.h Makes header-defined function inline to avoid ODR/multiple definition issues.
sysrap/SGLM.h Converts one header-defined static (TITLE) to inline (but leaves others non-inline).

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

Comment thread sysrap/SGLM.h
Comment on lines 726 to 730
SGLM* SGLM::INSTANCE = nullptr ;
SGLM* SGLM::Get(){ return INSTANCE ? INSTANCE : new SGLM ; }

const char* SGLM::TITLE = ssys::getenvvar(kTITLE, "TITLE") ;
inline const char* SGLM::TITLE = ssys::getenvvar(kTITLE, "TITLE") ;
glm::ivec2 SGLM::WH = EVec2i(kWH,"1920,1080") ;
Comment thread CMakeLists.txt
Comment on lines +21 to +24
# 20 not 17: headers shared between C++ and CUDA (e.g. sysrap/torch.h) use
# C++20 designated initializers, which GNU-mode nvcc tolerates in C++17 as an
# extension but MSVC-host nvcc rejects.
set(CMAKE_CUDA_STANDARD 20)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Changing CMAKE_CUDA_STANDARD from 17 to 20 effectively drops our Ubuntu 22.04 configuration, which uses CMake 3.22

@plexoos

plexoos commented Aug 25, 2026

Copy link
Copy Markdown
Member

This looks like a substantial Windows-porting effort. How do we plan to test and maintain the Windows build? Do we have access to a Windows machine?

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.

3 participants