Skip to content

Make the installed libminc package usable outside the superbuild - #150

Merged
vfonov merged 3 commits into
BIC-MNI:develop-1.9.18from
gdevenyi:ci-modernize
Jul 23, 2026
Merged

vfonov merged 3 commits into
BIC-MNI:develop-1.9.18from
gdevenyi:ci-modernize

Conversation

@gdevenyi

@gdevenyi gdevenyi commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

libminc's installed CMake package describes its dependencies the way they look inside the minc-toolkit-v2 superbuild. As a result, make install-ing libminc and building a consumer (bicpl, minc-tools, mni_autoreg, …) against it does not work today. The superbuild hides every defect below — it builds its own HDF5, stages it into libminc's own install prefix, and compiles consumers from the source tree.

Each fix corresponds to a build that fails on current develop-1.9.18 and passes with this branch.

No CI changes here — the workflow that found all of this is split out into a separate PR that stacks on this one (see Context).

1. BuildNIFTI: install bundled nifti_clib into CMAKE_INSTALL_LIBDIR

nifti_clib defaults its install library dir to plain lib, but BuildNIFTI.cmake expects the staged libraries under ${CMAKE_INSTALL_LIBDIR} — lib64 on RPM distros. So LIBMINC_USE_NIFTI=ON on Fedora fails:

No rule to make target 'external//usr/local/lib64/libniftiio.a', needed by 'testdir/icv'

One line: pass NIFTI_INSTALL_LIBRARY_DIR=${CMAKE_INSTALL_LIBDIR} to the external project.

2. Installed config: use LIBMINC_INSTALL_LIB_DIR, not hard-coded lib/

The generated config pointed LIBMINC_USE_FILE and LIBMINC_LIBRARY_DIRS at <prefix>/lib/..., while GNUInstallDirs had installed those files to <prefix>/lib64. Consumers on Fedora:

INCLUDE could not find requested file: <prefix>/lib/cmake/UseLIBMINC.cmake

3. Installed config: make the exported package usable standalone

Four related defects, all invisible inside the superbuild:

a. Dependency libraries were exported as bare file names. Consumers link those names with link_directories(${LIBMINC_LIBRARY_DIRS}), which only covers libminc's own prefix. Correct for a superbuild-staged HDF5 — and what keeps such an install relocatable — but a system HDF5 lives elsewhere:

ld: library 'hdf5' not found                              # macOS / Homebrew
undefined reference to symbol 'H5Pset_chunk@@HDF5_SERIAL_1.8.7'
/lib/x86_64-linux-gnu/libhdf5_serial.so.103: error adding symbols: DSO missing from command line   # Debian/Ubuntu

