Name: quit Version: 3.4 Release: 6%{?dist} Summary: Quantitative Imaging Tools for MRI data processing License: MPL-2.0 URL: https://github.com/spinicist/QUIT Source0: %{url}/archive/v%{version}/QUIT-%{version}.tar.gz # Header-only argument parser library (not packaged in Fedora) Source1: https://github.com/Taywee/args/archive/refs/tags/6.4.8.tar.gz#/args-6.4.8.tar.gz # CMake find module for bundled args library Source2: Findargs.cmake # fmt v9 is bundled because QUIT relies on implicit ostream formatting removed in fmt v11 Source3: https://github.com/fmtlib/fmt/archive/refs/tags/9.1.0.tar.gz#/fmt-9.1.0.tar.gz # Eigen 3.4.0 is bundled solely for its unsupported/ modules (MatrixFunctions, # Splines, MPRealSupport). ITK's bundled itkeigen (3.4.90) ships no unsupported/ # tree, and the system Eigen (5.0.x on rawhide) is ABI-incompatible with the # itkeigen that ITK's public headers force in. See the %%build comment. Source4: https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz BuildRequires: cmake >= 3.12 BuildRequires: gcc-c++ BuildRequires: make BuildRequires: InsightToolkit5-devel >= 5.3.0 BuildRequires: eigen3-devel BuildRequires: ceres-solver-devel BuildRequires: suitesparse-devel BuildRequires: blas-devel BuildRequires: lapack-devel BuildRequires: json-devel Requires: InsightToolkit5%{?_isa} Provides: bundled(fmt) = 9.1.0 Provides: bundled(args) = 6.4.8 Provides: bundled(eigen3) = 3.4.0 Provides: bundled(NumericalIntegration) %description QUIT (QUantitative Imaging Tools) is a collection of programs for processing quantitative MRI data, including DESPOT, relaxometry, magnetization transfer, perfusion, susceptibility mapping, and more. All tools are accessed via the single 'qi' command with subcommands, similar to git or bart. QUIT processes NIfTI format neuroimaging files and accepts sequence parameters via JSON input. %prep %autosetup -n QUIT-%{version} # Install bundled args header tar xf %{SOURCE1} install -p -m 0644 args-6.4.8/args.hxx External/include/ # Install cmake find module for args install -p -m 0644 %{SOURCE2} cmake/Findargs.cmake # Bundle fmt 9.1.0 (QUIT relies on implicit ostream formatting removed in fmt v11) tar xf %{SOURCE3} mv fmt-9.1.0 External/fmt # Unpack bundled Eigen 3.4.0 (only its unsupported/ tree is used; see %%build) tar xf %{SOURCE4} # Drop the `qi tgv` subcommand. tgv-denoise.hpp is the package's only consumer # of Eigen's unsupported/CXX11/Tensor module, which is tightly coupled to its # matching Eigen Core. ITK's bundled itkeigen (3.4.90) ships no unsupported/ # tree, the system Eigen is 5.0.x, and Eigen 3.4.0's CXX11 meta collides with # itkeigen's Core (type_list &c. redefined) — so no available unsupported/Tensor # is compatible with the itkeigen that ITK's public headers force in. Removing # the tool keeps every other utility; only TGV denoising is unavailable. rm -f Source/Utils/qi_tgv.cpp Source/Utils/tgv-denoise.hpp sed -i '/ADD(tgv, utils,/d' Source/qi_main.cpp # Fix ambiguous format_to with Eigen expression templates in C++20 # Replace the custom formatter with a simple ostream-based one sed -i '/template /,/};/c\ template auto format(const QI::SSFPSequence \&s, FormatContext \&ctx) const {\ std::ostringstream oss;\ oss << "SSFP:\\n\\tTR: " << s.TR << "\\n\\tFA: " << (s.FA * 180. / M_PI).transpose() << "\\n\\tPhaseInc: " << (s.PhaseInc * 180. / M_PI).transpose();\ return fmt::format_to(ctx.out(), "{}", oss.str());\ }\ };' Source/Sequences/SSFPSequence.h sed -i '1i #include ' Source/Sequences/SSFPSequence.h %build # --- Single, consistent Eigen for the whole build ---------------------------- # QUIT includes Eigen directly (, ), while # ITK's *public* headers (e.g. itkSymmetricEigenAnalysis.h) unconditionally pull # ITK's bundled Eigen 3.4.90 from /usr/include/ITK-5.4/itkeigen via quoted, # relative includes that cannot be redirected. On current Fedora the system # Eigen is 5.0.x, so a single translation unit ends up combining ITK's 3.4.90 # Eigen/Core with the system Eigen's headers (identical include guards, very # different versions). The result is the "instantiating erroneous template" / # is_nothrow_move_constructible failures in itkeigen Quaternion.h. # # Eliminate the skew by making QUIT's own resolve to the *same* # itkeigen used by ITK, and supplying the missing unsupported/ tree from a # version-matched Eigen 3.4.0. A -I dir always outranks the system -isystem # /usr/include/eigen3, so this wins without having to scrub CMake's flags. # The unsupported/ headers reach Eigen/Core via "../../Eigen/Core", so the # Eigen symlink must sit beside unsupported/ in the same root. mkdir -p _eigen_unified ln -sf /usr/include/ITK-5.4/itkeigen/Eigen _eigen_unified/Eigen cp -a eigen-3.4.0/unsupported _eigen_unified/unsupported export CFLAGS="%{optflags} -std=gnu17" export CXXFLAGS="%{optflags} -I$PWD/_eigen_unified -Wno-template-body -include cstdint -fpermissive" # Build bundled fmt 9.1.0 first cmake -S External/fmt -B External/fmt/build \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=%{_builddir}/QUIT-%{version}/External/fmt/install \ -DFMT_DOC=OFF -DFMT_TEST=OFF %make_build -C External/fmt/build %make_build -C External/fmt/build install %cmake \ -DCMAKE_MODULE_PATH:PATH="%{_builddir}/QUIT-%{version}/cmake" \ -DExternal_Include_DIR:PATH="%{_builddir}/QUIT-%{version}/External/include" \ -DBUILD_PARMESAN:BOOL=OFF \ -Dfmt_DIR:PATH="%{_builddir}/QUIT-%{version}/External/fmt/install/lib64/cmake/fmt" %cmake_build %install %cmake_install %files %license LICENSE.txt %doc README.md CHANGELOG.md %{_bindir}/qi %changelog * Fri May 29 2026 Morgan Hough - 3.4-6 - Drop the `qi tgv` (TGV denoising) subcommand: its tgv-denoise.hpp is the only user of Eigen's unsupported/CXX11/Tensor, which has no version-compatible source given ITK forces in itkeigen 3.4.90 (no unsupported/) and system Eigen is 5.0.x. All other utilities are retained. * Fri May 29 2026 Morgan Hough - 3.4-5 - Fix the real cause of the itkeigen Quaternion.h build failure: QUIT was combining ITK's bundled Eigen 3.4.90 (forced in by ITK's public headers) with the system Eigen (now 5.0.x), two incompatible Eigens with identical include guards in one translation unit. Build a unified Eigen include root (Eigen symlinked to ITK's itkeigen, unsupported/ supplied by a bundled, version-matched Eigen 3.4.0) and prepend it with -I so it outranks the system eigen3. Drops the previous no-op shadow-patch of Quaternion.h (it sed'd a `typename` that never existed in the header). - Bundle Eigen 3.4.0 (Source4) for its unsupported/ modules; itkeigen ships none. * Sun May 24 2026 Morgan Hough - 3.4-4 - Shadow-patch ITK 5.4's bundled itkeigen/Eigen/src/Geometry/Quaternion.h: copy it into _itk_eigen_patch/ in %build, strip the invalid `typename std::is_nothrow_move_*::value` typename keyword, prepend the patched dir to -I so it wins over /usr/include/ITK-5.4/itkeigen/. Add -fpermissive belt-and-suspenders. GCC 16 now enforces what was always invalid C++ (typename used on a non-type ::value member). * Sat May 23 2026 Morgan Hough - 3.4-2 - Add missing Source2 Findargs.cmake (was referenced but never committed, blocking SRPM rebuild). Simple header-only find module providing args::args INTERFACE target. * Mon Mar 30 2026 Morgan Hough - 3.4-1 - Initial package for Fedora