xref: /spdk/scripts/pkgdep/common.sh (revision 60982c759db49b4f4579f16e3b24df0725ba4b94)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2020 Intel Corporation
4#  All rights reserved.
5#
6install_liburing() {
7	local GIT_REPO_LIBURING=https://github.com/axboe/liburing.git
8	local liburing_dir=/usr/local/src/liburing
9
10	if [[ -d $liburing_dir ]]; then
11		echo "liburing source already present, not cloning"
12	else
13		mkdir -p $liburing_dir
14		git clone "${GIT_REPO_LIBURING}" "$liburing_dir"
15	fi
16	# Use commit we know we can compile against. See #1673 as a reference.
17	git -C "$liburing_dir" checkout liburing-2.2
18	(cd "$liburing_dir" && ./configure --libdir=/usr/lib64 --libdevdir=/usr/lib64 && make install)
19	echo /usr/lib64 > /etc/ld.so.conf.d/spdk-liburing.conf
20	ldconfig
21}
22
23install_shfmt() {
24	# Fetch version that has been tested
25	local shfmt_version=3.1.0
26	local shfmt=shfmt-$shfmt_version
27	local shfmt_dir=${SHFMT_DIR:-/opt/shfmt}
28	local shfmt_dir_out=${SHFMT_DIR_OUT:-/usr/bin}
29	local shfmt_url
30	local os
31	local arch
32
33	if hash "$shfmt" && [[ $("$shfmt" --version) == "v$shfmt_version" ]]; then
34		echo "$shfmt already installed"
35		return 0
36	fi 2> /dev/null
37
38	arch=$(uname -m)
39	os=$(uname -s)
40
41	case "$arch" in
42		x86_64) arch="amd64" ;;
43		aarch64) arch="arm" ;;
44		*)
45			echo "Not supported arch (${arch:-Unknown}), skipping"
46			return 0
47			;;
48	esac
49
50	case "$os" in
51		Linux) shfmt_url=https://github.com/mvdan/sh/releases/download/v$shfmt_version/shfmt_v${shfmt_version}_linux_${arch} ;;
52		FreeBSD) shfmt_url=https://github.com/mvdan/sh/releases/download/v$shfmt_version/shfmt_v${shfmt_version}_freebsd_${arch} ;;
53		*)
54			echo "Not supported OS (${os:-Unknown}), skipping"
55			return 0
56			;;
57	esac
58
59	mkdir -p "$shfmt_dir"
60	mkdir -p "$shfmt_dir_out"
61
62	echo "Fetching ${shfmt_url##*/}"...
63	local err
64	if err=$(curl -f -Lo"$shfmt_dir/$shfmt" "$shfmt_url" 2>&1); then
65		chmod +x "$shfmt_dir/$shfmt"
66		ln -sf "$shfmt_dir/$shfmt" "$shfmt_dir_out"
67	else
68		cat <<- CURL_ERR
69
70			* Fetching $shfmt_url failed, $shfmt will not be available for format check.
71			* Error:
72
73			$err
74
75		CURL_ERR
76		return 0
77	fi
78	echo "$shfmt installed"
79}
80
81install_spdk_bash_completion() {
82	[[ -e /usr/share/bash-completion/bash_completion ]] || return 0
83
84	local compat_dir=/etc/bash_completion.d
85	mkdir -p "$compat_dir"
86
87	if [[ ! -e $compat_dir/spdk ]]; then
88		cp -v "$scriptsdir/bash-completion/spdk" "$compat_dir"
89	fi
90}
91
92install_markdownlint() {
93	local git_repo_mdl="https://github.com/markdownlint/markdownlint.git"
94	local mdl_version="v0.11.0"
95	if [ ! -d /usr/src/markdownlint ]; then
96		sudo -E git clone --branch "$mdl_version" "$git_repo_mdl" "/usr/src/markdownlint"
97		(
98			cd /usr/src/markdownlint
99			if ! hash rake &> /dev/null; then
100				sudo -E gem install rake
101			fi
102			if ! hash bundler &> /dev/null; then
103				sudo -E gem install bundler
104			fi
105			sudo -E rake install
106		)
107	else
108		echo "Markdown lint tool already in /usr/src/markdownlint. Not installing"
109	fi
110}
111
112version-at-least() {
113	local atleastver="$1"
114	local askver="$2"
115	local smallest
116	smallest=$(echo -e "${atleastver}\n${askver}" | sort -V | head -n 1)
117	[[ "${smallest}" == "${atleastver}" ]]
118}
119
120install_protoc() {
121	local PROTOCVERSION=${PROTOCVERSION:-21.7}
122	local PROTOCGENGOVERSION=${PROTOCGENGOVERSION:-1.28}
123	local PROTOCGENGOGRPCVERSION=${PROTOCGENGOGRPCVERSION:-1.2}
124	local protocdir protocpkg protocurl protocver arch
125	local skip_protoc=0
126	# It is easy to find an incompatible combination of protoc,
127	# protoc-gen-go and protoc-gen-go-grpc. Therefore install a
128	# preferred version combination even if more recent versions
129	# of some of these tools would be available in the system.
130	protocver=$(protoc --version 2> /dev/null | {
131		read -r _ v
132		echo $v
133	})
134	if [[ "3.${PROTOCVERSION}" == "${protocver}" ]]; then
135		echo "found protoc version ${protocver} exactly required 3.${PROTOCVERSION}, skip installing"
136		skip_protoc=1
137	fi
138	protocdir=/opt/protoc/${PROTOCVERSION}
139	if [[ -x "${protocdir}/bin/protoc" ]]; then
140		echo "protoc already installed to ${protocdir}, skip installing"
141		skip_protoc=1
142	fi
143	if [[ "${skip_protoc}" != "1" ]]; then
144		echo "installing protoc v${PROTOCVERSION} to ${protocdir}"
145		mkdir -p "${protocdir}"
146		arch=x86_64
147		if [[ "$(arch)" == "aarch64" ]]; then
148			arch=aarch_64
149		fi
150		protocpkg=protoc-${PROTOCVERSION}-linux-${arch}.zip
151		protocurl=https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOCVERSION}/${protocpkg}
152		curl -f -LO "${protocurl}" || {
153			echo "downloading protoc ${PROTOCVERSION} from ${protocurl} failed"
154			return 1
155		}
156		unzip -d "${protocdir}" "${protocpkg}" || {
157			echo "extracting protoc ${PROTOCVERSION} from ${protocpkg} failed"
158			rm -f "${protocpkg}"
159			return 1
160		}
161		rm -f "${protocpkg}"
162	fi
163	if [[ -x "${protocdir}/bin/protoc-gen-go" ]]; then
164		echo "${protocdir}/bin/protoc-gen-go already installed"
165	else
166		echo "installing protoc-gen-go v${PROTOCGENGOVERSION} to ${protocdir}/bin"
167		mkdir -p "${protocdir}/bin"
168		GOBIN="${protocdir}/bin" go install "google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOCGENGOVERSION}" || {
169			echo "protoc protoc-gen-go plugin install failed"
170			return 1
171		}
172	fi
173	if [[ -x "${protocdir}/bin/protoc-gen-go-grpc" ]]; then
174		echo "${protocdir}/bin/protoc-gen-go-grpc already installed"
175	else
176		echo "installing protoc-gen-go-grpc v${PROTOCGENGOGRPCVERSION} to ${protocdir}/bin"
177		mkdir -p "${protocdir}/bin"
178		GOBIN="${protocdir}/bin" go install "google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${PROTOCGENGOGRPCVERSION}" || {
179			echo "protoc protoc-gen-go-grpc plugin install failed"
180			return 1
181		}
182	fi
183	pkgdep_toolpath protoc "${protocdir}/bin"
184}
185
186install_golang() {
187	local GOVERSION=${GOVERSION:-1.19}
188	local godir gopkg gover arch
189	gover=$(go version 2> /dev/null | {
190		read -r _ _ v _
191		echo ${v#go}
192	})
193	if [[ -n "${gover}" ]] && version-at-least "${GOVERSION}" "${gover}"; then
194		echo "found go version ${gover} >= required ${GOVERSION}, skip installing"
195		return 0
196	fi
197	godir=/opt/go/${GOVERSION}
198	if [[ -x "${godir}/bin/go" ]]; then
199		echo "go already installed in ${godir}, skip installing"
200		return 0
201	fi
202	mkdir -p "${godir}"
203	arch=amd64
204	if [[ "$(arch)" == "aarch64" ]]; then
205		arch=arm64
206	fi
207	gopkg=go${GOVERSION}.linux-${arch}.tar.gz
208	echo "installing go v${GOVERSION} to ${godir}/bin"
209	curl -s https://dl.google.com/go/${gopkg} | tar -C "${godir}" -xzf - --strip 1
210	${godir}/bin/go version || {
211		echo "go install failed"
212		return 1
213	}
214	export PATH=${godir}/bin:$PATH
215	export GOBIN=${godir}/bin
216	pkgdep_toolpath go "${godir}/bin"
217}
218
219pkgdep_toolpath() {
220	# Usage: pkgdep_toolpath TOOL DIR
221	#
222	# Regenerates /etc/opt/spdk-pkgdep/paths to ensure that
223	# TOOL in DIR will be in PATH before other versions
224	# of the TOOL installed in the system.
225	local toolname="$1"
226	local toolpath="$2"
227	local toolpath_dir="/etc/opt/spdk-pkgdep/paths"
228	local toolpath_file="${toolpath_dir}/${toolname}.path"
229	local export_file="${toolpath_dir}/export.sh"
230	mkdir -p "$(dirname "${toolpath_file}")"
231	echo "${toolpath}" > "${toolpath_file}" || {
232		echo "cannot write toolpath ${toolpath} to ${toolpath_file}"
233		return 1
234	}
235	echo "# generated, source this file in shell" > "${export_file}"
236	for pathfile in "${toolpath_dir}"/*.path; do
237		echo "PATH=$(< ${pathfile}):\$PATH" >> "${export_file}"
238	done
239	echo "export PATH" >> "${export_file}"
240	echo "echo \$PATH" >> "${export_file}"
241	chmod a+x "${export_file}"
242}
243
244if [[ $INSTALL_DEV_TOOLS == true ]]; then
245	install_shfmt
246	install_spdk_bash_completion
247	if [[ $ID != centos && $ID != rocky && $ID != sles ]]; then
248		install_markdownlint
249	else
250		echo "mdl not supported on $ID, disabling"
251	fi
252fi
253
254if [[ $INSTALL_LIBURING == true ]]; then
255	install_liburing
256fi
257
258if [[ $INSTALL_GOLANG == true ]]; then
259	install_golang
260	install_protoc
261fi
262