8000 Build and publish an arm64 Linux package by fedorov · Pull Request #556 · QIICR/dcmqi · GitHub
[go: up one dir, main page]

Skip to content

Build and publish an arm64 Linux package - #556

Merged
fedorov merged 4 commits into
masterfrom
add-arm64-linux-windows-builds
Aug 11, 2026
Merged

fedorov merged 4 commits into
masterfrom
add-arm64-linux-windows-builds

Conversation

@fedorov
@fedorov fedorov commented Aug 11, 2026 •
Copy link
Copy Markdown
Member

Adds a build-linux-arm64 job so releases carry a dcmqi-<version>-linux-arm64.tar.gz. Requested in ImagingDataCommons/dcmqi-python-distributions#44 — 3D Slicer has Linux arm64 users who currently have to build from source because no wheel exists for their platform.

What this does

  • .github/workflows/cmake-linux.yml — new build-linux-arm64 job on the native ubuntu-24.04-arm runner, inside a quay.io/pypa/manylinux_2_28_aarch64 container so the binaries carry the same glibc floor as the x86_64 package. Mirrors the existing macOS job's cache/validate/configure/build/test/package/publish shape.
  • CMakeLists.txt — CPACK_SYSTEM_NAME gains an arm64 branch. The x86_64 names stay unqualified (linux, win64) so existing download URLs keep working.
  • finalize-latest.yml, RELEASE.md — documentation kept in step with the new asset.

Container paths

The job deliberately uses $GITHUB_WORKSPACE in shell steps and workspace-relative paths in action inputs, rather than the ${{ github.workspace }} expression the other jobs use. In a container: job the two disagree: the expression is evaluated on the host and yields /home/runner/work/..., while the repository is mounted inside the container at /__w/.... The first push here used the expression and failed with The source directory "/home/runner/work/dcmqi/dcmqi" does not appear to contain CMakeLists.txt — the mkdir -p steps had quietly created the empty host path. There is a comment on the job saying so.

Windows arm64 is not included

It was in the first version of this PR and had to come out. ITK's vendored GDCM does not compile for ARM64 with MSVC (failing job):

winbase.h(9858,23): error C2664: 'unsigned int gdcm::_InterlockedIncrement(volatile unsigned int *)':
  cannot convert argument 1 from 'volatile long *' to 'volatile unsigned int *'

plus ~11 more (_InterlockedDecrement, _InterlockedExchange, _InterlockedExchangeAdd, _InterlockedCompareExchange). Note the namespace. gdcmFilename.cxx includes <windows.h> at line 100, inside namespace gdcm (lines 20–187). On x64 the _Interlocked* functions are intrinsics and winbase.h declares nothing; on ARM64 it declares real inline wrappers, which then land in namespace gdcm and shadow the intrinsics with the wrong signature.

-DModule_ITKIOGDCM:BOOL=OFF does not help — dcmqi's sources never reference GDCM, but ITKReview (turned on explicitly in CMakeExternals/ITK.cmake) hard-DEPENDS on ITKIOGDCM, which PRIVATE_DEPENDS on ITKGDCM.

The fix is one line in the right place, but it belongs upstream in GDCM or the Slicer/ITK fork pinned here, not in a PATCH_COMMAND against third-party source in our superbuild. Windows arm64 follows once ITK carries it. CPACK_SYSTEM_NAME already handles the naming, so only the build job will be needed — it is retained deliberately, because an ARM64 target is 64-bit and a local build would otherwise emit a package called win64 full of arm64 binaries.

Relationship to #555

This branch originally carried part of #555's cmake-macos.yml / cmake-win.yml changes but not its if: fix, which left both files with a comment promising the cache save was gated on build success while the condition was still always(). Those files are now reverted to master here; #555 has all of it, correctly. The two PRs no longer overlap.

Testing

build-linux-arm64 passes end to end, 15m46s with a cold cache. All other jobs unaffected.

🤖 Generated with Claude Code

dcmqi released binaries for Linux and Windows on x86_64 only, so downstream
consumers (notably the dcmqi PyPI wheels) had no arm64 package to repackage
even though macOS has shipped both architectures since v1.5.1.

Linux arm64 is built natively on ubuntu-24.04-arm inside the official
manylinux_2_28_aarch64 image rather than through docker/Makefile: the dockcross
images driving the x86_64 build are amd64-only cross toolchains, so they can
neither run on an arm64 host nor execute the binaries they produce. The
container also holds the glibc floor of the shipped binaries at 2.28, well
below the runner's own Ubuntu 24.04; building bare on the runner would raise it
to 2.39 and make the package unusable on most current distributions.

Windows gains an arch matrix mirroring the existing macOS one, building natively
on windows-11-arm with the Visual Studio ARM64 toolset.

