xref: /spdk/scripts/pkgdep/common.sh (revision 167ad6fb3ade0a58da32b6d09824aae4d3e2c79f)
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
112install_protoc() {
113	local PROTOCVERSION=${PROTOCVERSION:-21.7}
114	local PROTOCGENGOVERSION=${PROTOCGENGOVERSION:-1.28}
115	local PROTOCGENGOGRPCVERSION=${PROTOCGENGOGRPCVERSION:-1.2}
116	local protocdir protocpkg protocurl protocver arch
117	local skip_protoc=0
118	# It is easy to find an incompatible combination of protoc,
119	# protoc-gen-go and protoc-gen-go-grpc. Therefore install a
120	# preferred version combination even if more recent versions
121	# of some of these tools would be available in the system.
122	protocver=$(protoc --version 2> /dev/null | {
123		read -r _ v
124		echo $v
125	})
126	if [[ "3.${PROTOCVERSION}" == "${protocver}" ]]; then
127		echo "found protoc version ${protocver} exactly required 3.${PROTOCVERSION}, skip installing"
128		skip_protoc=1
129	fi
130	protocdir=/opt/protoc/${PROTOCVERSION}
131	if [[ -x "${protocdir}/bin/protoc" ]]; then
132		echo "protoc already installed to ${protocdir}, skip installing"
133		skip_protoc=1
134	fi
135	if [[ "${skip_protoc}" != "1" ]]; then
136		echo "installing protoc v${PROTOCVERSION} to ${protocdir}"
137		mkdir -p "${protocdir}"
138		arch=x86_64
139		if [[ "$(arch)" == "aarch64" ]]; then
140			arch=aarch_64
141		fi
142		protocpkg=protoc-${PROTOCVERSION}-linux-${arch}.zip
143		protocurl=https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOCVERSION}/${protocpkg}
144		curl -f -LO "${protocurl}" || {
145			echo "downloading protoc ${PROTOCVERSION} from ${protocurl} failed"
146			return 1
147		}
148		unzip -d "${protocdir}" "${protocpkg}" || {
149			echo "extracting protoc ${PROTOCVERSION} from ${protocpkg} failed"
150			rm -f "${protocpkg}"
151			return 1
152		}
153		rm -f "${protocpkg}"
154	fi
155	if [[ -x "${protocdir}/bin/protoc-gen-go" ]]; then
156		echo "${protocdir}/bin/protoc-gen-go already installed"
157	else
158		echo "installing protoc-gen-go v${PROTOCGENGOVERSION} to ${protocdir}/bin"
159		mkdir -p "${protocdir}/bin"
160		GOBIN="${protocdir}/bin" go install "google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOCGENGOVERSION}" || {
161			echo "protoc protoc-gen-go plugin install failed"
162			return 1
163		}
164	fi
165	if [[ -x "${protocdir}/bin/protoc-gen-go-grpc" ]]; then
166		echo "${protocdir}/bin/protoc-gen-go-grpc already installed"
167	else
168		echo "installing protoc-gen-go-grpc v${PROTOCGENGOGRPCVERSION} to ${protocdir}/bin"
169		mkdir -p "${protocdir}/bin"
170		GOBIN="${protocdir}/bin" go install "google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${PROTOCGENGOGRPCVERSION}" || {
171			echo "protoc protoc-gen-go-grpc plugin install failed"
172			return 1
173		}
174	fi
175	pkgdep_toolpath protoc "${protocdir}/bin"
176}
177
178install_golang() {
179	local GOVERSION=${GOVERSION:-1.21.1}
180	local godir gopkg gover arch
181
182	read -r _ _ gover _ < <(go version) || true
183	gover=${gover#go}
184	if [[ -n "${gover}" ]] && ge "${gover}" "${GOVERSION}"; then
185		echo "found go version ${gover} >= required ${GOVERSION}, skip installing"
186		return 0
187	fi
188	godir=/opt/go/${GOVERSION}
189	if [[ -x "${godir}/bin/go" ]]; then
190		echo "go already installed in ${godir}, skip installing"
191		return 0
192	fi
193	mkdir -p "${godir}"
194	arch=amd64
195	if [[ "$(arch)" == "aarch64" ]]; then
196		arch=arm64
197	fi
198	gopkg=go${GOVERSION}.linux-${arch}.tar.gz
199	echo "installing go v${GOVERSION} to ${godir}/bin"
200	curl -sL https://go.dev/dl/${gopkg} | tar -C "${godir}" -xzf - --strip 1
201	if ! "${godir}/bin/go" version; then
202		echo "go install failed"
203		return 1
204	fi
205	export PATH=${godir}/bin:$PATH
206	export GOBIN=${godir}/bin
207	pkgdep_toolpath go "${godir}/bin"
208}
209
210install_golangci_lint() {
211	local golangcidir installed_lintversion lintversion=${GOLANGCLILINTVERSION:-1.54.2}
212	installed_lintversion=$(golangci-lint --version | awk '{print $4}')
213
214	if [[ -n "${installed_lintversion}" ]] && ge "${installed_lintversion}" "${lintversion}"; then
215		echo "golangci-lint already installed, skip installing"
216		return 0
217	fi
218
219	echo "installing golangci-lint"
220	golangcidir=/opt/golangci/$lintversion/bin
221	export PATH=${golangcidir}:$PATH
222	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v${lintversion}/install.sh \
223		| sh -s -- -b "${golangcidir}" || {
224		echo "installing golangci-lint failed"
225		return 1
226	}
227	pkgdep_toolpath golangci_lint "${golangcidir}"
228}
229
230pkgdep_toolpath() {
231	# Usage: pkgdep_toolpath TOOL DIR
232	#
233	# Regenerates /etc/opt/spdk-pkgdep/paths to ensure that
234	# TOOL in DIR will be in PATH before other versions
235	# of the TOOL installed in the system.
236	local toolname="$1"
237	local toolpath="$2"
238	local toolpath_dir="/etc/opt/spdk-pkgdep/paths"
239	local toolpath_file="${toolpath_dir}/${toolname}.path"
240	local export_file="${toolpath_dir}/export.sh"
241	mkdir -p "$(dirname "${toolpath_file}")"
242	echo "${toolpath}" > "${toolpath_file}" || {
243		echo "cannot write toolpath ${toolpath} to ${toolpath_file}"
244		return 1
245	}
246	echo "# generated, source this file in shell" > "${export_file}"
247	for pathfile in "${toolpath_dir}"/*.path; do
248		echo "PATH=$(< ${pathfile}):\$PATH" >> "${export_file}"
249	done
250	echo "export PATH" >> "${export_file}"
251	echo "echo \$PATH" >> "${export_file}"
252	chmod a+x "${export_file}"
253}
254
255if [[ $INSTALL_DEV_TOOLS == true ]]; then
256	install_shfmt
257	install_spdk_bash_completion
258	if [[ $ID != centos && $ID != rocky && $ID != sles ]]; then
259		install_markdownlint
260	else
261		echo "mdl not supported on $ID, disabling"
262	fi
263fi
264
265if [[ $INSTALL_LIBURING == true ]]; then
266	install_liburing
267fi
268
269if [[ $INSTALL_GOLANG == true ]]; then
270	install_golang
271	install_protoc
272	install_golangci_lint
273fi
274