Name: acvd Version: 4.0 Release: 6%{?dist} Summary: Fast simplification and remeshing of 3D surface meshes (VTK-based) # CeCILL-B is a permissive BSD-like French free-software license (Fedora-allowed). License: CECILL-B URL: https://github.com/valette/ACVD Source0: %{url}/archive/refs/tags/v%{version}/ACVD-%{version}.tar.gz Patch0: acvd-vtk97-addviewprop.patch BuildRequires: cmake BuildRequires: ninja-build BuildRequires: gcc-c++ BuildRequires: chrpath BuildRequires: vtk-devel # IOMINC component requested by ACVD's find_package(VTK) BuildRequires: libminc-devel # OpenMP (optional acceleration in the remeshing examples; harmless for the libs) BuildRequires: libomp-devel # VTK cmake config resolves all module deps at find_package time BuildRequires: hdf5-devel json-devel jsoncpp-devel utf8cpp-devel fmt-devel BuildRequires: freetype-devel pugixml-devel PEGTL-devel libglvnd-devel BuildRequires: libtheora-devel libogg-devel libjpeg-turbo-devel libpng-devel BuildRequires: libtiff-devel fontconfig-devel expat-devel lz4-devel xz-devel BuildRequires: zlib-devel sqlite-devel libxml2-devel netcdf-devel proj-devel BuildRequires: tbb-devel libharu-devel gl2ps-devel double-conversion-devel BuildRequires: gdal-devel libpq-devel libX11-devel libXt-devel libGL-devel BuildRequires: cli11-devel boost-devel # Pin the exact VTK ABI this package was built against. VTK freezes its soname at # libvtk*.so.1 across all of 9.x, so rpm cannot tell 9.5 from 9.6 from 9.7: a consumer # built against one installs cleanly against another and fails at LOAD with undefined # symbols. A >= floor does not help -- 9.7.0 satisfies >= 9.6.2 -- so this is an exact # match. %%vtk_abi comes from vtk-devel's macros.vtk, so it re-pins on every rebuild. # # The missing-macro check lives in %%build, deliberately, NOT at parse time. A # parse-time %%error cannot distinguish "COPR is generating the SRPM" from "this is a # real buildroot": rpkg srpm parses the spec with no buildroot and therefore no # vtk-devel, so a parse-time guard killed every SCM build of every guarded package # before any chroot existed (python-simpleitk 10980296 failed in 0 minutes with # "can't parse specfile"). Expanding to UNSET keeps the SRPM parse alive, and the # %%build test still fails loudly in a buildroot lacking vtk-devel, so no RPM carrying # the placeholder can ever be produced. Requires: vtk(abi) = %{?vtk_abi}%{!?vtk_abi:UNSET} %description ACVD provides fast, high-quality simplification and isotropic/anisotropic remeshing of 3D triangular surface meshes, based on Approximated Centroidal Voronoi Diagrams (Valette et al.). It is built on top of VTK and provides the vtkSurface and vtkVolumeProcessing shared libraries plus a header-only discrete remeshing module, used by statistical-shape-modeling pipelines (e.g. ShapeWorks) for surface correspondence preprocessing. %package devel Summary: Development files for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} Requires: vtk-devel %description devel Headers and CMake package configuration for developing against %{name} (ACVD: vtkSurface, vtkDiscreteRemeshing, vtkVolumeProcessing). %prep %autosetup -p1 -n ACVD-%{version} # Recode the sources to UTF-8. Common/vtkOFFWriter.h carries a single Latin-1 byte in a # comment (the accent in "multi-resolution"), and that header is INSTALLED, so it becomes # a problem for consumers rather than for us: harmless until something compiles with a # UTF-8 source charset, at which point a downstream build fails on a file it does not own. # We shipped it in 4.0-5 -- file(1) reports "C++ source, ISO-8859 text" and iconv rejects # it. # # Swept rather than patched by name: of 33 installed headers exactly one is affected # today, and fixing only the one we were told about leaves the next one to be found by # whoever it breaks. Reported by the neurodebian session, who hit it packaging ACVD for # Debian. _recoded=0 while read -r f; do iconv -f UTF-8 -t UTF-8 "$f" >/dev/null 2>&1 && continue iconv -f ISO-8859-1 -t UTF-8 "$f" > "$f.utf8" && mv -f "$f.utf8" "$f" echo "acvd: recoded $f from ISO-8859-1 to UTF-8" _recoded=$((_recoded+1)) done < <(find . -type f \( -name '*.h' -o -name '*.hxx' -o -name '*.cxx' -o -name '*.txx' \)) echo "acvd: recoded ${_recoded} file(s)" # Assert the tree is clean afterwards, so a future iconv failure cannot pass silently. while read -r f; do iconv -f UTF-8 -t UTF-8 "$f" >/dev/null 2>&1 || { echo "ERROR: $f is still not valid UTF-8 after recoding." >&2 exit 1 } done < <(find . -type f \( -name '*.h' -o -name '*.hxx' -o -name '*.cxx' -o -name '*.txx' \)) %build # vtk_abi comes from vtk-devel's macros.vtk. Absent means BuildRequires: vtk-devel is # missing, and the Requires above would ship as the vacuous "vtk(abi) = UNSET". test -n "%{?vtk_abi}" || { echo "ERROR: vtk_abi undefined - add 'BuildRequires: vtk-devel'" >&2; exit 1; } # ACVD's sources use unqualified cout/cin/cerr/endl with neither nor # `using namespace std` — they relied on transitive availability that newer VTK # headers / GCC 15 no longer provide. Force-include a small prelude that supplies # both, restoring the environment the code was written for. cat > _acvd_prelude.h <<'EOF' #include using namespace std; EOF export CXXFLAGS="%{optflags} -include $PWD/_acvd_prelude.h" # Library-only build: the bundled Examples produce many generically-named CLI # binaries (viewer, icp, sampleMesh, ...) that would collide in %{_bindir}; # downstreams (ShapeWorks) need only the libraries + headers + cmake config. # ACVD uses its own INSTALL_*_DIR vars (not CMAKE_INSTALL_LIBDIR), so set lib64. %cmake -GNinja \ -DBUILD_SHARED_LIBS:BOOL=ON \ -DBUILD_EXAMPLES:BOOL=OFF \ -DBUILD_DOCUMENTATION:BOOL=OFF \ -DINSTALL_LIB_DIR:PATH=%{_lib} \ -DINSTALL_INCLUDE_DIR:PATH=include \ -DINSTALL_CMAKE_DIR:PATH=%{_lib}/cmake/ACVD %cmake_build %install %cmake_install # Drop any build-tree RPATHs. find %{buildroot} -type f \( -name '*.so' -o -name '*.so.*' \) \ -exec chrpath --delete {} \; 2>/dev/null || : # ACVD's CMakeLists writes ONE ACVDConfig.cmake for both the build tree and the # install tree, so the installed copy hardcodes the absolute SOURCE paths of the # machine that built it: # set( ACVD_INCLUDE_DIRS "/builddir/build/BUILD/acvd-4.0-build/ACVD-4.0/Common; # ...;/DiscreteRemeshing;.../VolumeProcessing" ) # and then include_directories() on them. Those directories exist nowhere but the # builder, so every consumer of find_package(ACVD) silently gets include paths # pointing at nothing -- MITK's Modules/Remeshing failed with # "vtkIsotropicDiscreteRemeshing.h: No such file or directory" even though # acvd-devel ships that header (mitk 2026.06-12, object 3279 of 4406). # Point them at the installed layout instead. Kept as three entries because MITK # and ShapeWorks include these headers flat (), # not as . sed -i -E 's|^set\( *ACVD_INCLUDE_DIRS .*\)$|set( ACVD_INCLUDE_DIRS "%{_includedir}/ACVD/Common;%{_includedir}/ACVD/DiscreteRemeshing;%{_includedir}/ACVD/VolumeProcessing" )|' \ %{buildroot}%{_libdir}/cmake/ACVD/ACVDConfig.cmake grep -q '%{_includedir}/ACVD/DiscreteRemeshing' \ %{buildroot}%{_libdir}/cmake/ACVD/ACVDConfig.cmake \ || { echo "ERROR: ACVD_INCLUDE_DIRS rewrite did not apply"; exit 1; } ! grep -q '/builddir/' %{buildroot}%{_libdir}/cmake/ACVD/ACVDConfig.cmake \ || { echo "ERROR: build-tree paths still present in ACVDConfig.cmake"; exit 1; } # The INSTALLED headers have the same unqualified-cout/endl problem the %%build # prelude works around for ACVD's own compilation -- but that prelude is a build # flag, so it never reaches consumers. 8 headers, 149 sites, none of which # include . Any downstream that INSTANTIATES the templates (a plain # #include is not enough; the bodies only get diagnosed on instantiation) fails # with "'cout' was not declared in this scope [-Wtemplate-body]" -- MITK's # Modules/Remeshing hit exactly this, 35 errors, once the include path above was # fixed and the headers were finally reachable. # Qualify with std:: rather than injecting "using namespace std" into public # headers, which would leak into every consumer's translation units. The perl # lookbehinds skip already-qualified names and member accesses (x.cout, p->cout). _acvd_hdrs=$(grep -rlE '(^|[^:[:alnum:]_>.])(cout|cerr|cin|endl)[^[:alnum:]_]' \ %{buildroot}%{_includedir}/ACVD/ || :) for _h in $_acvd_hdrs; do perl -pi -e 's/(?])\b(cout|cerr|cin|endl)\b/std::$1/g' "$_h" grep -q '#include ' "$_h" \ || perl -0pi -e 's/^(#include)/#include \n$1/m' "$_h" done # Guards: the rewrite must have run, and must not have double-qualified anything. grep -q 'std::cout' %{buildroot}%{_includedir}/ACVD/Common/vtkUniformClustering.h \ || { echo "ERROR: ACVD header std:: qualification did not apply"; exit 1; } ! grep -rq 'std::std::' %{buildroot}%{_includedir}/ACVD/ \ || { echo "ERROR: double-qualified std::std:: in ACVD headers"; exit 1; } %files %license LICENSE.txt %doc Readme.md %{_libdir}/libvtkSurface.so.4.0* %{_libdir}/libvtkVolumeProcessing.so.4.0* %files devel %{_includedir}/ACVD/ %{_libdir}/libvtkSurface.so %{_libdir}/libvtkVolumeProcessing.so %{_libdir}/cmake/ACVD/ %changelog * Mon Sep 28 2026 Morgan Hough - 4.0-6 - Recode the sources to UTF-8 in %prep. Common/vtkOFFWriter.h carries one Latin-1 byte in a comment and that header is INSTALLED, so it is a problem for consumers rather than for us: harmless until something compiles with a UTF-8 source charset, and then a downstream build fails on a file it does not own. 4.0-5 shipped it -- file(1) says "C++ source, ISO-8859 text" and iconv rejects it. - Swept rather than patched by name. Exactly one of 33 installed headers is affected today; fixing only the file we were told about would leave the next one for whoever it breaks. %prep asserts the whole tree is valid UTF-8 afterwards. - Reported by the neurodebian session from packaging ACVD for Debian, and confirmed here against our own published acvd-devel rpm. * Sun Aug 23 2026 Morgan Hough - 4.0-4 - Rebuild against VTK 9.7.0. VTK here installs unversioned sonames (libvtk*.so.1), so 9.7 replaces 9.6 in place and every consumer must be rebuilt or it fails at runtime with undefined symbols. - Add acvd-vtk97-addviewprop.patch: VTK 9.7 removed vtkViewport::AddActor2D/RemoveActor2D; switch to the AddViewProp/RemoveViewProp they aliased. * Mon Aug 03 2026 Morgan Hough - 4.0-3 - Qualify cout/cerr/cin/endl with std:: in the INSTALLED headers and add the missing . %%build already force-includes a prelude supplying both, but that is a compiler flag for ACVD's own sources -- the headers ship unchanged, so every consumer inherits the problem. 8 headers, 149 sites, none including . A plain #include is not enough to trigger it: the template bodies are only diagnosed on instantiation, which is why this stayed hidden until MITK's Modules/Remeshing instantiated them and produced 35 "'cout' was not declared in this scope [-Wtemplate-body]" errors -- and only after 4.0-2 fixed the include path so the headers were reachable at all. std:: qualification rather than "using namespace std" in a public header, which would leak into every consumer. Verified inside the preserved mock chroot with MITK's own compile command: 35 errors -> COMPILE_OK. Should go upstream with the 4.0-2 config fix. * Mon Aug 03 2026 Morgan Hough - 4.0-2 - Rewrite ACVD_INCLUDE_DIRS in the installed ACVDConfig.cmake. ACVD generates a single config file for both its build tree and its install tree, so the shipped copy hardcoded the absolute source paths of the build machine (/builddir/build/BUILD/acvd-4.0-build/ACVD-4.0/{Common,DiscreteRemeshing, VolumeProcessing}) and then called include_directories() on them. Those exist nowhere but the builder, so every consumer of find_package(ACVD) got include directories pointing at nothing while the headers themselves were installed correctly under %%{_includedir}/ACVD/. MITK's Modules/Remeshing failed with "vtkIsotropicDiscreteRemeshing.h: No such file or directory" (mitk 2026.06-12, object 3279 of 4406) despite acvd-devel shipping that exact header. Two guards: the rewrite must apply, and no /builddir/ path may survive. Worth sending upstream -- the same config is wrong for every packager. * Thu Jun 18 2026 Morgan Hough - 4.0-1 - Initial package (stock upstream valette/ACVD v4.0). Library-only build (BUILD_EXAMPLES=OFF) against system VTK; provides vtkSurface / vtkVolumeProcessing / vtkDiscreteRemeshing for the ShapeWorks dependency chain.