1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2021 Intel Corporation 4# All rights reserved. 5# 6 7set -e 8 9specdir=$(readlink -f "$(dirname "$0")") 10rootdir=$(readlink -f "$specdir/../") 11 12[[ -e /etc/os-release ]] 13source /etc/os-release 14 15id_ok=no 16 17for id in $ID $ID_LIKE; do 18 [[ "$id" =~ ^(fedora|centos|rhel) ]] && id_ok=yes 19done 20 21if [[ "$id_ok" != "yes" ]]; then 22 printf '%s not supported\n' "$ID" >&2 23 exit 1 24fi 25 26get_config() { 27 # Intercept part of the ./configure's cmdline we are interested in 28 configure_opts=($(getopt -l "$1::" -o "" -- $configure 2> /dev/null)) || true 29 # If "--" is the first argument then either the cmdline is empty or doesn't 30 # match on what we are looking for. In either case simply return as there 31 # is nothing to check. 32 [[ ${configure_opts[0]} == "--" ]] && return 1 33 34 if [[ $2 == has-arg ]]; then 35 [[ -n ${configure_opts[1]} && ${configure_opts[1]} != "''" ]] 36 elif [[ $2 == print ]]; then 37 echo "${configure_opts[1]//\'/}" 38 fi 39} 40 41fedora_python_sys_path_workaround() { 42 [[ -z $NO_WORKAROUND ]] || return 0 43 44 # Fedora builds its python version with a patch which attempts to remove all 45 # "/usr/local" paths from sys.path in case it's run under RPM environment, 46 # i.e., when RPM_BUILD_ROOT variable is detected. This particular variable 47 # is set by the rpmbuild when it executes its sh wrappers built out of the 48 # .spec file. 49 50 # This is problematic in case meson and ninja were installed via rooted pip 51 # which had its working directory set to /usr/local. As a result, when the 52 # SPDK executes meson to build DPDK, from rpmbuild env, it fails as 53 # it's not able to find its mesonbuild module. 54 55 # To workaround this little hiccup we fetch the entire sys.path list and 56 # then export it via PYTHONPATH so when rpmbuild kicks in, python will be 57 # able to find all the modules regardless if the RPM_BUILD_ROOT is set or 58 # not. 59 # FIXME: The alternative is to unset RPM_BUILD_ROOT directly in the spec? 60 # It does work but it feels wrong. 61 62 PYTHONPATH="$(python3 -c "import sys; print('%s' % ':'.join(sys.path)[1:])")" 63 export PYTHONPATH 64} 65 66get_version() { 67 local version 68 version=$(git -C "$rootdir" describe --tags --abbrev=0) 69 70 echo "${version%%-*}" 71} 72 73build_macros() { 74 local -g macros=() 75 local dir _dir dpdk_req 76 77 macros+=(-D "configure ${configure:-"%{nil}"}") 78 macros+=(-D "make $make") 79 macros+=(-D "release $release") 80 macros+=(-D "version $version") 81 82 # Adjust dir macros to update the final location of the RPMS 83 for dir in build buildroot rpm source spec srcrpm; do 84 _dir=$(rpm --eval "%{_${dir}dir}") 85 if [[ -z $USE_DEFAULT_DIRS ]]; then 86 macros+=(-D "_${dir}dir $rpmbuild_dir/$dir") 87 _dir=$rpmbuild_dir/$dir 88 fi 89 local -g "_${dir}dir=$_dir" 90 done 91 92 if get_config with-shared; then 93 macros+=(-D "shared 1") 94 fi 95 96 if get_config with-dpdk; then 97 # spdk is requested to build against installed dpdk (i.e. provided by the dist). 98 # Don't build dpdk rpm rather define proper requirements for the spdk. 99 dpdk_req="dpdk-devel >= 22.11" 100 macros+=(-D "dpdk 0") 101 requirements=${requirements:+$requirements, }"$dpdk_req" 102 build_requirements=${build_requirements:+$build_requirements, }"$dpdk_req" 103 else 104 macros+=(-D "dpdk 1") 105 fi 106 107 if get_config with-fio; then 108 macros+=(-D "fio 1") 109 fi 110 111 if get_config with-rbd; then 112 macros+=(-D "rbd 1") 113 requirements=${requirements:+$requirements, }"librados2, librbd1" 114 build_requirements=${build_requirements:+$build_requirements, }"librados-devel, librbd-devel" 115 fi 116 117 if get_config libdir has-arg; then 118 macros+=(-D "libdir $(get_config libdir print)") 119 fi 120 121 if get_config with-vfio-user; then 122 macros+=(-D "vfio_user 1") 123 fi 124 125 if [[ $deps == no ]]; then 126 macros+=(-D "deps 0") 127 fi 128 129 if [[ -n $requirements ]]; then 130 macros+=(-D "requirements 1") 131 macros+=(-D "requirements_list $requirements") 132 fi 133 134 if [[ -n $build_requirements ]]; then 135 macros+=(-D "build_requirements 1") 136 macros+=(-D "build_requirements_list $build_requirements") 137 fi 138 139 build_macros_flags 140} 141 142build_macros_flags() { 143 local flags flag 144 145 flags=(CFLAGS CXXFLAGS LDFLAGS) 146 147 for flag in "${flags[@]}"; do 148 # If we are running in the environment where the flag is set, don't touch it - 149 # rpmbuild will use it as is during the build. If it's not set, make sure the 150 # rpmbuild won't set its defaults which may affect the build in an unpredictable 151 # manner. 152 [[ -n ${!flag} ]] && continue 153 macros+=(-D "build_${flag,,} %{nil}") 154 done 155} 156 157gen_spec() { 158 rpmspec "${macros[@]}" -P "$spec" 159} 160 161build_rpm() ( 162 fedora_python_sys_path_workaround 163 164 mkdir -p \ 165 "$_builddir" \ 166 "$_buildrootdir" \ 167 "$_rpmdir" \ 168 "$_sourcedir" \ 169 "$_specdir" \ 170 "$_srcrpmdir" 171 172 # Despite building in-place, rpmbuild still looks under %{_sourcedir} as defined 173 # in Source:. Create a dummy file to fulfil its needs and to keep Source in 174 # the .spec. 175 : > "$_sourcedir/spdk-$version.tar.gz" 176 177 cd "$rootdir" 178 179 printf '* Starting rpmbuild...\n' 180 rpmbuild --clean --nodebuginfo "${macros[@]}" --build-in-place -ba "$spec" 181) 182 183# .spec defaults 184configure=$* 185deps=${DEPS:-yes} 186make="${MAKEFLAGS:--j $(nproc)}" 187release=${RPM_RELEASE:-1} 188requirements=${REQUIREMENTS:-} 189build_requirements=${BUILD_REQUIREMENTS:-} 190version=${SPDK_VERSION:-$(get_version)} 191 192rpmbuild_dir=${BUILDDIR:-"$HOME/rpmbuild"} 193spec=$specdir/spdk.spec 194 195build_macros 196if [[ -n $GEN_SPEC ]]; then 197 gen_spec 198 exit 0 199fi 200build_rpm 201