The x86_64 asset names (dcmqi-X-linux.tar.gz, dcmqi-X-win64.zip) are
deliberately left unqualified so existing download URLs keep working; only the
new architectures carry a suffix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fedorov
fedorov requested a lite review from Copilot August 11, 2026 14:25
Comment thread .github/workflows/cmake-linux.yml Fixed
Comment thread .github/workflows/cmake-linux.yml Fixed
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 ARM64 build/release support for Linux and Windows to align release assets across platforms, while preserving the historical (unqualified) x86_64 asset names for Linux and Windows to avoid breaking existing download URLs.

Changes:

  • Extend CPACK_SYSTEM_NAME to emit linux-arm64 and win-arm64 while keeping linux and win64 for x86_64.
  • Add a native manylinux-based build-linux-arm64 job to produce Linux ARM64 release assets.
  • Convert the Windows workflow into an x64/arm64 matrix and update release documentation/comments accordingly.

Reviewed changes

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

Show a summary per file
File Description
RELEASE.md Documents the expanded set of six release assets (platform × architecture) and the naming constraints.
CMakeLists.txt Updates packaging name logic to distinguish ARM64 for Linux/Windows without changing existing x86_64 names.
.github/workflows/finalize-latest.yml Updates stale comment to reflect six parallel build jobs.
.github/workflows/cmake-win.yml Adds an arch matrix to build/publish both Windows x64 and ARM64 artifacts.
.github/workflows/cmake-linux.yml Adds a native manylinux container job to build/test/package/publish Linux ARM64 artifacts.

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

Comment thread .github/workflows/cmake-linux.yml Outdated
Comment on lines +339 to +340
gh_version=$(curl -sSL https://api.github.com/repos/cli/cli/releases/latest \
| sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p' | head -n 1)
The job failed at configure with "source directory does not appear to contain
CMakeLists.txt". In a container job the `github.workspace` expression and
`$GITHUB_WORKSPACE` disagree: the expression is evaluated on the host and yields
/home/runner/work/..., while the repository is mounted inside the container at
/__w/.... The job was copied from the macOS build, which uses the expression
throughout, so every path pointed at an empty host directory -- the mkdir steps
quietly created one, and cmake then found nothing there.

Shell steps now use $GITHUB_WORKSPACE, and the cache and artifact paths are
workspace-relative, which is container-agnostic.

Also address the review of the publish step: pin the gh CLI version instead of
discovering it through an unauthenticated API call subject to the anonymous rate
limit, mirroring the pinned ninja download in the macOS build, and enforce https
on the transfer and on any redirect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Windows arm64 job cannot build. ITK's vendored GDCM fails to compile for
ARM64 with MSVC: gdcmFilename.cxx includes <windows.h> from inside
`namespace gdcm`, and on ARM64 winbase.h declares real inline _Interlocked*
wrappers where x64 has only intrinsics. Those declarations land in the
namespace, so later unqualified calls resolve to gdcm::_InterlockedIncrement
and friends with the wrong signature -- a dozen C2664/C2665 errors.

Disabling the module is not an option: dcmqi's own sources never touch GDCM,
but ITKReview (enabled explicitly in CMakeExternals/ITK.cmake) hard-DEPENDS on
ITKIOGDCM, which PRIVATE_DEPENDS on ITKGDCM. The fix belongs upstream in GDCM
or the Slicer/ITK fork pinned here, so Windows arm64 waits for that rather than
patching third-party source out of the superbuild.

Linux arm64 is unaffected and stays: it builds green in 15m46s uncached.

Also reverts this branch's cmake-macos.yml and cmake-win.yml changes. They
duplicated part of #555 without its `if:` fix, leaving each file with a comment
promising the save step is gated on build success while the condition was still
`always()`. #555 carries all of it correctly.

CMakeLists.txt keeps the win-arm64 CPACK_SYSTEM_NAME branch even though nothing
builds it: an ARM64 target is 64-bit, so a local build would otherwise emit a
package named "win64" containing arm64 binaries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fedorov fedorov changed the title feat: build and publish arm64 packages for Linux and Windows Build and publish an arm64 Linux package Aug 11, 2026
Both jobs declare their own permissions, and a job-level block replaces the
workflow-level one rather than merging with it, so this block never applied to
anything. cmake-macos.yml and cmake-win.yml already declare none, so removing
it also makes the three CI workflows consistent.

Clears the two githubactions:S8233 alerts SonarCloud raises on this file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

deployments: write
packages: write
# Permissions are declared per job. A job-level block replaces the workflow-level one
# rather than merging with it, so a workflow-level block here would have had no effect
packages: write
# Permissions are declared per job. A job-level block replaces the workflow-level one
# rather than merging with it, so a workflow-level block here would have had no effect
# on either job below -- and the macOS and Windows workflows already declare none.
@fedorov
fedorov merged commit e1dd8d4 into master Aug 11, 2026
9 checks passed
@fedorov
fedorov deleted the add-arm64-linux-windows-builds branch August 11, 2026 16:40
fedorov added a commit that referenced this pull request Aug 11, 2026
Author the release notes ahead of tagging (per RELEASE.md). The release
exists to ship the first arm64 Linux package (#556); the only other change
since v1.5.6 is the CI cache-save fix (#550, #555). No library changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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

0