Blob Blame History Raw
%global _description %{expand:
MorphIO is a library for reading and writing neuron morphology files. It
supports the following formats:

- SWC
- ASC (aka. neurolucida)
- H5 v1
- H5 v2 is not supported anymore

It provides 3 C++ classes that are the starting point of every morphology
analysis:

- Soma: contains the information related to the soma.
- Section: a section is the succession of points between two bifurcations. To
  the bare minimum the Section object will contain the section type, the
  position and diameter of each point.
- Morphology: the morphology object contains general information about the
  loaded cell but also provides accessors to the different sections.

One important concept is that MorphIO is split into a read-only part and a
read/write one.
}

%global pretty_name MorphIO

# Include the pybind11 sources, which upstream includes as a sub-module
# pybind11 documentation suggests that this is the correct way to use pybind11
# Using the Fedora pybind11-devel package does not work (or I've not been able
# to figure out how to correctly patch this project to use it)
# https://pybind11.readthedocs.io/en/stable/compiling.html#building-with-cmake
#
# Official support for external pybind11 requested upstream:
# https://github.com/BlueBrain/MorphIO/issues/337
%global p_commit b4e5d582cb656a590b256bcf4a8ffa7c8ce9ba19
%global p_shortcommit %(c=%{p_commit}; echo ${c:0:7})
# pybind11/_version.py
%global p_version 2.4~dev4

# cpp tests
%bcond_without tests
# python tests
%bcond_without pytests

%bcond_without sphinxdocs

Name:           morphio
Version:        3.3.0
Release:        1%{?dist}
Summary:        A python and C++ library for reading and writing neuronal morphologies

# The entire source is LGPLv3 except the following, which are BSD:
#   - 3rdparty/pybind11/
#   - CMake/CodeCoverage.cmake
# The “effective license” remains LGPLv3.
License:        LGPLv3
URL:            https://github.com/BlueBrain/MorphIO
Source0:        %{url}/archive/v%{version}/%{name}-%{version}.tar.gz
Source1:        https://github.com/pybind/pybind11/archive/%{p_commit}/pybind11-%{p_shortcommit}.tar.gz

# Patches
# TODO: Some of these will be sent upstream
# Do not use their compiler flags
Patch0:         0001-Do-not-use-their-compiler-flags.patch
# Do not let cmake use $FLAGS env var
Patch1:         0002-Stop-them-using-a-random-env-var.patch
# Use CMake GNUInstallDirs to install things in the right places
Patch2:         0003-Use-gnuinstall-dirs.patch
# Remove more hard-coded compiler flags
Patch3:         0004-Remove-upstreams-flags.patch
# Set a shared object version (0.0.0)
Patch4:         0005-Version-soname.patch
# Add install target for the compiled python module
Patch5:         0006-Install-python-shared-object.patch
# Stop setup.py from running the cmake build, we’ll run it ourselves
Patch6:         0007-Stop-setup.py-from-cmake-build.patch
# Some Python tests are failing because “expected” results are float32 and then
# promoted back to float64 for comparison with the actual results. We are not
# sure why upstream is not experiencing this.
Patch7:         MorphIO-3.3.0-pytests-float32.patch