(Debian ships HDF5 as libhdf5_serial under /usr/lib/*/hdf5/serial.)

The rule now applied: a dependency outside the install prefix is exported as an absolute path; one staged inside the prefix keeps its plain name. This leaves the superbuild's relocatable install untouched while making system dependencies resolvable. The mapping handles multi-entry lists (module-mode FindHDF5 reports libhdf5.so;libsz.so;libz.so;libdl.a;libm.so) and entries that are already bare -l names (h5cc/Homebrew), whose directories are added to the exported LIBMINC_LIBRARY_DIRS.

b. Dependency include dirs were not exported. minc.h includes <hdf5.h> and volume_io needs netcdf.h with MINC1 support, but LIBMINC_INCLUDE_DIRS held only <prefix>/include:

/opt/bic-mni/include/minc.h:170:10: fatal error: hdf5.h: No such file or directory

Same in/out-of-prefix rule as (a).

c. internal_volume_io.h was never installed. It is absent from every header list, yet consumers (bicpl, conglomerate) #include <internal_volume_io.h> directly — inside the superbuild it resolves from the source tree:

bicpl/Testing/test_obj_io.c:1:11: fatal error: internal_volume_io.h: No such file or directory

d. UseLIBMINC.cmake injected NOTFOUND into the include path. It did include_directories(${HDF5_INCLUDE_DIR}) unconditionally; when the consumer has not resolved HDF5 itself (it no longer needs to, given (b)), the literal NOTFOUND fails the configure:

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
HDF5_INCLUDE_DIR (ADVANCED)

Now guarded on both HDF5_INCLUDE_DIR and NETCDF_INCLUDE_DIR.

Review notes

  • The load-bearing decision is in (3a): outside the prefix → absolute path, inside → bare name. Deliberately conservative, so the superbuild's relocatable install is unaffected. The alternative — always export absolute paths — is simpler but bakes build-machine paths into a redistributable install. Happy to switch if you prefer.
  • An earlier revision of (3a) tried to re-resolve HDF5 on the consumer side instead. A debug print in CI showed HDF5_FOUND=0 there — it dropped hdf5 entirely and was worse than the original bug. Discarded in favour of fixing this at the origin; noting it since it looks like the obvious approach.
  • No change to the imported-target path (LIBMINC::minc2); this only repairs the legacy variables existing consumers use.

Validation

These commits are the base of the CI PR (#151), where libminc's own matrix runs green on ubuntu 22.04/24.04, macOS 14/15 and fedora:44 across shared/static × MINC1 × NIFTI: https://github.com/gdevenyi/libminc/actions/runs/29535929762

Every tier-1 consumer also builds and tests against these fixes on ubuntu:24.04 + fedora:44 + macOS, all green:
EBTKS ·
bicpl ·
minc_gco ·
glim_image ·
mrisim ·
postf ·
xdisp ·
minc-tools ·
BEaST ·
mni_autoreg

(Those consumer runs temporarily build libminc from this branch; their own PRs point back at BIC-MNI once this merges.)

Context

Found while adding standalone build+test CI to the BIC-MNI submodule repos, mirroring the superbuild CI in minc-toolkit-v2. This PR is the keystone — 9 of the 10 tier-1 repos cannot build against an installed libminc without it.

🤖 Generated with Claude Code

https://claude.ai/code/session_011nEnygr1q87PepYiJobEGW

Copilot AI review requested due to automatic review settings July 16, 2026 18:09

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

Modernizes the GitHub Actions CI workflow to run on all branches/PRs and expands coverage with a Fedora container matrix, while also addressing two CI-discovered issues: NIFTI staging on lib64 distros and macOS leak-test max RSS unit differences.

Changes:

  • Update .github/workflows/cmake.yml to run on all branch pushes, add concurrency + least-privilege defaults, and add a Fedora 44 container job mirroring the existing option matrix.
  • Fix NIFTI external build staging on RPM/lib64 platforms by forcing nifti_clib’s install library directory to match CMAKE_INSTALL_LIBDIR.
  • Normalize ru_maxrss units on macOS in minc2-leak-test so leak thresholds behave consistently.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
.github/workflows/cmake.yml CI modernization (triggers/concurrency/permissions), matrix cleanup, and Fedora container job added.
cmake-modules/BuildNIFTI.cmake Align nifti_clib install libdir with CMAKE_INSTALL_LIBDIR for lib64 staging correctness.
testdir/minc2-leak-test.c Normalize macOS RSS units to KB to prevent leak-test false positives.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread testdir/minc2-leak-test.c
Comment on lines +26 to +29
* checks for maximum memory usage.
* ru_maxrss is in kilobytes on Linux but bytes on macOS/BSD.
* Normalize to kilobytes so the leak-detection threshold works
* on both platforms.
Comment thread .github/workflows/cmake.yml Outdated
Comment on lines +73 to +75
- name: Build
run: cmake --build build -j4

Comment thread .github/workflows/cmake.yml Outdated
Comment on lines +126 to +128
- name: Build
run: cmake --build build -j4

Comment thread .github/workflows/cmake.yml Outdated
Comment on lines +83 to +87
fedora:
name: fedora:44 ${{ matrix.build-params.WITH_MINC1 == 'ON' && 'MINC_1_2' || 'MINC_1' }} ${{ matrix.build-params.USE_NIFTI == 'ON' && 'NIFTI' || '' }} ${{ matrix.build-params.static == 'ON' && 'static' || 'shared' }}
runs-on: ubuntu-latest
container: 'fedora:44'
strategy:
Comment thread .github/workflows/cmake.yml Outdated
Comment on lines +103 to +105
- name: Allow git to read the workspace owned by the runner user
run: git config --global --add safe.directory '*'

@gdevenyi
gdevenyi changed the base branch from master to develop-1.9.18 July 16, 2026 18:20
@gdevenyi
gdevenyi force-pushed the ci-modernize branch 4 times, most recently from 77fdf2c to b26b35b Compare July 16, 2026 21:24
@gdevenyi gdevenyi changed the title CI: modernize workflow (all branches + Fedora), fix NIFTI lib64 build, fix macOS leak-test CI: add branch/Fedora coverage, and make the installed libminc package usable outside the superbuild Jul 16, 2026
@gdevenyi
gdevenyi requested a review from vfonov July 16, 2026 22:14
gdevenyi and others added 3 commits July 16, 2026 18:15
nifti_clib defaults NIFTI_INSTALL_LIBRARY_DIR to plain "lib", but
BuildNIFTI.cmake expects the staged static libraries under
${CMAKE_INSTALL_LIBDIR}, which is lib64 on RPM-based distros. On Fedora
the build then fails with:

  No rule to make target 'external//usr/local/lib64/libniftiio.a'

Pass NIFTI_INSTALL_LIBRARY_DIR=${CMAKE_INSTALL_LIBDIR} to the external
project so both sides agree.

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

The installed-tree LIBMINCConfig.cmake pointed LIBMINC_USE_FILE and
LIBMINC_LIBRARY_DIRS at <prefix>/lib/..., but with GNUInstallDirs the
files are installed under <prefix>/lib64 on RPM-based distros, so
consumers failed with:

  INCLUDE could not find requested file: <prefix>/lib/cmake/UseLIBMINC.cmake

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011nEnygr1q87PepYiJobEGW
Building any consumer (bicpl, minctools, mni_autoreg, ...) against an
installed libminc failed outside the minc-toolkit superbuild, because the
installed package config only described dependencies as they look from
inside that superbuild:

- The HDF5/NetCDF entries in LIBMINC_LIBRARIES were reduced to plain file
  names, and LIBMINC_LIBRARY_DIRS only covers libminc's own prefix. That
  is right for the superbuild, which stages its own HDF5 into that prefix
  and keeps the install relocatable, but a system HDF5 lives elsewhere, so
  consumers failed with "ld: library 'hdf5' not found" (macOS/Homebrew) or
  "undefined reference to H5Pset_chunk ... DSO missing from command line"
  (Debian, where HDF5 is libhdf5_serial under /usr/lib/*/hdf5/serial).
  Keep the absolute path for dependencies outside the install prefix and
  plain names for those staged with libminc.
- minc.h includes <hdf5.h> and volume_io needs netcdf.h with MINC1
  support, but LIBMINC_INCLUDE_DIRS held only <prefix>/include, so
  consumers failed with 'hdf5.h: No such file or directory'. Export the
  dependency include dirs when they are outside the prefix.
- internal_volume_io.h was never installed although consumers include it
  directly; inside the superbuild it resolves from the source tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011nEnygr1q87PepYiJobEGW
@gdevenyi gdevenyi changed the title CI: add branch/Fedora coverage, and make the installed libminc package usable outside the superbuild Make the installed libminc package usable outside the superbuild Jul 16, 2026
@vfonov
vfonov merged commit 282fbe5 into BIC-MNI:develop-1.9.18 Jul 23, 2026
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