xref: /spdk/scripts/pkgdep/common.sh (revision 0cdba6b186375c7b8356940a958b8b186a5ca1f9)
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 -X
21}
22
23install_uadk() {
24	local GIT_REPO_UADK=https://github.com/Linaro/uadk
25	local uadk_dir=/usr/local/src/uadk
26
27	if [[ -d $uadk_dir ]]; then
28		echo "uadk source already present, not cloning"
29	else
30		mkdir -p $uadk_dir
31		git clone "${GIT_REPO_UADK}" "$uadk_dir"
32	fi
33	(cd "$uadk_dir" && ./cleanup.sh && ./autogen.sh && ./configure --libdir=/usr/lib64 && make install)
34	echo /usr/lib64 > /etc/ld.so.conf.d/uadk.conf
35	ldconfig
36}
37
38_install_shfmt() {
39	local version=$1 arch=$2 type=$3
40
41	local shfmt_dir=/usr/local/src/shfmt shfmt_repo=https://github.com/mvdan/sh
42
43	if [[ $type != build ]]; then
44		echo "$shfmt_repo/releases/download/$version/shfmt_${version}_linux_${arch}"
45		return 0
46	fi
47
48	if [[ ! -e /etc/opt/spdk-pkgdep/paths/go.path ]]; then
49		install_golang
50	fi
51	source /etc/opt/spdk-pkgdep/paths/export.sh > /dev/null
52
53	rm -rf "$shfmt_dir"
54
55	git clone "$shfmt_repo" "$shfmt_dir"
56	git -C "$shfmt_dir" checkout "$version"
57
58	# See cmd/shfmt/Dockerfile
59	CGO_ENABLED=0 go -C "$shfmt_dir" build \
60		-ldflags "-w -s -extldflags '-static' -X main.version=$version" \
61		"$shfmt_dir/cmd/shfmt"
62
63	echo "file://$shfmt_dir/shfmt"
64}
65
66install_shfmt() {
67	# Fetch version that has been tested
68	local shfmt_version=v3.8.0
69	local shfmt=shfmt-$shfmt_version
70	local shfmt_dir=${SHFMT_DIR:-/opt/shfmt}
71	local shfmt_dir_out=${SHFMT_DIR_OUT:-/usr/bin}
72	local shfmt_url
73	local os
74	local arch
75	local cmdline
76
77	if hash "$shfmt" && [[ $("$shfmt" --version) == "$shfmt_version" ]]; then
78		echo "$shfmt already installed"
79		return 0
80	fi 2> /dev/null
81
82	arch=$(uname -m)
83	os=$(uname -s)
84
85	case "$arch" in
86		x86_64) arch="amd64" ;;
87		aarch64) arch="arm" ;;
88		amd64) ;; # FreeBSD
89		*)
90			echo "Not supported arch (${arch:-Unknown}), skipping"
91			return 0
92			;;
93	esac
94
95	cmdline=("$shfmt_version" "$arch")
96	[[ $os == FreeBSD || -n $BUILD_SHFMT ]] && cmdline+=(build)
97
98	shfmt_url=$(_install_shfmt "${cmdline[@]}")
99
100	mkdir -p "$shfmt_dir"
101	mkdir -p "$shfmt_dir_out"
102
103	echo "Fetching ${shfmt_url##*/}"...
104	local err
105	if err=$(curl -f -Lo"$shfmt_dir/$shfmt" "$shfmt_url" 2>&1); then
106		chmod +x "$shfmt_dir/$shfmt"
107		ln -sf "$shfmt_dir/$shfmt" "$shfmt_dir_out"
108	else
109		cat <<- CURL_ERR
110
111			* Fetching $shfmt_url failed, $shfmt will not be available for format check.
112			* Error:
113
114			$err
115
116		CURL_ERR
117		return 0
118	fi
119	echo "$shfmt installed"
120}
121
122install_spdk_bash_completion() {
123	[[ -e /usr/share/bash-completion/bash_completion ]] || return 0
124
125	local compat_dir=/etc/bash_completion.d
126	mkdir -p "$compat_dir"
127
128	if [[ ! -e $compat_dir/spdk ]]; then
129		cp -v "$scriptsdir/bash-completion/spdk" "$compat_dir"
130	fi
131}
132
133install_markdownlint() {
134	local git_repo_mdl="https://github.com/markdownlint/markdownlint.git"
135	local mdl_version="v0.11.0"
136	local srcdir=/usr/src/markdownlint
137
138	rm -rf "$srcdir"
139	git clone --branch "$mdl_version" "$git_repo_mdl" "$srcdir"
140	(
141		cd "$srcdir"
142		rake install
143	)
144}
145
146install_protoc() {
147	local PROTOCVERSION=${PROTOCVERSION:-21.7}
148	local PROTOCGENGOVERSION=${PROTOCGENGOVERSION:-1.28}
149	local PROTOCGENGOGRPCVERSION=${PROTOCGENGOGRPCVERSION:-1.2}
150	local protocdir protocpkg protocurl protocver arch
151	local skip_protoc=0
152	# It is easy to find an incompatible combination of protoc,
153	# protoc-gen-go and protoc-gen-go-grpc. Therefore install a
154	# preferred version combination even if more recent versions
155	# of some of these tools would be available in the system.
156	protocver=$(protoc --version 2> /dev/null | {
157		read -r _ v
158		echo $v
159	})
160	if [[ "3.${PROTOCVERSION}" == "${protocver}" ]]; then
161		echo "found protoc version ${protocver} exactly required 3.${PROTOCVERSION}, skip installing"
162		skip_protoc=1
163	fi
164	protocdir=/opt/protoc/${PROTOCVERSION}
165	if [[ -x "${protocdir}/bin/protoc" ]]; then
166		echo "protoc already installed to ${protocdir}, skip installing"
167		skip_protoc=1
168	fi
169	if [[ "${skip_protoc}" != "1" ]]; then
170		echo "installing protoc v${PROTOCVERSION} to ${protocdir}"
171		mkdir -p "${protocdir}"
172		arch=x86_64
173		if [[ "$(uname -m)" == "aarch64" ]]; then
174			arch=aarch_64
175		fi
176		protocpkg=protoc-${PROTOCVERSION}-linux-${arch}.zip
177		protocurl=https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOCVERSION}/${protocpkg}
178		curl -f -LO "${protocurl}" || {
179			echo "downloading protoc ${PROTOCVERSION} from ${protocurl} failed"
180			return 1
181		}
182		unzip -d "${protocdir}" "${protocpkg}" || {
183			echo "extracting protoc ${PROTOCVERSION} from ${protocpkg} failed"
184			rm -f "${protocpkg}"
185			return 1
186		}
187		rm -f "${protocpkg}"
188	fi
189	if [[ -x "${protocdir}/bin/protoc-gen-go" ]]; then
190		echo "${protocdir}/bin/protoc-gen-go already installed"
191	else
192		echo "installing protoc-gen-go v${PROTOCGENGOVERSION} to ${protocdir}/bin"
193		mkdir -p "${protocdir}/bin"
194		GOBIN="${protocdir}/bin" go install "google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOCGENGOVERSION}" || {
195			echo "protoc protoc-gen-go plugin install failed"
196			return 1
197		}
198	fi
199	if [[ -x "${protocdir}/bin/protoc-gen-go-grpc" ]]; then
200		echo "${protocdir}/bin/protoc-gen-go-grpc already installed"
201	else
202		echo "installing protoc-gen-go-grpc v${PROTOCGENGOGRPCVERSION} to ${protocdir}/bin"
203		mkdir -p "${protocdir}/bin"
204		GOBIN="${protocdir}/bin" go install "google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${PROTOCGENGOGRPCVERSION}" || {
205			echo "protoc protoc-gen-go-grpc plugin install failed"
206			return 1
207		}
208	fi
209	pkgdep_toolpath protoc "${protocdir}/bin"
210}
211
212install_golang() {
213	local GOVERSION=${GOVERSION:-1.21.1}
214	local godir gopkg gover arch os
215
216	read -r _ _ gover _ < <(go version) || true
217	gover=${gover#go}
218	if [[ -n "${gover}" ]] && ge "${gover}" "${GOVERSION}"; then
219		echo "found go version ${gover} >= required ${GOVERSION}, skip installing"
220		return 0
221	fi
222	godir=/opt/go/${GOVERSION}
223	if [[ -x "${godir}/bin/go" ]]; then
224		echo "go already installed in ${godir}, skip installing"
225		return 0
226	fi
227	mkdir -p "${godir}"
228	arch=amd64
229	os=$(uname -s)
230	if [[ "$(uname -m)" == "aarch64" ]]; then
231		arch=arm64
232	fi
233	gopkg=go${GOVERSION}.${os,,}-${arch}.tar.gz
234	echo "installing go v${GOVERSION} to ${godir}/bin"
235	curl -sL https://go.dev/dl/${gopkg} | tar -C "${godir}" -xzf - --strip 1
236	if ! "${godir}/bin/go" version; then
237		echo "go install failed"
238		return 1
239	fi
240	export PATH=${godir}/bin:$PATH
241	export GOBIN=${godir}/bin
242	pkgdep_toolpath go "${godir}/bin"
243}
244
245install_golangci_lint() {
246	local golangcidir installed_lintversion lintversion=${GOLANGCLILINTVERSION:-1.54.2}
247	installed_lintversion=$(golangci-lint --version | awk '{print $4}')
248
249	if [[ -n "${installed_lintversion}" ]] && ge "${installed_lintversion}" "${lintversion}"; then
250		echo "golangci-lint already installed, skip installing"
251		return 0
252	fi
253
254	echo "installing golangci-lint"
255	golangcidir=/opt/golangci/$lintversion/bin
256	export PATH=${golangcidir}:$PATH
257	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v${lintversion}/install.sh \
258		| sh -s -- -b "${golangcidir}" "v$lintversion" || {
259		echo "installing golangci-lint failed"
260		return 1
261	}
262	pkgdep_toolpath golangci_lint "${golangcidir}"
263}
264
265if [[ $INSTALL_DEV_TOOLS == true ]]; then
266	install_shfmt
267	install_spdk_bash_completion
268	if [[ $ID != centos && $ID != rocky && $ID != sles ]]; then
269		install_markdownlint
270	else
271		echo "mdl not supported on $ID, disabling"
272	fi
273fi
274
275if [[ $INSTALL_LIBURING == true ]]; then
276	install_liburing
277fi
278
279if [[ $INSTALL_UADK == true ]]; then
280	install_uadk
281fi
282
283if [[ $INSTALL_GOLANG == true ]]; then
284	install_golang
285	[[ $(uname -s) == Linux ]] && install_protoc
286	install_golangci_lint
287fi
288