COMP: Build and test on Windows - #82
Merged
Merged
Conversation
hjmjohnson
force-pushed
the
ci/windows
branch
from
September 22, 2026 14:31
f2689a0 to
c25de3e
Compare
hjmjohnson
marked this pull request as ready for review
September 22, 2026 14:33
hjmjohnson
force-pushed
the
ci/windows
branch
from
September 22, 2026 14:37
c25de3e to
79a5a40
Compare
Twelve source files carry WIN32 or _MSC_VER guards and no workflow has ever compiled them, so a change that breaks the Windows path is invisible here and surfaces only when a consumer reports it. Static and shared, because the ZNZ_API and NIFTI_API decorations differ between them and only the shared build exercises the dllexport path. zlib and expat come from vcpkg, which the runner image already carries. VCPKG_INSTALLATION_ROOT is set by the runner image rather than by the workflow, so the toolchain path is read in PowerShell and checked before cmake runs, which reports a missing toolchain as itself rather than as a CMake error several lines removed from the cause.
afni_xml_io.h decorates its declarations with CIF_API and afni_xml.h decorated none of its own, so a Windows shared build produced a DLL missing every axml_ entry point and both cifti tools failed to link against the library they are built with. The macro definition moves to afni_xml.h, which afni_xml_io.h includes at its top, so one definition now serves both headers rather than each carrying its own. Nothing changes where the attribute expands to default visibility: the exported set of the shared build is byte-identical. Found by the Windows job added in the preceding commit.
hjmjohnson
force-pushed
the
ci/windows
branch
from
September 22, 2026 14:48
79a5a40 to
c377dbc
Compare
Collaborator
|
@hjmjohnson Why are you merging PRs with no one reviewing them? |
This was referenced Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Windows leg, static and shared, so the
WIN32and_MSC_VERpaths are compiled by CI for the first time — and fixes the one defect that exposed.Two commits, one file each, separable:
a007745.github/workflows/cmake-multi-platform.yml79a5a40cifti/afni_xml.hWhat the leg found: the cifti DLL was missing half its entry points
The cifti library is built from two sources with two public headers.
afni_xml_io.hdecorates its declarations withCIF_API;afni_xml.hdecorated none of its own. On Windows that produced a DLL with everyaxml_entry point absent, and the library's own tools could not link against it:afni_xml.hwas the only undecorated public header in the project. For comparison, after the fix:nifti2_io.h134 decorated declarations,nifti1_io.h103,nifticdf.h89,fslio.h70,afni_xml.h21,afni_xml_io.h10,znzlib.h13.The
CIF_APIdefinition moves toafni_xml.h, whichafni_xml_io.hincludes at its top, so one definition serves both headers instead of each carrying its own copy. One macro per library is this project's existing convention —ZNZ_API,NIO_API,NCDF_API,FSL_API,NI2_API— and both these headers belong to the same library, so they must share one.No ABI effect off Windows.
CIF_APIexpands to__attribute__((visibility("default")))on ELF and Mach-O, and this project sets no-fvisibility=hiddenpolicy, so the attribute is a no-op there. Verified: the exported symbol set of the shared build is byte-identical before and after, and theexported symbol baselinejob agrees.Why a Windows leg at all
Twelve source files carry
WIN32or_MSC_VERguards and no workflow compiled them, so a change breaking the Windows path was invisible here and would surface only when a consumer reported it. This library is vendored into ITK, AFNI, FSL, dcm2niix and Slicer, several of which ship on Windows.The immediate trigger was concrete. A review of #41 found that its new test target guards on
if(NIFTI_BUILD_TESTING AND ZLIB_FOUND)while the function it tests is compiled under#if !defined (WIN32), so the target would configure and then fail to link. That was an inference from reading guards; with this leg it becomes a red check. Adding the leg first also keeps the two findings attributable — landing #41 first would have mixed its guard omission in with this DLL defect.Build choices
Both linkages. The
ZNZ_APIandNIFTI_APIdecorations differ between them and only the shared build exercisesdllexport— which is precisely how the cifti defect surfaced. Static alone would have passed and found nothing.zlib and expat from vcpkg, which the runner image already carries.
find_package(ZLIB REQUIRED)atCMakeLists.txt:109leaves no zlib-free configuration.The toolchain path is resolved in PowerShell, not by a GitHub expression.
VCPKG_INSTALLATION_ROOTis set by the runner image rather than by the workflow, so theenvexpression context expands it to nothing. The step now reads it in the shell that knows it and fails with the path it tried, rather than as a CMake error several frames removed from the cause.--no-tests=ignoreon the ctest step, matching theminimaljob.Scope of the evidence
A successful link proves the symbols the in-tree tools actually use are exported — no more. A function declared in a header but called by no tool could still be undecorated and silently missing from a DLL without the build noticing. That is exactly the blind spot that let this defect survive: it surfaced only because the cifti tools happened to call the missing symbols.
Closing that gap properly would mean comparing each DLL's export table against its header's declared set — a Windows analogue of the existing
exported symbol baselinejob. Worth a follow-up rather than expanding this PR.