# LTO is disabled deliberately. MRtrix3 links with its own command line # ('OBJECTS LINKFLAGS -o EXECUTABLE', configure:336) which never carries # -flto, so the LTO in %%{optflags} buys nothing at link time and only costs # a second code-generation pass per object via -ffat-lto-objects. %global _lto_cflags %{nil} # Cap build concurrency by MEMORY, not by core count. MRtrix3's ./build # defaults to SC_NPROCESSORS_ONLN (build:1441-1444) with no memory awareness, # and at the -O3 a release build actually uses, single Eigen translation units # are enormous. Measured, one at a time, g++ 16.1.1, x86_64: # # cmd/mrregister.cpp 7,381,368 KB 142 s # src/registration/transform/affine.cpp 3,038,284 KB 30 s # core/math/average_space.cpp 2,949,976 KB 39 s # # So one job can want 7.2 GB. Sixteen in parallel is not survivable on any # builder we have, and four is not survivable either on a machine with other # work on it -- both of those were observed, not predicted. The budget below # is set from the measured maximum, not from the file an OOM happened to name. # %%_smp_tasksize_proc is MB of RAM per job, so %%{_smp_build_ncpus} scales the # job count with the builder's memory: 2 jobs on a 16 GB builder. %global _smp_tasksize_proc 8192 %global install_dir %{_libdir}/%{name} Name: mrtrix3 Version: 3.0.8 Release: 8%{?dist} Summary: Advanced Diffusion MRI Processing and Visualisation License: MPL-2.0 URL: https://www.mrtrix.org/ Source0: https://github.com/MRtrix3/%{name}/archive/refs/tags/%{version}.tar.gz#/%{name}-%{version}.tar.gz # Bundled Eigen 3.4.0 — system eigen3 5.0.1 on F44+ renamed the version macros # (EIGEN_WORLD_VERSION → EIGEN_VERSION_MAJOR, etc.) which breaks mrtrix3's # configure test compile. Bundling lets us pin to a 3.x API. Source1: https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz Source2: mrview.metainfo.xml Provides: bundled(eigen3) = 3.4.0 BuildRequires: gcc-c++ BuildRequires: git BuildRequires: python3 BuildRequires: python3-devel BuildRequires: eigen3-devel BuildRequires: zlib-devel BuildRequires: fftw-devel BuildRequires: libtiff-devel BuildRequires: libpng-devel # Qt5 Dependencies BuildRequires: qt5-qtbase-devel BuildRequires: qt5-qtsvg-devel BuildRequires: mesa-libGL-devel BuildRequires: mesa-libGLU-devel # desktop integration: validate the .desktop we install BuildRequires: desktop-file-utils BuildRequires: /usr/bin/appstream-util Requires: python3 Requires: python3-numpy Requires: qt5-qtbase Requires: qt5-qtsvg Requires: mesa-libGL # mrview.desktop declares application/x-nifti and application/x-mgh as # handled types. Those are defined by neuro-mime-types; without it the # two declarations are inert and .nii never reaches mrview. Weak, not # hard: mrview is perfectly usable on its own formats alone. Recommends: neuro-mime-types Requires: hicolor-icon-theme %description MRtrix3 provides a set of tools to perform various types of diffusion MRI analyses, from various forms of tractography through to next-generation group-level analyses. %prep %autosetup # Extract bundled Eigen 3.4.0 alongside the source tree tar xf %{SOURCE1} %build # 1. Fix build scripts to use python3 (Required for Mock/Fedora) # MRtrix3 defaults to 'python', which doesn't exist in clean Fedora chroots. sed -i 's|#!/usr/bin/env python|#!/usr/bin/python3|' configure build # 2. Compiler flags. MRtrix3's configure reads CFLAGS and NOTHING ELSE: it # builds the C++ compile line as "-c CFLAGS SRC -o OBJECT" (configure:333) # and appends $CFLAGS to it (configure:789). An exported CXXFLAGS is read by # no part of configure or build, so up to and including 3.0.8-4 the # %%{optflags} this spec set had never once reached the compiler. export CFLAGS="%{optflags}" # 3. Linker Flags (Map Fedora's LDFLAGS to MRtrix's LINKFLAGS) export LDFLAGS="%{?__global_ldflags}" export LINKFLAGS="$LDFLAGS" # 4. Architecture. configure appends -march=$ARCH whenever ARCH is set # (configure:778-782), and upstream documents 'native' as the value to use. # A -march=native binary is tuned for whichever builder happened to pick the # job up, not for the machines that install the RPM, so it must never be set # here. The baseline -march comes from %%{optflags}. unset ARCH # 4b. Parallelism. ./build reads NUMBER_OF_PROCESSORS and otherwise takes # every core on the builder; see the %%_smp_tasksize_proc note above. export NUMBER_OF_PROCESSORS=%{_smp_build_ncpus} # 5. Qt5 Paths export QMAKE=/usr/bin/qmake-qt5 export MOC=/usr/bin/moc-qt5 export RCC=/usr/bin/rcc-qt5 # Force configure to use bundled Eigen 3.4.0 (avoid system Eigen 5) export EIGEN_CFLAGS="-isystem $PWD/eigen-3.4.0" # 6. Configure (now using python3). NOT -debug: that sets optimlevel = 0 # (configure:205-207) and appends -O0 after $CFLAGS (configure:1434), so it # silently overrode the -O2 in %%{optflags} and, with it, _FORTIFY_SOURCE, # which is a no-op at -O0. Every mrtrix3 we have ever published says # "debug version with nooptim" in its own --version banner. ./configure # 7. Build (now using python3) ./build %install mkdir -p %{buildroot}%{install_dir} mkdir -p %{buildroot}%{_bindir} # Copy artifacts to private dir cp -a bin %{buildroot}%{install_dir}/ cp -a lib %{buildroot}%{install_dir}/ cp -a share %{buildroot}%{install_dir}/ # Symlink binaries to /usr/bin for b in %{buildroot}%{install_dir}/bin/*; do binary_name=$(basename "$b") # Only symlink if it's not the python binary itself if [ "$binary_name" != "python" ]; then ln -s %{install_dir}/bin/"$binary_name" %{buildroot}%{_bindir}/"$binary_name" fi done # --- SHEBANG FIX --- # Robustly rewrite ALL python shebangs to #!/usr/bin/python3 # We loop through every file in bin/, check if it's a script calling python, # and forcefully overwrite the first line. for f in %{buildroot}%{install_dir}/bin/*; do if [ -f "$f" ]; then # Check if the first line contains "python" if head -n 1 "$f" | grep -q "python"; then echo "Fixing shebang in $f" # Replace the entire first line with #!/usr/bin/python3 sed -i '1s|^#!.*|#!/usr/bin/python3|' "$f" fi fi done # --- DESKTOP INTEGRATION --- # Upstream ships all of this and we have never installed any of it, so mrview # and shview have had no menu entry, no icon and no file associations since # 3.0.8-1. Upstream's own install_mime_types.sh is a per-user xdg-* installer # (it rewrites Exec= to an absolute path in the source tree), so it is no use # to a package; the system install is done here instead. # # Two corrections to mrview.desktop on the way through, both --set-key: # its first key is "Value=1.0" where the spec says Version, and its # Categories names THREE main categories (Science;Development;Education), so # mrview would appear three times in the menu -- including under Development, # where an MRI viewer does not belong. desktop-file-validate emitted exactly # that duplicate-main-category hint before Categories was set here. # # The "#!/usr/bin/env xdg-open" shebang upstream puts at the top is left # alone: desktop-file-install does NOT strip it (checked, rather than # assumed), and it is a valid comment line, so validation passes with it. # # MimeType= is rewritten, not left alone. Declaring mrview as a HANDLER for # NIfTI is correct -- it opens them -- and we still decline to DEFINE those # types here; that is what neuro-mime-types answers. But upstream's list # names four types that do not exist under those names anywhere: # # application/x-nifti-gz .nii.gz is a glob of application/x-nifti, # not a separate type # application/x-image-mgh the type is application/x-mgh # application/x-image-mgz .mgz is a glob of application/x-mgh # application/x-image-analyze deliberately not defined -- Analyze's *.img # is the single most generic extension there is # # A declaration for an undefined type is inert: it costs nothing and does # nothing, so these four were silently buying us no NIfTI support at all # while reading as though they did. ci/check-mime-consistency.py now fails # the build on a declaration nothing we ship defines. # # x-mrtrix-tracks is added: mrview does open .tck, and the type is ours. desktop-file-install \ --dir=%{buildroot}%{_datadir}/applications \ --set-key=Version --set-value=1.0 \ --remove-key=Value \ --set-key=Keywords --set-value="MRI;diffusion;tractography;DWI;neuroimaging;" \ --set-key=Categories --set-value="Science;MedicalSoftware;" \ --set-key=MimeType --set-value="application/x-mrtrix;application/x-mrtrix-gz;application/x-mrtrix-tracks;application/x-nifti;application/x-mgh;" \ mrview.desktop for s in 16 32 48 64 128; do install -Dpm0644 icons/desktop/${s}x${s}/mrtrix.png \ %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps/application-x-mrtrix.png done # MIME: ship ONLY the formats that are MRtrix's own. Upstream's # mrtrix-mime.xml also claims application/x-nifti for *.nii and *.nii.gz, # *.mgh/*.mgz, and -- worst -- application/x-image-analyze for the entirely # generic *.img. Installing that system-wide would make mrview the owner of # NIfTI for every user on the machine, ahead of fsleyes, invesalius, mricrogl # and 3dslicer, and would collide with disk images on *.img. Those types want # defining once, for all of them, not eight times by whichever package was # installed last; see docs/gui-wayland-matrix.md. cat > mrtrix3-mime.xml <<'XML' MRtrix image MRtrix image (compressed) MRtrix streamlines XML install -Dpm0644 mrtrix3-mime.xml \ %{buildroot}%{_datadir}/mime/packages/mrtrix3.xml # AppStream metadata. A .desktop file makes an application launchable; a # metainfo file makes it DISCOVERABLE -- GNOME Software and KDE Discover list # only applications that ship one. Validation runs here rather than in # %check so a malformed file fails the build instead of shipping and being # silently ignored, which is how Ankur Sinha does it in Fedora's # python-fsleyes. install -Dpm 0644 %{SOURCE2} %{buildroot}%{_metainfodir}/mrview.metainfo.xml appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/mrview.metainfo.xml %check desktop-file-validate %{buildroot}%{_datadir}/applications/mrview.desktop test -f %{buildroot}%{_metainfodir}/mrview.metainfo.xml %files %license LICENCE.txt %doc README.md %{install_dir}/ %{_bindir}/* %{_datadir}/applications/mrview.desktop %{_datadir}/icons/hicolor/*/apps/application-x-mrtrix.png %{_datadir}/mime/packages/mrtrix3.xml %{_metainfodir}/mrview.metainfo.xml %changelog * Sun Oct 04 2026 Morgan Hough - 3.0.8-8 - Rewrite mrview.desktop's MimeType=. Four of the seven types upstream lists do not exist under those names anywhere: application/x-nifti-gz (.nii.gz is a glob of application/x-nifti, not a type), application/x-image-mgh (ours is application/x-mgh), application/x-image-mgz (a glob of x-mgh), and application/x-image-analyze, which we deliberately decline to define. A declaration for an undefined type is INERT -- it costs nothing and does nothing -- so the line read as though mrview handled NIfTI while in fact it handled none of it. Added application/x-mrtrix-tracks, which mrview does open and which is our own type. - Drop the two duplicate definitions: neuro-mime-types also defined application/x-mrtrix and application/x-mrtrix-tracks, and its *.mif.gz glob (weight 60) outranked this package's own application/x-mrtrix-gz (weight 50). With both packages installed, .mif.gz resolved to a type mrview.desktop does not declare and stopped opening. Fixed on the neuro-mime-types side; mrtrix3 remains the sole owner of its formats. - Recommends: neuro-mime-types, which defines the two generic types the desktop entry now declares. - ci/check-mime-consistency.py fails on any of the three: a type defined twice, a glob two types claim, a declaration nothing defines. * Thu Oct 01 2026 Morgan Hough - 3.0.8-7 - Fix -6, which failed in %%check after 67 minutes of build time. The metainfo path had been inserted into %%check, where the shell tried to EXECUTE it, instead of into %%files, where it belongs. Same anchor mistake as the four specs repaired in 086b655; mrtrix3 survived that pass because it was judged clean from a grep of line numbers rather than from reading the sections. - %%check now asserts the file exists instead of naming it, and %%files ships it. ci/check-static-qa.sh gained a rule for this shape. * Tue Sep 29 2026 Morgan Hough - 3.0.8-6 - Ship AppStream metadata (mrview.metainfo.xml). A desktop entry makes an application launchable; a metainfo file makes it DISCOVERABLE, because GNOME Software and KDE Discover list only applications that ship one. Twenty of the twenty-six applications in this repo had a desktop entry and no metainfo, so they were invisible in the software centre even once installed. Validated at build time with appstream-util validate-relax --nonet, in %install rather than %check, so a malformed file fails the build. - Added Requires: hicolor-icon-theme, which the icons need. * Mon Sep 28 2026 Morgan Hough - 3.0.8-5 - Build as an optimised release. Dropped ./configure -debug, which set optimlevel = 0 and appended -O0 after $CFLAGS, so every mrtrix3 we have published is an unoptimised debug build -- of a package whose main job is hours-long tractography. Confirmed in the shipped binary's own banner: "64 bit debug version with nooptim". - Pass %%{optflags} through CFLAGS, not CXXFLAGS. configure reads CFLAGS and nothing else (compile line "-c CFLAGS SRC -o OBJECT", configure:333/789), so the CXXFLAGS this spec exported was inert and Fedora's flags had never reached the compiler. Corroborated in mrtrix3-3.0.8-3.fc44.x86_64: zero __*_chk references, i.e. no _FORTIFY_SOURCE, which -O0 disables anyway. - Dropped ARCH=native. It makes configure append -march=native, which targets whichever COPR builder took the job rather than the machines that install the package. The two defects had to be fixed together: removing -debug without this would have shipped builder-specific ISA at full optimisation. - Not re-adding the -std=gnu++17 -fpermissive that rode along in the inert CXXFLAGS. They have never been in effect and the build does not need them; upstream's own -std=c++11 (configure:334) is what has always been used. - Disabled LTO (%%global _lto_cflags %%{nil}): mrtrix3's link line never carries -flto, so -ffat-lto-objects only pays for a second codegen pass. - Enabled debuginfo generation, previously off via %%define debug_package %%{nil}; the binaries were being stripped and the debug info discarded. - Capped build concurrency by memory (%%global _smp_tasksize_proc 8192 + NUMBER_OF_PROCESSORS=%%{_smp_build_ncpus}). Not cosmetic: once -O3 is really in effect, cmd/mrregister.cpp alone peaks at 7.2 GB RSS (142 s), with affine.cpp and average_space.cpp at 2.9-3.0 GB. ./build's own default of one job per core OOM-killed cc1plus twice -- at 16 jobs and again at 4 -- and the budget here is set from the measured maximum rather than from whichever file the OOM message happened to name. The -O0 builds never showed any of this because they never optimised. - Install the desktop integration upstream has always shipped and this spec has never used: mrview.desktop, an app icon at five sizes, and MIME types. mrview and shview have had no menu entry, no icon and no file association since 3.0.8-1. The .desktop needed two fixes on the way through (a shebang line, and "Value=1.0" where the spec says Version); desktop-file-validate now runs in %%check. - Shipping only MRtrix's OWN mime types (.mif/.mih/.mif.gz/.tck), not upstream's full mrtrix-mime.xml: that file also claims application/x-nifti for *.nii/*.nii.gz and Analyze for the generic *.img, which would make mrview the system-wide owner of NIfTI ahead of fsleyes, invesalius, mricrogl and 3dslicer, and collide with disk images. - tests/mrtrix3.bats gates this: the BUILD group reads mrinfo --version and fails on "debug version"/"nooptim", with a second test asserting the banner still has the shape the first one greps. * Mon Sep 28 2026 Morgan Hough - 3.0.8-4 - Release bump only, no content change. f44-x86_64 has been serving 3.0.8-3 from build 10426601 (2026-05-05) -- a build that PREDATES the -2 spec committed on 2026-05-24, but outranks it, because rpm orders -3 above -2. So the chroot that looked "ahead" was pinned to the older package and every other chroot correctly served the newer -2. Skipping to -4 restores the intended content everywhere without reusing -3, which is already published with different bytes. - Not an aarch64 gap despite reading as one. The measurement said "ARM behind on f44" and the cause was a release regression on x86. * Sun May 24 2026 Morgan Hough - 3.0.8-2 - Bundle Eigen 3.4.0: F44+ system eigen3 5.0.1 renamed the version macros (EIGEN_WORLD_VERSION → EIGEN_VERSION_MAJOR) which breaks mrtrix3's configure test-compile of the Eigen3 detection probe. Pinning to a 3.x API via $PWD/eigen-3.4.0 + EIGEN_CFLAGS sidesteps the Eigen-5 incompatibility. * Sun Jan 04 2026 Morgan Hough - 3.0.8-1 - Initial package for MRtrix3 version 3.0.8