# Pinned submodule commits for 3.7.0 tag %global sdk_commit cbcc6e0cac025a277464a81c24b45cc8140c7405 %global designer_commit 50ac3772d5a21b01bc5a41bbfc4fbffeebd73974 %global extras_commit 97cdd0f70e9e749858aaca0f35a7d4424c59b778 Name: openvibe Version: 3.7.0 Release: 13%{?dist} Summary: Brain-Computer Interface platform for EEG/MEG signal processing License: AGPL-3.0-or-later URL: http://openvibe.inria.fr Source0: https://gitlab.inria.fr/openvibe/meta/-/archive/%{version}/meta-%{version}.tar.gz Source1: https://gitlab.inria.fr/openvibe/sdk/-/archive/%{sdk_commit}/sdk-%{sdk_commit}.tar.gz Source2: https://gitlab.inria.fr/openvibe/designer/-/archive/%{designer_commit}/designer-%{designer_commit}.tar.gz Source3: https://gitlab.inria.fr/openvibe/extras/-/archive/%{extras_commit}/extras-%{extras_commit}.tar.gz # Tiny bundled sources with no system-package equivalent Provides: bundled(lepton) Provides: bundled(r8brain) Provides: bundled(wavelib) Provides: bundled(dsp-filters) Provides: bundled(SuperEasyJSON) BuildRequires: cmake >= 3.20 BuildRequires: ninja-build BuildRequires: gcc-c++ # Core dependencies BuildRequires: boost-devel >= 1.71 BuildRequires: eigen3-devel BuildRequires: lua-devel BuildRequires: xerces-c-devel BuildRequires: tinyxml2-devel BuildRequires: expat-devel BuildRequires: zlib-devel # GTK2 — used for the designer GUI and visualization plugins BuildRequires: gtk2-devel BuildRequires: pkgconfig(gtk+-2.0) # OpenGL (GLX) — used for 3D visualization rendering BuildRequires: mesa-libGL-devel BuildRequires: libX11-devel # Audio BuildRequires: openal-soft-devel BuildRequires: freealut-devel BuildRequires: libogg-devel BuildRequires: libvorbis-devel # Signal processing BuildRequires: fftw-devel # External device/streaming protocols BuildRequires: vrpn-devel # Lab Streaming Layer — from mhough/neurofedora COPR. # Several extras plugins (games, network-io, acquisition-server) unconditionally # link LSL::lsl, so this is effectively required despite find_package lacking REQUIRED. BuildRequires: liblsl-devel >= 1.16 # Scripting BuildRequires: python3-devel # GTest — required by cmake configure even when tests are disabled BuildRequires: gtest-devel Requires: gtk2%{?_isa} %description OpenViBE is an open-source software platform for Brain-Computer Interfaces (BCI). It can be used to acquire, filter, process, classify, and visualize brain signals in real time. OpenViBE supports EEG and MEG data from a wide range of acquisition hardware through its acquisition server, and provides a visual designer for building signal-processing pipelines using a drag-and-drop box paradigm. %package devel Summary: Development headers for OpenViBE SDK Requires: %{name}%{?_isa} = %{version}-%{release} %description devel Headers and development files for building plugins and applications against the OpenViBE SDK (modules: ebml, xml, socket, fs, csv, communication, system, toolkit, visualization-toolkit). %prep # GitLab names an archive's top directory after the project's *name* and ref, # not its path: openvibe/meta at tag 3.7.0 unpacks as # "openvibe-3.7.0-7de1f01340f705bfe53af6a1b49e7ad2b72c4868/", not "meta-3.7.0/". # The project was evidently renamed to "openvibe" while keeping the "meta" path, # so `%%autosetup -n meta-%%{version}` stopped matching and %%prep died with # cd: meta-3.7.0: No such file or directory # (11006001, f45-aarch64). Nothing arch-specific: 3.7.0-9 is published on # f45-x86_64 from before the rename and would fail the same way if rebuilt. # # Do not chase the new name -- pinning it would break again on the next rename, # and the sha in it is not something the spec otherwise knows. Create the # directory and strip the top level off, which is what Sources 1-3 already do # below and is immune to whatever upstream calls it. %setup -q -c -T -n %{name}-%{version} tar -xf %{SOURCE0} --strip-components=1 # Unpack submodules into their directories tar -xf %{SOURCE1} --strip-components=1 -C sdk tar -xf %{SOURCE2} --strip-components=1 -C designer tar -xf %{SOURCE3} --strip-components=1 -C extras # Disable extras/applications/examples/openvibe-to-tcpip: uses the removed # boost::asio::ip::tcp::resolver::query API (gone in Boost 1.84+; F44+ # ships >= 1.86). The example isn't shipped in any binary subpackage — # just blow away its CMakeLists so OV_ADD_PROJECTS skips it. rm -rf extras/applications/examples/openvibe-to-tcpip # Remove install(CODE ... create_symlink ...) blocks — they use absolute paths # that bypass DESTDIR, trying to create symlinks in /usr/ instead of $DESTDIR/usr/. # The symlinks are redundant anyway (binaries already install to /usr/bin). find sdk designer extras -name CMakeLists.txt -exec \ sed -i '/install(CODE/,/^)/d' {} + # Fix hardcoded CMAKE_INSTALL_LIBDIR — upstream forces "lib" but Fedora needs # the arch-specific libdir (lib64 on x86_64) sed -i '/^set(CMAKE_INSTALL_LIBDIR lib)/d' CMakeLists.txt sed -i '/^SET(CMAKE_INSTALL_LIBDIR lib)/d' designer/CMakeLists.txt # Fix DIST_LIBDIR to use CMAKE_INSTALL_LIBDIR instead of hardcoded "lib" sed -i 's|set(DIST_LIBDIR ${DIST_ROOT}/lib)|set(DIST_LIBDIR ${DIST_ROOT}/${CMAKE_INSTALL_LIBDIR})|' CMakeLists.txt # Py_GetPath() was deprecated in Python 3.13 and REMOVED in 3.15, which f45 # ships. Seven lines across five files in extras/ still call it. # # Only three are compiled on Linux, and all three are the same debug log line: # getLogManager() << LogLevel_Debug << "The Python path is [" << Py_GetPath() # in pybox-manager/CPolyBox.cpp, python3/ovpCBoxAlgorithmPython3.cpp and # python2/ovpCBoxAlgorithmPython2.cpp. The remaining four, in the two # ovp_main.cpp files, sit inside #ifdef TARGET_OS_Windows -- two of those are # functional rather than diagnostic (checkPython3Path parses the path), so they # are deliberately left alone: rewriting Windows code we never compile would be # unreviewable churn. # # There is no drop-in replacement returning wchar_t*; the supported route is # PyConfig_Get("module_search_paths"), which yields a PyObject and does not fit a # stream insertion. So the three log lines go. # # (-11 fixed only CPolyBox.cpp because I matched on the build log, which names # one failing file at a time; ovpCBoxAlgorithmPython3.cpp:159 was next in line. # Hence the tree-wide sed and a guard that checks the whole of extras/.) sed -i '/The Python path is \[/d' \ $(grep -rl 'The Python path is \[' extras) # Every surviving reference must be Windows-only. Anything else means a new call # site appeared and this needs revisiting rather than silently shipping broken. leftover=$(grep -rl 'Py_GetPath' extras 2>/dev/null | grep -v 'ovp_main\.cpp$' || true) if [ -n "$leftover" ]; then echo "ERROR: Py_GetPath outside the Windows-only ovp_main.cpp files:" >&2 echo "$leftover" >&2 exit 1 fi # Fix Eigen3 version check for Fedora 44+ (Eigen 5.x SameMajorVersion compat) sed -i 's/find_package(Eigen3 3.3.7)/find_package(Eigen3)/' CMake/FindThirdPartyEigen.cmake # Fix Python3 version — upstream hardcodes 3.10 EXACT; Fedora 43 has 3.14 sed -i 's/find_package(Python3 3.10 EXACT/find_package(Python3 3/' CMake/FindThirdPartyPython.cmake # Designer plugins: project() calls lack VERSION, resulting in literal "SOVERSION" filenames for f in designer/plugins/visualization/ovp-advanced-visualization/CMakeLists.txt \ designer/plugins/visualization/simple-visualization/CMakeLists.txt \ designer/plugins/examples/CMakeLists.txt; do sed -i 's/^PROJECT(\(.*\))/PROJECT(\1 VERSION %{version})/' "$f" sed -i 's/^project(\(.*\))/project(\1 VERSION %{version})/' "$f" done # aarch64: remove x86-only -msse2 flag sed -i 's/set(OV_EIGEN_FLAGS "-msse2")/if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|i686")\n\tset(OV_EIGEN_FLAGS "-msse2")\nelse()\n\tset(OV_EIGEN_FLAGS "")\nendif()/' \ sdk/CMakeLists.txt extras/CMakeLists.txt # Boost 1.87+ (F44+): io_service removed, use io_context; resolver::query removed; # deadline_timer removed, use steady_timer. sed -i 's/boost::asio::io_service/boost::asio::io_context/g' \ extras/modules/tcptagging/include/tcptagging/CStimulusSender.h \ extras/contrib/plugins/server-extensions/tcp-tagging/ovasCTagStream.h \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.h \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.cpp # Same rename for the m_ioService member-init / type variants sed -i 's/io_service/io_context/g' \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.cpp # deadline_timer → steady_timer sed -i 's/boost::asio::deadline_timer/boost::asio::steady_timer/g' \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.h \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.cpp # Residual Boost 1.87 API fallout in ovasCSmartingAmp.cpp surfaced by -8 # build 10522031: # - io_context::reset() was deprecated in 1.66, removed in 1.87 → restart() # - steady_timer takes std::chrono durations, not boost::posix_time; # expires_from_now() also removed → expires_after() sed -i \ -e 's/m_io\.reset()/m_io.restart()/g' \ -e 's/expires_from_now(boost::posix_time::milliseconds(/expires_after(std::chrono::milliseconds(/g' \ extras/contrib/plugins/server-drivers/mbt-smarting/src/ovasCSmartingAmp.cpp # Replace the query+resolve+connect block with modern Boost.Asio API # resolver.resolve() returns results_type, use boost::asio::connect() instead of socket.connect(*iter) sed -i '/const boost::asio::ip::tcp::resolver::query query/,/m_oStimulusSocket.connect(\*endpointIterator, error);/c\\t\t\tauto endpoints = resolver.resolve(sAddress, sStimulusPort);\n\t\t\tboost::asio::connect(m_oStimulusSocket, endpoints, error);' \ extras/modules/tcptagging/src/CStimulusSender.cpp # GCC 15: explicit qualification in declaration is now a hard error # RiemannianPotato.cpp defines free functions with Riemannian:: qualifier # inside the Riemannian namespace — remove the redundant qualifier sed -i 's/void Riemannian::saveToXML/void saveToXML/' \ extras/plugins/processing/riemannian/src/boxes/RiemannianPotato.cpp sed -i 's/Riemannian::loadFromXML/loadFromXML/' \ extras/plugins/processing/riemannian/src/boxes/RiemannianPotato.cpp # GCC 15 / C++17: floor/log/etc. need — add missing include sed -i '1i #include ' \ extras/plugins/processing/signal-processing/src/box-algorithms/CBoxAlgorithmEntropyMeasure.cpp # GCC 16 / C++20: std::none_of moved out of transitive — needs # explicit include in this file. sed -i '1i #include ' \ extras/plugins/processing/simple-visualization/src/box-algorithms/CBoxAlgorithmErpPlot.cpp # VRPN: OpenViBE vrpn-simulator and vrpn-to-openvibe use vrpn_Button_Server # which lives in libvrpnserver, not libvrpn — add it to the vrpn interface target sed -i 's/target_link_libraries(vrpn INTERFACE ${VRPN_LIBRARY} ${QUAT_LIBRARY})/find_library(VRPNSERVER_LIBRARY NAMES vrpnserver)\ntarget_link_libraries(vrpn INTERFACE ${VRPN_LIBRARY} ${VRPNSERVER_LIBRARY} ${QUAT_LIBRARY})/' \ CMake/FindThirdPartyVRPN.cmake # Boost 1.87+ (F44+): boost::filesystem::extension() removed, use path method sed -i 's/boost::filesystem::extension(path)/boost::filesystem::path(path).extension().string()/' \ designer/applications/platform/designer/src/CInterfacedScenario.cpp # IT++ library is not in Fedora — remove from contrib signal-processing link sed -i '/^[[:space:]]*itpp[[:space:]]*$/d' \ extras/contrib/plugins/processing/signal-processing/CMakeLists.txt %build export CXXFLAGS="%{optflags} -std=c++17 -include cstdint -fpermissive" %cmake -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_SKIP_INSTALL_RPATH=ON \ -DBUILD_VALIDATION_TEST=OFF \ -DBUILD_UNIT_TEST=OFF \ -DBUILD_DOCUMENTATION=OFF \ -DBUILD_GCOV=OFF \ -DOV_PACKAGE=OFF %cmake_build %install %cmake_install # OpenViBE plugins are loaded by dlopen("libopenvibe-plugins-*.so") at runtime, # so unversioned .so symlinks must stay in the main package # Fix non-executable shell script chmod +x %{buildroot}%{_datadir}/openvibe/plugins/simple-visualization/p300-magic-card/convert.sh # Drop the advanced-visualization TEST RENDERER. It is the only thing in the # package that links libmensia-advanced-visualization.so.3, and that library # is never installed: upstream builds it SHARED but its install rules ship # only libmensia-advanced-visualization-static.a. rpm generates # "Requires: libmensia-advanced-visualization.so.3()(64bit)" from these two # binaries, nothing in any chroot provides it, and openvibe was therefore # UNINSTALLABLE on all seven chroots (found by repoclosure, not by a build -- # every build was green). # # Removing the test harness rather than installing the library, because # installing a library upstream deliberately does not install would make us # the owner of its soname and ABI for the sake of a test tool. Upstream # shipping the -static.a is the tell: consumers are meant to link statically # and the shared build is internal to this harness. # # No regression risk: the package cannot be installed today, so nobody has # these binaries. # # A build-tree sweep confirmed this is the ONLY such case -- 51 shared # libraries are built, 50 reach the buildroot, and the one that does not is # libmensia-advanced-visualization.so. for _b in %{buildroot}%{_bindir}/openvibe-lib-adv-viz-test-renderer \ %{buildroot}%{_bindir}/openvibe-lib-adv-viz-test-renderer-%{version}; do test -e "$_b" || { echo "ERROR: $_b absent -- upstream changed, drop this block" >&2; exit 1; } rm -f "$_b" done # The point of the removal is the dependency, so assert on THAT, not on the files. if grep -rlq . %{buildroot}%{_bindir} 2>/dev/null; then if find %{buildroot} -type f -perm -u+x -exec sh -c \ 'objdump -p "$1" 2>/dev/null | grep -q "NEEDED.*libmensia-advanced-visualization"' _ {} \; -print \ | grep -q .; then echo "ERROR: something still links libmensia-advanced-visualization; openvibe will be uninstallable" >&2 exit 1 fi fi %ldconfig_scriptlets %files %license COPYING %doc sdk/COPYING.md extras/COPYING # Binaries %{_bindir}/openvibe-* %{_bindir}/sdk-examples-* # Shared libraries — plugins need unversioned .so for dlopen at runtime %{_libdir}/lib*.so %{_libdir}/lib*.so.* # Data files %{_datadir}/openvibe/ %files devel %{_includedir}/*.h %{_includedir}/*.hpp %{_includedir}/communication/ %{_includedir}/csv/ %{_includedir}/ebml/ %{_includedir}/fs/ %{_includedir}/geometry/ %{_includedir}/openvibe/ %{_includedir}/socket/ %{_includedir}/system/ %{_includedir}/toolkit/ %{_includedir}/visualization-toolkit/ %{_includedir}/xml/ %{_includedir}/eigen/ %{_includedir}/lsl/ %{_includedir}/mensia/ %{_includedir}/tcptagging/ %{_libdir}/*.a %changelog * Tue Oct 06 2026 Morgan Hough - 3.7.0-13 - Fix openvibe being UNINSTALLABLE on all seven chroots. It Requires libmensia-advanced-visualization.so.3()(64bit) and nothing in any chroot provides it. Upstream builds that library SHARED but its install rules ship only libmensia-advanced-visualization-static.a, so the shared object exists only in the cmake build tree. The sole consumer is the test harness openvibe-lib-adv-viz-test-renderer, which IS shipped, so rpm generated the dependency from it. - Drop the test renderer rather than install the library. Installing a library upstream deliberately does not install would make us the owner of its soname and ABI for the sake of a test tool; upstream shipping the -static.a says consumers are meant to link statically. No regression risk: the package cannot be installed today, so nobody has these binaries. - Swept the build tree rather than fixing the one name in the error: 51 shared libraries are built, 50 reach the buildroot, and libmensia-advanced-visualization.so is the only one that does not. - Found by repoclosure (ci/verify-installed-runtime.sh on aarch64), not by a build. Every openvibe build was green while the package was uninstallable everywhere -- which is the whole reason that check exists. * Thu Sep 24 2026 Morgan Hough - 3.7.0-12 - Finish the Py_GetPath removal. -11 patched only pybox-manager's CPolyBox.cpp because I read the failing file out of the build log, and ninja reports one target at a time; ovpCBoxAlgorithmPython3.cpp had the identical line and failed next. Checked the sources instead of the log this time: seven call sites in five files, of which three are compiled on Linux (all the same debug log line) and four are inside #ifdef TARGET_OS_Windows and left untouched. The sed is now tree-wide and the guard covers all of extras/. * Wed Sep 23 2026 Morgan Hough - 3.7.0-11 - Drop the one use of Py_GetPath(), removed in Python 3.15. It is a debug log line in pybox-manager's CPolyBox.cpp and was the only removed-API reference in the entire build. Not arch-specific; f45-x86_64 would fail identically. * Wed Sep 23 2026 Morgan Hough - 3.7.0-10 - %%prep could not find its source directory. GitLab renamed the openvibe/meta project to "openvibe", and its archive endpoint names the top directory after the project name, so meta-3.7.0.tar.gz now unpacks as openvibe-3.7.0-7de1f013.../ and `%%autosetup -n meta-3.7.0` had nothing to cd into. Unpack with --strip-components=1 into a directory of our own, the way the other three sources here already do, so the next rename cannot break it. * Thu May 28 2026 Morgan Hough - 3.7.0-9 - Finish the Boost 1.87 mbt-smarting cleanup that -8 left half-done. ovasCSmartingAmp.cpp still calls io_context::reset() (removed in 1.87, rename to restart()) and steady_timer::expires_from_now() with a boost::posix_time::milliseconds argument (steady_timer takes std::chrono durations and the expires_from_now() spelling was also removed, use expires_after(std::chrono::milliseconds(...))). Failure surfaced in build 10522031. * Wed May 27 2026 Morgan Hough - 3.7.0-8 - Extend Boost 1.87 io_service→io_context sed to two more files surfaced by build 10517287: extras/contrib/plugins/server-extensions/tcp-tagging/ ovasCTagStream.h and extras/contrib/plugins/server-drivers/mbt-smarting/ src/ovasCSmartingAmp.{h,cpp}. The latter also uses deadline_timer (also removed in 1.87) — rename to steady_timer. * Wed May 27 2026 Morgan Hough - 3.7.0-7 - Add #include to CBoxAlgorithmErpPlot.cpp: GCC 16 / C++20 no longer brings std::none_of in transitively. * Wed May 27 2026 Morgan Hough - 3.7.0-6 - Remove extras/applications/examples/openvibe-to-tcpip in %%prep: uses boost::asio::ip::tcp::resolver::query removed in Boost 1.84+. * Thu Mar 19 2026 Morgan Hough - 3.7.0-5 - Fix install: remove create_symlink install(CODE) blocks that bypass DESTDIR (they create symlinks in /usr/ instead of $DESTDIR/usr/, causing permission errors) * Mon Mar 09 2026 Morgan Hough - 3.7.0-4 - Fix files section: add missing header subdirs (eigen, lsl, mensia, tcptagging) - Fix Boost.Asio: use boost::asio::connect() with resolver results (F44+) - Fix Boost.Filesystem: replace removed extension() free function (F44+) * Fri Mar 06 2026 Morgan Hough - 3.7.0-2 - Fix aarch64 build: make -msse2 flag conditional on x86 - Fix F44+/rawhide: patch Boost io_service to io_context, remove resolver::query * Wed Mar 04 2026 Morgan Hough - 3.7.0-1 - Initial package of OpenViBE 3.7.0 for Fedora