I have been facing problems generating an RPM for a C++ project using MPI (openmpi in my case) , build with cmake on a Rocky9 (virtual) machine. Since RHEL8, MPI distributions are expected to include an extra identifier for MPI to the Requires and Provides sections of a .spec file to mark their specific version.
This is supposed to be done by the rpm-mpi-hooks package. however I can not find any information on how this is supposed to actually run. The RPMs I currently generated give me this error when I try to install
Problem 1: conflicting requests
- nothing provides libmpi.so.40()(64bit) needed by myrpm
as the expected packages have the form of libmpi.so.40()(64bit)(openmpi-x86_64)
but mine requires libmpi.so.40()(64bit)
.
I have found some resources of people facing the same problems here, here, here, and here, which generally point towards the Fedora guidelines towards packaging MPI. I have tried quite a few things, including using the macro's as they are provided in many spots of the .spec file, I have tried renaming the binary to have a -mpi marker at the end, or moving them to a specific MPI directory without success.
Using the guidelines to making a spec-file, I constructed a very simple setup, where the actual code is a tiny HelloWorld C++ code. With a CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(HelloWorld)
add_executable(HWorld main.cxx)
set(CMAKE_INSTALL_PREFIX "/usr")
find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(HWorld ${MPI_C_LIBRARIES} ${MPI_CXX_LIBRARIES})
install(TARGETS HWorld DESTINATION bin)
and a very general .spec file:
Name: HWorld
Version: 1
Release: 1%{?dist}
Summary: Test script with MPI
License: Test
Source0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz
%define debug_package %{nil}
BuildRequires: gcc
BuildRequires: make
%description
%prep
%setup -q
%build
%cmake
%cmake_build
%install
%cmake_install
%files
%{_bindir}/%{name}
%post
%changelog
* ...
This gives me an rpm with the bad mpi requires tag:
$ rpmbuild -bb HWorld.spec
$ rpm -qp --requires HWorld-1-1.el9.x86_64.rpm
...
libmpi.so.40()(64bit)
It is generally best to look for inspiration from something that already exists.
For example, the vtk
package provided by EPEL is built via cmake
and depends on MPI.
Here is a sample CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(helloworld)
add_executable(helloworld main.c)
find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
target_link_libraries(helloworld ${MPI_C_LIBRARIES})
install(TARGETS helloworld DESTINATION bin)
and the spec
file (openmpi
is hardcoded, you generally want to build a spec
file that works for both mpich
and openmpi
Name: helloworld
Version: 1.0
Release: 1%{?dist}
Summary: Test script with MPI
License: Test
Source0: https://www.example.com/%{name}/releases/helloworld-%{version}.tar.gz
%define debug_package %{nil}
BuildRequires: gcc
BuildRequires: cmake
%description
%prep
%setup -q
%build
%global _vpath_builddir build-openmpi
%_openmpi_load
%cmake
%cmake \
-DCMAKE_PREFIX_PATH:PATH=$MPI_HOME \
-DCMAKE_INSTALL_PREFIX:PATH=$MPI_HOME
%cmake_build
%install
%cmake_install
%package openmpi
BuildRequires: openmpi-devel
Summary: binaries built with openmpi
%description openmpi
%files openmpi
%{_libdir}/openmpi/bin/%{name}
and here are the requirements of the helloworld-openmpi
package:
$ rpm -qpR RPMS/aarch64/helloworld-openmpi-1.0-1.el9.aarch64.rpm
libc.so.6()(64bit)
libc.so.6(GLIBC_2.17)(64bit)
libc.so.6(GLIBC_2.34)(64bit)
libmpi.so.40()(64bit)(openmpi-aarch64)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsZstd) <= 5.4.18-1
rtld(GNU_HASH)