# Fix build failure on armv7hl:
#
# FAILED: binds/python/_morphio.cpython-310-arm-linux-gnueabihf.so
# : && /usr/bin/g++ -fPIC -O2 -flto=auto -ffat-lto-objects -fexceptions -g
#     -grecord-gcc-switches -pipe -Wall -Werror=format-security
#     -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS
#     -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong
#     -march=armv7-a -mfpu=vfpv3-d16 -mtune=generic-armv7-a -mabi=aapcs-linux
#     -mfloat-abi=hard  -Wl,-z,relro -Wl,--as-needed  -Wl,-z,now
#     -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -shared  -o
#     binds/python/_morphio.cpython-310-arm-linux-gnueabihf.so
#     binds/python/CMakeFiles/_morphio.dir/morphio.cpp.o
#     binds/python/CMakeFiles/_morphio.dir/bind_immutable.cpp.o
#     binds/python/CMakeFiles/_morphio.dir/bindings_utils.cpp.o
#     binds/python/CMakeFiles/_morphio.dir/bind_misc.cpp.o
#     binds/python/CMakeFiles/_morphio.dir/bind_mutable.cpp.o
#     binds/python/CMakeFiles/_morphio.dir/bind_vasculature.cpp.o  -flto
#     src/libmorphio_static.a  -lhdf5 && :
# /usr/bin/ld: binds/python/CMakeFiles/_morphio.dir/bind_mutable.cpp.o (symbol
#     from plugin): in function `bind_mutable_module(pybind11::module&)':
# (.text+0x0): multiple definition of `typeinfo name for
#     morphio::SectionBase<morphio::Section>';
#     binds/python/CMakeFiles/_morphio.dir/bind_immutable.cpp.o (symbol from
#     plugin):(.text+0x0): first defined here
# /usr/bin/ld: binds/python/CMakeFiles/_morphio.dir/bind_mutable.cpp.o (symbol
#     from plugin): in function `bind_mutable_module(pybind11::module&)':
# (.text+0x0): multiple definition of `typeinfo for
#     morphio::SectionBase<morphio::Section>';
#     binds/python/CMakeFiles/_morphio.dir/bind_immutable.cpp.o (symbol from
#     plugin):(.text+0x0): first defined here
#
# This indicates an identical explicit template instantiation appears in more
# than one translation unit, which violates the C++ standard. Since the
# instantiation is in a header, this occurs whenever the header is included in
# more than one translation unit. GCC tends to produce an error about this on
# 32-bit ARM but not on other common architectures. See also
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608029.
#
# https://github.com/BlueBrain/MorphIO/pull/338
Patch8:         https://github.com/BlueBrain/MorphIO/pull/338.patch
# Remove unused Python mock dependency
# https://github.com/BlueBrain/MorphIO/pull/339
Patch9:         https://github.com/BlueBrain/MorphIO/pull/339.patch

BuildRequires:  hdf5-devel
BuildRequires:  boost-devel
%if %{with tests}
BuildRequires:  catch-devel
%endif

BuildRequires:  gcc-c++
BuildRequires:  cmake
# Our choice: the make backend works fine too
BuildRequires:  ninja-build

# Header-only libraries; -static required by guidelines for tracking
BuildRequires:  cmake(gsl-lite)
BuildRequires:  gsl-lite-static
BuildRequires:  cmake(highfive)
BuildRequires:  highfive-static
BuildRequires:  lexertl14-devel
BuildRequires:  lexertl14-static
# We cannot currently figure out how to unbundle this:
#BuildRequires:  cmake(pybind11)
#BuildRequires:  pybind11-static
Provides:       bundled(pybind11) = %{p_version}

%description %_description


%package        devel
Summary:        Development files for %{name}
Requires:       %{name}%{?_isa} = %{version}-%{release}
Provides:       %{name}-static = %{version}-%{release}

# A gsl header is included from the public morphio/types.h header.
Requires:       gsl-lite-devel%{?_isa}
Requires:       gsl-lite-static
# A HighFive header is included from the public morphio/morphology.h header.
Requires:       highfive-devel%{?_isa}
Requires:       highfive-static
# Note that packages using this -devel package should ideally also BR
# gsl-lite-static and highfive-static for header-only library tracking.

%description    devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.


%package -n python3-%{name}
Summary:        Python bindings for %{name}
BuildRequires:  python3-devel
BuildRequires:  python3-setuptools
BuildRequires:  python3-setuptools_scm
%if %{with pytests}
# tests/requirements-tests.txt
BuildRequires:  %{py3_dist h5py} >= 2.9.0
BuildRequires:  %{py3_dist pytest} >= 6.0
BuildRequires:  %{py3_dist numpy} >= 1.14.2
BuildRequires:  %{py3_dist requests} >= 2.25.1
%endif

# Note that this package does not depend at all on the base package (it does
# not link against the shared library).

%description -n python3-%{name}
This package includes the Python 3 bindings for %{name}.


%package doc
Summary:        Documentation for %{name}
BuildArch:      noarch
%if %{with sphinxdocs}
BuildRequires:  %{py3_dist sphinx}
BuildRequires:  doxygen
BuildRequires:  graphviz
%endif

%description doc
This package provides documentation for %{name}


%prep
%autosetup -n %{pretty_name}-%{version} -p1

