diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7eef87b --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Sandro Mani + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/mpi.attrs b/mpi.attrs new file mode 100644 index 0000000..05064d7 --- /dev/null +++ b/mpi.attrs @@ -0,0 +1,5 @@ +%__mpi_provides %{_rpmconfigdir}/mpi.prov %{buildroot} %{?__filter_GLIBC_PRIVATE:--filter-private} +%__mpi_requires %{_rpmconfigdir}/mpi.req %{buildroot} %{?__filter_GLIBC_PRIVATE:--filter-private} +%__mpi_path ^%{_prefix}/lib(64)?/(openmpi|mpich)/.*$ +%__elf_exclude_path ^%{_prefix}/lib(64)?/(openmpi|mpich)/.*$ +%__libsymlink_exclude_path ^%{_prefix}/lib(64)?/(openmpi|mpich)/.*$ diff --git a/mpi.prov b/mpi.prov new file mode 100755 index 0000000..08bd807 --- /dev/null +++ b/mpi.prov @@ -0,0 +1,83 @@ +#!/bin/bash + +# Copyright (c) 2015 Sandro Mani +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE + + +# First argument is buildroot +buildroot="$1" +if [ ! -d "$buildroot" ]; then + >&2 echo "Invalid buildroot" + exit 1 +fi + +# Second argument can be --filter-private +filterprivate= +if [ "$2" == "--filter-private" ]; then + filterprivate="--filter-private" +fi + +# Search for all MPI implementations: +# - Search all modules which start with mpi +# - For each module, store $MPI_HOME -> $MPI_COMPILER in assoc. array +declare -A mpi_compier_for_home +if [ -e /etc/profile.d/modules.sh ]; then + . /etc/profile.d/modules.sh; + + # Add moduledirs in buildroot also for cases where an MPI implementation + # package is being built, meaning that its module files are not yet installed + IFS=':' read -ra _MODULEPATH <<< "$MODULEPATH" + for i in "${!_MODULEPATH[@]}"; do + _MODULEPATH[$i]=$buildroot${_MODULEPATH[$i]} + done + export MODULEPATH="$MODULEPATH:$(IFS=:; echo "${_MODULEPATH[*]}")" + + for module in $(module -t avail 2>&1 | grep "^mpi/"); do + module load $module + mpi_compier_for_home[${MPI_HOME}]=${MPI_COMPILER} + module unload $module + done +fi + +# Read file list from stdin +filelist=$(sed "s/['\"]/\\\&/g") + +# List provides: +if [ -x /usr/lib/rpm/elfdeps -a -n "$filelist" ]; then + for file in $(echo $filelist | tr '[:blank:]' \\n); do + + # Get the default provides string from elfdeps + prov=$(echo $file | /usr/lib/rpm/elfdeps --provides $filterprivate) + if [ -z $prov ]; then + continue + fi + + # If the path to the scanned binary starts with an $MPI_HOME, append the + # corresponding ($MPI_COMPILER) to the provides string + for mpi_home in "${!mpi_compier_for_home[@]}"; do + if [[ "$file" == "$buildroot$mpi_home"* ]]; then + prov="${prov}(${mpi_compier_for_home[$mpi_home]})" + break + fi + done + + echo "$prov" + done +fi diff --git a/mpi.req b/mpi.req new file mode 100755 index 0000000..de0e2cd --- /dev/null +++ b/mpi.req @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright (c) 2015 Sandro Mani +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE + + +# First argument is buildroot +buildroot="$1" +if [ ! -d "$buildroot" ]; then + >&2 echo "Invalid buildroot" + exit 1 +fi + +# Second argument can be --filter-private +filterprivate= +if [ "$1" == "--filter-private" ]; then + filterprivate="--filter-private" +fi + +# Search for all MPI implementations: +# - Search all modules which start with mpi +# - For each module, store $MPI_HOME -> $MPI_COMPILER and +# $MPI_COMPILER -> $MPI_LIB in assoc. array +declare -A mpi_compier_for_home +declare -A mpi_lib_for_compiler +if [ -e /etc/profile.d/modules.sh ]; then + . /etc/profile.d/modules.sh; + + # Add moduledirs in buildroot also for cases where an MPI implementation + # package is being built, meaning that its module files are not yet installed + IFS=':' read -ra _MODULEPATH <<< "$MODULEPATH" + for i in "${!_MODULEPATH[@]}"; do + _MODULEPATH[$i]=$buildroot${_MODULEPATH[$i]} + done + export MODULEPATH="$MODULEPATH:$(IFS=:; echo "${_MODULEPATH[*]}")" + + for module in $(module -t avail 2>&1 | grep "^mpi/"); do + module load $module + mpi_compier_for_home[${MPI_HOME}]=${MPI_COMPILER} + mpi_lib_for_compiler[${MPI_COMPILER}]=${MPI_LIB} + module unload $module + done +fi + +# Read file list from stdin +filelist=`sed "s/[]['\"*?{}]/\\\\\&/g"` + +# List requires: +if [ -x /usr/lib/rpm/elfdeps -a -n "$filelist" ]; then + for file in $(echo $filelist | tr '[:blank:]' \\n); do + + # Get the default requres string from elfdeps + reqs=$(echo $file | /usr/lib/rpm/elfdeps --requires $filterprivate) + + # Check whether the scanned binary is inside an $MPI_HOME dir + mpi_comp= + for mpi_home in "${!mpi_compier_for_home[@]}"; do + if [[ "$file" == "$buildroot$mpi_home"* ]]; then + mpi_comp="${mpi_compier_for_home[$mpi_home]}" + break + fi + done + + # If the scanned binary is inside an $MPI_HOME, for each dependency, check + # whether the library exists in $MPI_LIB, and if yes, append + # ($MPI_COMPILER) to each requires string + if [ ! -z $mpi_comp ]; then + mpi_lib=${mpi_lib_for_compiler[$mpi_comp]} + for req in $reqs; do + lib=$(echo $req | grep -Eo '^.*\.so[^(]*') + if [ ! -z $lib ] && ( [ -e $mpi_lib/$lib ] || [ -e $buildroot$mpi_lib/$lib ] ); then + req="${req}($mpi_comp)" + fi + echo "$req" + done + else + echo "$reqs" + fi + done +fi diff --git a/rpm-mpi-hooks.spec b/rpm-mpi-hooks.spec new file mode 100644 index 0000000..d59c93b --- /dev/null +++ b/rpm-mpi-hooks.spec @@ -0,0 +1,60 @@ +Name: rpm-mpi-hooks +Version: 1.0 +Release: 4%{?dist} +Summary: RPM dependency generator hooks for MPI packages + +License: MIT +BuildArch: noarch + +Source0: mpi.attrs +Source1: mpi.prov +Source2: mpi.req +Source3: LICENSE + +Requires: filesystem +Requires: rpm-build +# Instead of adding a BuildRequires to every MPI implementation spec +Requires: environment-modules + +%description +RPM dependency generator hooks for MPI packages. This package should be added +as a BuildRequires to all mpi implementations (i.e. openmpi, mpich) as well as +a Requires to the their -devel packages. + + +%prep +cp -a %SOURCE3 . + + +%build +# Nothing to build + + +%install +install -Dpm 0644 %{SOURCE0} %{buildroot}%{_rpmconfigdir}/fileattrs/mpi.attr +install -Dpm 0755 %{SOURCE1} %{buildroot}%{_rpmconfigdir}/mpi.prov +install -Dpm 0755 %{SOURCE2} %{buildroot}%{_rpmconfigdir}/mpi.req + + +%files +%license LICENSE +%{_rpmconfigdir}/fileattrs/mpi.attr +%{_rpmconfigdir}/mpi.req +%{_rpmconfigdir}/mpi.prov + + +%changelog +* Thu Jul 09 2015 Sandro Mani 1.0-4 +- mpi.prov, mpi.req: Use "module -t avail" instead of "module avail" +- mpi.prov, mpi.req: Also look in moduledirs in %%buildroot +- mpi.attrs: add %%__libsymlink_exclude_path + +* Thu Jul 09 2015 Sandro Mani 1.0-3 +- Add LICENSE + +* Thu Jul 09 2015 Sandro Mani 1.0-2 +- BuildRequires: rpm -> rpm-build +- Change license to MIT + +* Thu Jul 09 2015 Sandro Mani 1.0-1 +- Initial package