Spdk/rpmbuild/rpm.sh

209 lines
5.7 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2021 Intel Corporation
# All rights reserved.
#
set -e
specdir=$(readlink -f "$(dirname "$0")")
rootdir=$(readlink -f "$specdir/../")
[[ -e /etc/os-release ]]
source /etc/os-release
id_ok=no
for id in $ID $ID_LIKE; do
[[ "$id" =~ ^(fedora|centos|rhel) ]] && id_ok=yes
done
if [[ "$id_ok" != "yes" ]]; then
printf '%s not supported\n' "$ID" >&2
exit 1
fi
get_config() {
# Intercept part of the ./configure's cmdline we are interested in
configure_opts=($(getopt -l "$1::" -o "" -- $configure 2> /dev/null)) || true
# If "--" is the first argument then either the cmdline is empty or doesn't
# match on what we are looking for. In either case simply return as there
# is nothing to check.
[[ ${configure_opts[0]} == "--" ]] && return 1
if [[ $2 == has-arg ]]; then
[[ -n ${configure_opts[1]} && ${configure_opts[1]} != "''" ]]
elif [[ $2 == print ]]; then
echo "${configure_opts[1]//\'/}"
fi
}
fedora_python_sys_path_workaround() {
[[ -z $NO_WORKAROUND ]] || return 0
# Fedora builds its python version with a patch which attempts to remove all
# "/usr/local" paths from sys.path in case it's run under RPM environment,
# i.e., when RPM_BUILD_ROOT variable is detected. This particular variable
# is set by the rpmbuild when it executes its sh wrappers built out of the
# .spec file.
# This is problematic in case meson and ninja were installed via rooted pip
# which had its working directory set to /usr/local. As a result, when the
# SPDK executes meson to build DPDK, from rpmbuild env, it fails as
# it's not able to find its mesonbuild module.
# To workaround this little hiccup we fetch the entire sys.path list and
# then export it via PYTHONPATH so when rpmbuild kicks in, python will be
# able to find all the modules regardless if the RPM_BUILD_ROOT is set or
# not.
# FIXME: The alternative is to unset RPM_BUILD_ROOT directly in the spec?
# It does work but it feels wrong.
PYTHONPATH="$(python3 -c "import sys; print('%s' % ':'.join(sys.path)[1:])")"
export PYTHONPATH
}
get_version() {
local version
version=$(git -C "$rootdir" describe --tags --abbrev=0)
echo "${version%%-*}"
}
build_macros() {
local -g macros=()
local dir _dir
macros+=(-D "configure ${configure:-"%{nil}"}")
macros+=(-D "make $make")
macros+=(-D "release $release")
macros+=(-D "version $version")
# Adjust dir macros to update the final location of the RPMS
for dir in build buildroot rpm source spec srcrpm; do
_dir=$(rpm --eval "%{_${dir}dir}")
if [[ -z $USE_DEFAULT_DIRS ]]; then
macros+=(-D "_${dir}dir $rpmbuild_dir/$dir")
_dir=$rpmbuild_dir/$dir
fi
local -g "_${dir}dir=$_dir"
done
if get_config with-shared; then
macros+=(-D "shared 1")
macros+=(-D "dpdk 1")
fi
if get_config with-dpdk; then
if ! get_config with-dpdk has-arg; then
# spdk is requested to build against installed dpdk (i.e. provided by the dist).
# Don't build dpdk rpm rather define proper requirements for the spdk.
macros+=(-D "dpdk 0")
macros+=(-D "shared 1")
# This maps how Epoch is used inside dpdk packages across different distros. It's
# mainly relevant when comparing version of required packages. Default maps to 0.
local -A dpdk_rpm_epoch["fedora"]=2
local dpdk_version_min=${dpdk_rpm_epoch["$ID"]:-0}:20.11
local dpdk_req="dpdk-devel >= $dpdk_version_min"
requirements=${requirements:+$requirements, }"$dpdk_req"
build_requirements=${build_requirements:+$build_requirements, }"$dpdk_req"
else
dpdk_build_path=$(get_config with-dpdk print)
dpdk_path=$(dirname "$dpdk_build_path")
macros+=(-D "dpdk_build_path $dpdk_build_path")
macros+=(-D "dpdk_path $dpdk_path")
fi
fi
if get_config with-rbd; then
macros+=(-D "rbd 1")
requirements=${requirements:+$requirements, }"librados2, librbd1"
build_requirements=${build_requirements:+$build_requirements, }"librados-devel, librbd-devel"
fi
if get_config libdir has-arg; then
macros+=(-D "libdir $(get_config libdir print)")
fi
if get_config with-vfio-user; then
macros+=(-D "vfio_user 1")
fi
if [[ $deps == no ]]; then
macros+=(-D "deps 0")
fi
if [[ -n $requirements ]]; then
macros+=(-D "requirements 1")
macros+=(-D "requirements_list $requirements")
fi
if [[ -n $build_requirements ]]; then
macros+=(-D "build_requirements 1")
macros+=(-D "build_requirements_list $build_requirements")
fi
build_macros_flags
}
build_macros_flags() {
local flags flag
flags=(CFLAGS CXXFLAGS LDFLAGS)
for flag in "${flags[@]}"; do
# If we are running in the environment where the flag is set, don't touch it -
# rpmbuild will use it as is during the build. If it's not set, make sure the
# rpmbuild won't set its defaults which may affect the build in an unpredictable
# manner.
[[ -n ${!flag} ]] && continue
macros+=(-D "build_${flag,,} %{nil}")
done
}
gen_spec() {
rpmspec "${macros[@]}" -P "$spec"
}
build_rpm() (
fedora_python_sys_path_workaround
mkdir -p \
"$_builddir" \
"$_buildrootdir" \
"$_rpmdir" \
"$_sourcedir" \
"$_specdir" \
"$_srcrpmdir"
# Despite building in-place, rpmbuild still looks under %{_sourcedir} as defined
# in Source:. Create a dummy file to fulfil its needs and to keep Source in
# the .spec.
: > "$_sourcedir/spdk-$version.tar.gz"
cd "$rootdir"
printf '* Starting rpmbuild...\n'
rpmbuild --clean --nodebuginfo "${macros[@]}" --build-in-place -ba "$spec"
)
# .spec defaults
configure=$*
deps=${DEPS:-yes}
make="${MAKEFLAGS:--j $(nproc)}"
release=${RPM_RELEASE:-1}
requirements=${REQUIREMENTS:-}
build_requirements=${BUILD_REQUIREMENTS:-}
version=${SPDK_VERSION:-$(get_version)}
rpmbuild_dir=${BUILDDIR:-"$HOME/rpmbuild"}
spec=$specdir/spdk.spec
build_macros
if [[ -n $GEN_SPEC ]]; then
gen_spec
exit 0
fi
build_rpm