# https://github.com/BlueBrain/MorphIO/pull/336
mv CHANGLOG.md CHANGELOG.md

# Unbundle gsl-lite
rm -rvf 3rdparty/GSL_LITE
sed -r -i '/GSL_LITE/d' MANIFEST.in
sed -r -i '/director.*\(.*(gsl-lite|GSL_LITE).*\)/d' 3rdparty/CMakeLists.txt
sed -r -i \
    -e '/TARGET_PROPERTY:gsl-lite,INTERFACE_INCLUDE_DIRECTORIES/d' \
    -e 's/PUBLIC[[:blank:]]+gsl-lite[[:blank:]]+(PRIVATE)/\1/' \
    src/CMakeLists.txt
# Update includes. Note that this affects the public API headers.
#
# The grep-then-sed pattern means we only modify those files that need it,
# preserving the mtimes on the others.
grep -ErIl '#[[:blank:]]*include[[:blank:]]+["<]gsl/gsl[">]' . |
  xargs -r sed -r -i \
      's@(#[[:blank:]]*include[[:blank:]]+["<]gsl/gsl)([">])@\1-lite\.hpp\2@'

# Unbundle lexertl
rm -rvf '3rdparty/lexertl'
ln -s '%{_includedir}/lexertl' '3rdparty/'

# pybind11
pushd 3rdparty/pybind11/
%{__tar} --strip-components 1 -xvf %{SOURCE1}
popd

# Remove bundled catch.hpp
# We use the system copy
rm -frv tests/contrib
# Correct include
find tests/ -type f -exec sed -i 's|"contrib/catch.hpp"|"catch2/catch.hpp"|' '{}' \;

# Sphinx documentation uses sphinx-bluebrain-theme, which bundles
# mkdocs-material, which has pre-built compiled/minified JavaScript and CSS
# assets that cannot be packaged under guidelines (and the asset build pipeline
# is too complicated and “webby” to reproduce when building the RPM as would be
# required)—see https://bugzilla.redhat.com/show_bug.cgi?id=1960274#c3.
# Therefore, we change the theme, with the understanding that the documentation
# won’t appear as intended. It still seems to be generally usable.
sed -r -i 's/sphinx-bluebrain-theme/alabaster/' doc/source/conf.py

# Some of these could make it into the installed package:
find . -type f -name .gitignore -print -delete


%build
export SETUPTOOLS_SCM_PRETEND_VERSION='%{version}'
%cmake \
    -DEXTERNAL_HIGHFIVE:BOOL=TRUE \
    -DMORPHIO_USE_DOUBLE:BOOL=TRUE \
    -DBUILD_BINDINGS:BOOL=TRUE \
    -DMORPHIO_TESTS:BOOL=%{?with_tests:TRUE}%{?!with_tests:FALSE} \
    -DMORPHIO_ENABLE_COVERAGE:BOOL=TRUE \
    -DMORPHIO_VERSION_STRING:STRING="%{version}" \
    -GNinja
%cmake_build

# Build pure python bits
%py3_build

%if %{with sphinxdocs}
(
  # Temporary local installation so we can reliably import the Cython extension
  # module to build documentation.
  #
  # A similar approach would work even with pyproject-rpm-macros; see
  # https://src.fedoraproject.org/rpms/python-asyncpg for an example, and
  #   https://lists.fedoraproject.org/archives/list/
  #     python-devel@lists.fedoraproject.org/message/
  #     TRPRWUR4XCDSZ64RNWYVCH636CT4VHAT/
  # for alternatives.
  PYTEMP="${PWD}/%{_vpath_builddir}/pytemp"
  export PYTHONPATH="${PYTEMP}%{python3_sitearch}:${PYTEMP}%{python3_sitelib}"

  %{__python3} %{py_setup} %{?py_setup_args} install \
      -O1 --skip-build --root "${PYTEMP}"

  %make_build -C doc html SPHINXOPTS='%{?_smp_mflags}'
  rm -vf doc/build/html/.buildinfo

  rm -rf "${PYTEMP}"
)
%endif


%install
export SETUPTOOLS_SCM_PRETEND_VERSION='%{version}'
%cmake_install
# Install pure python bits
%py3_install

