1#!/bin/bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2018 Intel Corporation. All rights reserved.
4
5# stop on most errors
6set -e
7
8# Platforms built and tested by default in CI using the `-a` option.
9# They must have a toolchain available in the latest Docker image.
10DEFAULT_PLATFORMS=(
11    tgl tgl-h
12    imx8 imx8x imx8m imx8ulp
13    rn rmb
14    mt8186 mt8195
15)
16
17# Work in progress can be added to this "staging area" without breaking
18# the -a option for everyone.
19SUPPORTED_PLATFORMS=( "${DEFAULT_PLATFORMS[@]}" )
20
21# Waiting for container work in progress
22SUPPORTED_PLATFORMS+=( mt8188 )
23
24BUILD_ROM=no
25BUILD_DEBUG=no
26BUILD_FORCE_UP=no
27BUILD_JOBS=$(nproc --all)
28BUILD_VERBOSE=
29PLATFORMS=()
30
31SOF_TOP=$(cd "$(dirname "$0")/.." && pwd)
32
33# As CMake forks one compiler process for each source file, the XTensa
34# compiler spends much more time idle waiting for the license server
35# over the network than actually using CPU or disk. A factor 3 has been
36# found optimal for 16 nproc 25ms away from the server; your mileage may
37# vary.
38#
39# The entire, purely local gcc build is so fast (~ 1s) that observing
40# any difference between -j nproc and -j nproc*N is practically
41# impossible so let's not waste RAM when building with gcc.
42
43if [ -n "$XTENSA_TOOLS_ROOT" ]; then
44    BUILD_JOBS=$((BUILD_JOBS * 3))
45fi
46
47
48die()
49{
50	>&2 printf '%s ERROR: ' "$0"
51	# We want die() to be usable exactly like printf
52	# shellcheck disable=SC2059
53	>&2 printf "$@"
54	exit 1
55}
56
57print_usage()
58{
59    cat <<EOF
60Re-configures and re-builds SOF using the corresponding compiler and the
61<platform>_defconfig file. Implements and saves the manual configuration
62described in
63https://thesofproject.github.io/latest/developer_guides/firmware/cmake.html
64
65usage: $0 [options] platform(s)
66
67       -r Build rom if available (gcc only)
68       -a Build all default platforms fully supported by the latest Docker image and CI
69       -u Force CONFIG_MULTICORE=n
70       -d Enable debug build
71       -c Interactive menuconfig
72       -o arg, copies src/arch/xtensa/configs/override/<arg>.config
73          to the build directory after invoking CMake and before Make.
74       -k Configure rimage to use a non-default \${RIMAGE_PRIVATE_KEY}
75          DEPRECATED: use the more flexible \${PRIVATE_KEY_OPTION} below.
76       -v Verbose Makefile log
77       -i Optional IPC_VERSION: can be set to IPC3, IPC4 or an empty string.
78          If set to "IPCx" then CONFIG_IPC_MAJOR_x will be set. If set to
79          IPC4 then a platform specific overlay may be used.
80       -j n Set number of make build jobs. Jobs=#cores when no flag.
81            Infinite when not specified.
82       -m path to MEU tool. CMake disables rimage signing which produces a
83          .uns[igned] file signed by MEU. For a non-default key use the
84          PRIVATE_KEY_OPTION, see below.
85
86To use a non-default key you must define the right CMake parameter in the
87following environment variable:
88
89     PRIVATE_KEY_OPTION='-DMEU_PRIVATE_KEY=path/to/key'  $0  -m /path/to/meu ...
90or:
91     PRIVATE_KEY_OPTION='-DRIMAGE_PRIVATE_KEY=path/to/key'  $0 ...
92
93This script supports XtensaTools but only when installed in a specific
94directory structure, example:
95
96myXtensa/
97└── install/
98    ├── builds/
99    │   ├── RD-2012.5-linux/
100    │   │   └── Intel_HiFiEP/
101    │   └── RG-2017.8-linux/
102    │       ├── LX4_langwell_audio_17_8/
103    │       └── X4H3I16w2D48w3a_2017_8/
104    └── tools/
105        ├── RD-2012.5-linux/
106        │   └── XtensaTools/
107        └── RG-2017.8-linux/
108            └── XtensaTools/
109
110$ XTENSA_TOOLS_ROOT=/path/to/myXtensa $0 ...
111
112Known platforms: ${SUPPORTED_PLATFORMS[*]}
113
114EOF
115}
116
117# parse the args
118while getopts "rudi:j:ckvao:m:" OPTION; do
119        case "$OPTION" in
120		r) BUILD_ROM=yes ;;
121		u) BUILD_FORCE_UP=yes ;;
122		d) BUILD_DEBUG=yes ;;
123		i) IPC_VERSION=$OPTARG ;;
124		j) BUILD_JOBS=$OPTARG ;;
125		c) MAKE_MENUCONFIG=yes ;;
126		k) USE_PRIVATE_KEY=yes ;;
127		o) OVERRIDE_CONFIG=$OPTARG ;;
128		v) BUILD_VERBOSE='VERBOSE=1' ;;
129		a) PLATFORMS=("${DEFAULT_PLATFORMS[@]}") ;;
130		m) MEU_TOOL_PATH=$OPTARG ;;
131		*) print_usage; exit 1 ;;
132        esac
133done
134shift $((OPTIND-1))
135
136#default signing tool
137SIGNING_TOOL=RIMAGE
138
139if [ -n "${OVERRIDE_CONFIG}" ]
140then
141	OVERRIDE_CONFIG="${SOF_TOP}/src/arch/xtensa/configs/override/$OVERRIDE_CONFIG.config"
142	[ -f "${OVERRIDE_CONFIG}" ] || die 'Invalid override config file %s\n' "${OVERRIDE_CONFIG}"
143fi
144
145if [ -n "${MEU_TOOL_PATH}" ]
146then
147	[ -d "${MEU_TOOL_PATH}" ] || die 'Invalid MEU TOOL PATH %s\n' "${MEU_TOOL_PATH}"
148	MEU_PATH_OPTION=-DMEU_PATH="${MEU_TOOL_PATH}"
149	SIGNING_TOOL=MEU
150fi
151
152# parse platform args
153for arg in "$@"; do
154	platform=none
155	for i in "${SUPPORTED_PLATFORMS[@]}"; do
156		if [ x"$i" = x"$arg" ]; then
157			PLATFORMS=("${PLATFORMS[@]}" "$i")
158			platform=$i
159			shift || true
160			break
161		fi
162	done
163	if [ "$platform" == "none" ]; then
164		echo "Error: Unknown platform specified: $arg"
165		echo "Known platforms are: ${SUPPORTED_PLATFORMS[*]}"
166		exit 1
167	fi
168done
169
170# check target platform(s) have been passed in
171if [ ${#PLATFORMS[@]} -eq 0 ];
172then
173	echo "Error: No platform specified. Known platforms: " \
174		"${SUPPORTED_PLATFORMS[*]}"
175	print_usage
176	exit 1
177fi
178
179if [ "x$USE_PRIVATE_KEY" == "xyes" ]
180then
181	>&2 printf \
182	    'WARNING: -k and RIMAGE_PRIVATE_KEY are deprecated, see usage.\n'
183	if [ -z ${RIMAGE_PRIVATE_KEY+x} ]
184	then
185		echo "Error: No variable specified for RIMAGE_PRIVATE_KEY"
186		exit 1
187	fi
188	PRIVATE_KEY_OPTION="-DRIMAGE_PRIVATE_KEY=${RIMAGE_PRIVATE_KEY}"
189fi
190
191OLDPATH=$PATH
192CURDIR="$(pwd)"
193
194# build platforms
195for platform in "${PLATFORMS[@]}"
196do
197	HAVE_ROM='no'
198	DEFCONFIG_PATCH=''
199	PLATFORM_PRIVATE_KEY=''
200
201	case $platform in
202		tgl)
203			PLATFORM="tgplp"
204			XTENSA_CORE="cavs2x_LX6HiFi3_2017_8"
205			HOST="xtensa-cnl-elf"
206			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
207			HAVE_ROM='yes'
208			IPC4_CONFIG_OVERLAY="tigerlake_ipc4"
209			# default key for TGL
210			PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem"
211			;;
212		tgl-h)
213			PLATFORM="tgph"
214			XTENSA_CORE="cavs2x_LX6HiFi3_2017_8"
215			HOST="xtensa-cnl-elf"
216			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
217			HAVE_ROM='yes'
218			# default key for TGL
219			PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem"
220			;;
221		imx8)
222			PLATFORM="imx8"
223			XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017"
224			HOST="xtensa-imx-elf"
225			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
226			;;
227		imx8x)
228			PLATFORM="imx8x"
229			XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017"
230			HOST="xtensa-imx-elf"
231			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
232			;;
233		imx8m)
234			PLATFORM="imx8m"
235			XTENSA_CORE="hifi4_mscale_v0_0_2_2017"
236			HOST="xtensa-imx8m-elf"
237			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
238			;;
239		imx8ulp)
240			PLATFORM="imx8ulp"
241			XTENSA_CORE="hifi4_nxp2_ulp_prod"
242			HOST="xtensa-imx8ulp-elf"
243			XTENSA_TOOLS_VERSION="RG-2017.8-linux"
244			;;
245		rn)
246			PLATFORM="renoir"
247			XTENSA_CORE="ACP_3_1_001_PROD_2019_1"
248			HOST="xtensa-rn-elf"
249			XTENSA_TOOLS_VERSION="RI-2019.1-linux"
250			;;
251		rmb)
252			PLATFORM="rembrandt"
253			ARCH="xtensa"
254			XTENSA_CORE="LX7_HiFi5_PROD"
255			HOST="xtensa-rmb-elf"
256			XTENSA_TOOLS_VERSION="RI-2019.1-linux"
257			;;
258		mt8186)
259			PLATFORM="mt8186"
260			XTENSA_CORE="hifi5_7stg_I64D128"
261			HOST="xtensa-mt8186-elf"
262			XTENSA_TOOLS_VERSION="RI-2020.5-linux"
263			;;
264		mt8188)
265			PLATFORM="mt8188"
266			XTENSA_CORE="hifi5_7stg_I64D128"
267			HOST="xtensa-mt8188-elf"
268			XTENSA_TOOLS_VERSION="RI-2020.5-linux"
269			;;
270		mt8195)
271			PLATFORM="mt8195"
272			XTENSA_CORE="hifi4_8195_PROD"
273			HOST="xtensa-mt8195-elf"
274			XTENSA_TOOLS_VERSION="RI-2019.1-linux"
275			;;
276
277	esac
278
279	test -z "${PRIVATE_KEY_OPTION}" || PLATFORM_PRIVATE_KEY="${PRIVATE_KEY_OPTION}"
280
281	if [ -n "$XTENSA_TOOLS_ROOT" ]
282	then
283		XTENSA_TOOLS_DIR="$XTENSA_TOOLS_ROOT/install/tools/$XTENSA_TOOLS_VERSION"
284		XTENSA_BUILDS_DIR="$XTENSA_TOOLS_ROOT/install/builds/$XTENSA_TOOLS_VERSION"
285
286		# make sure the required version of xtensa tools is installed
287		if [ -d "$XTENSA_TOOLS_DIR" ]
288			then
289				XCC="xt-xcc"
290			else
291				XCC="none"
292				>&2 printf 'WARNING: %s
293\t is not a directory, reverting to gcc\n' "$XTENSA_TOOLS_DIR"
294		fi
295	fi
296
297	# CMake uses ROOT_DIR for includes and libraries a bit like
298	# --sysroot would.
299	ROOT="$SOF_TOP/../xtensa-root/$HOST"
300
301	if [ "$XCC" == "xt-xcc" ]
302	then
303		TOOLCHAIN=xt
304		ROOT="$XTENSA_BUILDS_DIR/$XTENSA_CORE/xtensa-elf"
305		# CMake cannot set (evil) build-time environment variables at configure time:
306# https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-get-or-set-environment-variables
307		export XTENSA_SYSTEM=$XTENSA_BUILDS_DIR/$XTENSA_CORE/config
308		printf 'XTENSA_SYSTEM=%s\n' "${XTENSA_SYSTEM}"
309		PATH=$XTENSA_TOOLS_DIR/XtensaTools/bin:$OLDPATH
310		COMPILER="xcc"
311	else
312		TOOLCHAIN=$HOST
313		PATH=$SOF_TOP/../$HOST/bin:$OLDPATH
314		COMPILER="gcc"
315		DEFCONFIG_PATCH=""
316	fi
317
318	BUILD_DIR=build_${platform}_${COMPILER}
319	printf "Build in %s\n" "$BUILD_DIR"
320
321	# only delete binary related to this build
322	rm -fr "$BUILD_DIR"
323	mkdir "$BUILD_DIR"
324	cd "$BUILD_DIR"
325
326	printf 'PATH=%s\n' "$PATH"
327	( set -x # log the main commands and their parameters
328	cmake -DTOOLCHAIN="$TOOLCHAIN" \
329		-DROOT_DIR="$ROOT" \
330		-DMEU_OPENSSL="${MEU_OPENSSL}" \
331		"${MEU_PATH_OPTION}" \
332		"${PLATFORM_PRIVATE_KEY}" \
333		-DINIT_CONFIG=${PLATFORM}${DEFCONFIG_PATCH}_defconfig \
334		-DEXTRA_CFLAGS="${EXTRA_CFLAGS}" \
335		"$SOF_TOP"
336	)
337
338	if [ -n "$OVERRIDE_CONFIG" ]
339	then
340		cp "$OVERRIDE_CONFIG" override.config
341	fi
342
343	if [[ "x$MAKE_MENUCONFIG" == "xyes" ]]
344	then
345		cmake --build .  --  menuconfig
346	fi
347
348	case "$IPC_VERSION" in
349	    '') ;;
350	    IPC3)
351		echo 'CONFIG_IPC_MAJOR_3=y' >> override.config
352		;;
353	    IPC4)
354		test -z "$IPC4_CONFIG_OVERLAY" ||
355	    cat "${SOF_TOP}/src/arch/xtensa/configs/override/$IPC4_CONFIG_OVERLAY.config" \
356		    >> override.config
357		echo 'CONFIG_IPC_MAJOR_4=y' >> override.config
358	    ;;
359	    *) die "Invalid -i '%s' argument\n" "$IPC_VERSION" ;;
360	esac
361
362	if [[ "x$BUILD_DEBUG" == "xyes" ]]
363	then
364		echo "CONFIG_DEBUG=y" >> override.config
365	fi
366
367	if [[ "x$BUILD_ROM" == "xyes" && "x$HAVE_ROM" == "xyes" ]]
368	then
369		echo "CONFIG_BUILD_VM_ROM=y" >> override.config
370	fi
371
372	if [ "x$BUILD_FORCE_UP" == "xyes" ]
373	then
374		echo "Force building UP(xtensa)..."
375		echo "CONFIG_MULTICORE=n" >> override.config
376	fi
377
378	if [ -e override.config ]
379	then
380		cmake --build .  --  overrideconfig
381	fi
382
383	cmake --build .  --  bin -j "${BUILD_JOBS}" ${BUILD_VERBOSE}
384
385	cd "$CURDIR"
386done # for platform in ...
387
388# list all the images
389ls -l build_*/*.ri build_*/src/arch/xtensa/rom*.bin || true
390ls -l build_*/sof
391