# Move module to sitearch so that the binding can be correctly imported.
if [ '%{python3_sitelib}' != '%{python3_sitearch}' ]
then
  mv -v $RPM_BUILD_ROOT/%{python3_sitelib}/%{name}/* \
      $RPM_BUILD_ROOT/%{python3_sitearch}/%{name}
  mv -v $RPM_BUILD_ROOT/%{python3_sitelib}/%{pretty_name}* \
      $RPM_BUILD_ROOT/%{python3_sitearch}/
fi


%check
export SETUPTOOLS_SCM_PRETEND_VERSION='%{version}'
%if %{with tests}
# From ci/cpp_test.sh
%ctest
%endif
%if %{with pytests}
# We will change directories so that the “un-built” package is not imported
xdir="$(basename "${PWD}")"
# From ci/python_test.sh
cd ..
# Fetches from the Internet:
k='not test_v2'
# TODO: Is this a real problem? The answer is only slightly outside tolerances.
#
# >               assert_array_almost_equal(neuron.markers[0].points,
#                                           np.array([[81.58, -77.98, -20.32]], dtype=np.float32))
# E               AssertionError:
# E               Arrays are not almost equal to 6 decimals
# E
# E               Mismatched elements: 2 / 3 (66.7%)
# E               Max absolute difference: 3.35693359e-06
# E               Max relative difference: 4.30486464e-08
# E                x: array([[ 81.58, -77.98, -20.32]])
# E                y: array([[ 81.58, -77.98, -20.32]], dtype=float32)
k="${k} and not test_neurolucida_markers"
# TODO: Is this a real problem? The answer is only slightly outside tolerances.
#
# >       assert_array_equal(m.markers[0].points, np.array([[  -0.97    , -141.169998,   84.769997]],
#                                                          dtype=np.float32))
# E       AssertionError:
# E       Arrays are not equal
# E
# E       Mismatched elements: 3 / 3 (100%)
# E       Max absolute difference: 3.35693359e-06
# E       Max relative difference: 3.96004922e-08
# E        x: array([[  -0.97, -141.17,   84.77]])
# E        y: array([[  -0.97, -141.17,   84.77]], dtype=float32)
k="${k} and not test_marker_with_string"
%pytest "${xdir}/tests" -k "${k}"
%endif


%files
%license COPYING COPYING.LESSER
%{_libdir}/libmorphio.so.0.0.0


%files devel
%{_includedir}/%{name}
%{_libdir}/libmorphio.so
%{_libdir}/cmake/%{pretty_name}


%files -n python3-%{name}
%license COPYING COPYING.LESSER
%{python3_sitearch}/%{name}
%{python3_sitearch}/%{pretty_name}-%{version}-py%{python3_version}.egg-info


%files doc
%license COPYING COPYING.LESSER
%doc CHANGELOG.md CONTRIBUTING.md README.rst examples
%if %{with sphinxdocs}
%doc doc/build/html
%endif


%changelog
* Wed Aug 25 2021 Benjamin A. Beasley <code@musicinmybrain.net> - 3.3.0-1
- Update to 3.3.0
- Use cmake(…) dependencies where appropriate
- Unbundle lexertl14
- Remove ExcludeArch on i686 and armv7hl since these are fixed in highfive (and
  an additional problem on armv7hl is fixed here)
- Add license files to -doc subpackage; drop text doc files from others
- Enable Sphinx documentation (with an alternative theme)
- Use SETUPTOOLS_SCM_PRETEND_VERSION instead of a local git repo
- Enable Python tests
- Add header-only dependencies present in the public API to the -devel package

* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.0.2-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild

* Fri Jun 04 2021 Python Maint <python-maint@redhat.com> - 3.0.2-2
- Rebuilt for Python 3.10

* Thu Apr 22 2021 Ankur Sinha <ankursinha AT fedoraproject DOT org> - 3.0.2-1
- Add excludearch because of highfive
- do not carry licenses in devel package, since it depends on the main package already

* Wed Apr 21 2021 Ankur Sinha <ankursinha AT fedoraproject DOT org> - 3.0.2-1
- Enable tests

* Sat Apr 17 2021 Ankur Sinha <ankursinha AT fedoraproject DOT org> - 3.0.2-1
- Initial build