• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2
3#
4# edk2-build.sh: evolution of uefi-build.sh for edk2-platforms
5#
6
7unset MAKEFLAGS  # BaseTools not safe to build parallel, prevent env overrides
8
9TOOLS_DIR="`dirname $0`"
10TOOLS_DIR="`readlink -f \"$TOOLS_DIR\"`"
11export TOOLS_DIR
12. "$TOOLS_DIR"/common-functions
13PLATFORM_CONFIG="-c $TOOLS_DIR/edk2-platforms.config"
14ARCH=
15VERBOSE=0                  # Override with -v
16ATF_DIR=
17TOS_DIR=
18TOOLCHAIN="gcc"            # Override with -T
19WORKSPACE=
20EDK2_DIR=
21PLATFORMS_DIR=
22NON_OSI_DIR=
23IMPORT_OPENSSL=TRUE
24OPENSSL_CONFIGURED=FALSE
25
26# Number of threads to use for build
27export NUM_THREADS=$((`getconf _NPROCESSORS_ONLN` + `getconf _NPROCESSORS_ONLN`))
28
29function do_build
30{
31	PLATFORM_ARCH=`echo $board | cut -s -d: -f2`
32	if [ -n "$PLATFORM_ARCH" ]; then
33		board=`echo $board | cut -d: -f1`
34	else
35		PLATFORM_ARCH="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o arch`"
36	fi
37	PLATFORM_NAME="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o longname` ($PLATFORM_ARCH)"
38	if [ -z "$PLATFORM_ARCH" ]; then
39		echo "Unknown target architecture - aborting!" >&2
40		return 1
41	fi
42	PLATFORM_PREBUILD_CMDS="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o prebuild_cmds`"
43	PLATFORM_BUILDFLAGS="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o buildflags`"
44	PLATFORM_BUILDFLAGS="$PLATFORM_BUILDFLAGS ${EXTRA_OPTIONS[@]}"
45	PLATFORM_BUILDCMD="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o buildcmd`"
46	PLATFORM_DSC="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o dsc`"
47	PLATFORM_PACKAGES_PATH=""
48	COMPONENT_INF="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o inf`"
49
50	TEMP_PACKAGES_PATH="$GLOBAL_PACKAGES_PATH:`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o packages_path`"
51	IFS=:
52	for path in "$TEMP_PACKAGES_PATH"; do
53		case "$path" in
54			/*)
55				PLATFORM_PACKAGES_PATH="$PLATFORM_PACKAGES_PATH:$path"
56			;;
57			*)
58				PLATFORM_PACKAGES_PATH="$PLATFORM_PACKAGES_PATH:$PWD/$path"
59			;;
60	        esac
61	done
62	unset IFS
63
64	if [ $VERBOSE -eq 1 ]; then
65		echo "Setting build parallellism to $NUM_THREADS processes"
66		echo "PLATFORM_NAME=$PLATFORM_NAME"
67		echo "PLATFORM_PREBUILD_CMDS=$PLATFORM_PREBUILD_CMDS"
68		echo "PLATFORM_BUILDFLAGS=$PLATFORM_BUILDFLAGS"
69		echo "PLATFORM_BUILDCMD=$PLATFORM_BUILDCMD"
70		echo "PLATFORM_DSC=$PLATFORM_DSC"
71		echo "PLATFORM_ARCH=$PLATFORM_ARCH"
72		echo "PLATFORM_PACKAGES_PATH=$PLATFORM_PACKAGES_PATH"
73	fi
74
75	set_cross_compile
76	CROSS_COMPILE="$TEMP_CROSS_COMPILE"
77
78	echo "Building $PLATFORM_NAME - $PLATFORM_ARCH"
79	echo "CROSS_COMPILE=\"$TEMP_CROSS_COMPILE\""
80	echo "$board"_BUILDFLAGS="'$PLATFORM_BUILDFLAGS'"
81
82	if [ "$TARGETS" == "" ]; then
83		TARGETS=( RELEASE )
84	fi
85
86	case $TOOLCHAIN in
87		"gcc")
88			PLATFORM_TOOLCHAIN=`get_gcc_version "$CROSS_COMPILE"gcc`
89			;;
90		"clang")
91			PLATFORM_TOOLCHAIN=`get_clang_version clang`
92			;;
93		*)
94			# Use command-line specified profile directly
95			PLATFORM_TOOLCHAIN=$TOOLCHAIN
96			;;
97	esac
98	echo "PLATFORM_TOOLCHAIN is ${PLATFORM_TOOLCHAIN}"
99
100	export ${PLATFORM_TOOLCHAIN}_${PLATFORM_ARCH}_PREFIX=$CROSS_COMPILE
101	echo "Toolchain prefix: ${PLATFORM_TOOLCHAIN}_${PLATFORM_ARCH}_PREFIX=$CROSS_COMPILE"
102
103	export PACKAGES_PATH="$PLATFORM_PACKAGES_PATH"
104	for target in "${TARGETS[@]}" ; do
105		if [ X"$PLATFORM_PREBUILD_CMDS" != X"" ]; then
106			echo "Run pre-build commands:"
107			if [ $VERBOSE -eq 1 ]; then
108				echo "  ${PLATFORM_PREBUILD_CMDS}"
109			fi
110			eval ${PLATFORM_PREBUILD_CMDS}
111		fi
112
113		if [ -n "$COMPONENT_INF" ]; then
114			# Build a standalone component
115			if [ $VERBOSE -eq 1 ]; then
116				echo "build -n $NUM_THREADS -a \"$PLATFORM_ARCH\" -t ${PLATFORM_TOOLCHAIN} -p \"$PLATFORM_DSC\"" \
117					"-m \"$COMPONENT_INF\" -b "$target" ${PLATFORM_BUILDFLAGS}"
118			fi
119			build -n $NUM_THREADS -a "$PLATFORM_ARCH" -t ${PLATFORM_TOOLCHAIN} -p "$PLATFORM_DSC" \
120				-m "$COMPONENT_INF" -b "$target" ${PLATFORM_BUILDFLAGS}
121		else
122			# Build a platform
123			if [ $VERBOSE -eq 1 ]; then
124				echo "build -n $NUM_THREADS -a \"$PLATFORM_ARCH\" -t ${PLATFORM_TOOLCHAIN} -p \"$PLATFORM_DSC\"" \
125					"-b "$target" ${PLATFORM_BUILDFLAGS}"
126			fi
127			build -n $NUM_THREADS -a "$PLATFORM_ARCH" -t ${PLATFORM_TOOLCHAIN} -p "$PLATFORM_DSC" \
128				-b "$target" ${PLATFORM_BUILDFLAGS}
129		fi
130
131		RESULT=$?
132		if [ $RESULT -eq 0 ]; then
133			if [ X"$TOS_DIR" != X"" ]; then
134				pushd $TOS_DIR >/dev/null
135				if [ $VERBOSE -eq 1 ]; then
136					echo "$TOOLS_DIR/tos-build.sh -e "$EDK2_DIR" -t "$target"_${PLATFORM_TOOLCHAIN} $board"
137				fi
138				$TOOLS_DIR/tos-build.sh -e "$EDK2_DIR" -t "$target"_${PLATFORM_TOOLCHAIN} $board
139				RESULT=$?
140				popd >/dev/null
141			fi
142		fi
143		if [ $RESULT -eq 0 ]; then
144			if [ X"$ATF_DIR" != X"" ]; then
145				pushd $ATF_DIR >/dev/null
146				if [ $VERBOSE -eq 1 ]; then
147					echo "$TOOLS_DIR/atf-build.sh -e "$EDK2_DIR" -t "$target"_${PLATFORM_TOOLCHAIN} $board"
148				fi
149				$TOOLS_DIR/atf-build.sh -e "$EDK2_DIR" -t "$target"_${PLATFORM_TOOLCHAIN} $board
150				RESULT=$?
151				popd >/dev/null
152			fi
153		fi
154		result_log $RESULT "$PLATFORM_NAME $target"
155	done
156	unset PACKAGES_PATH
157}
158
159
160function configure_paths
161{
162	WORKSPACE="$PWD"
163
164	# Check to see if we are in a UEFI repository
165	# refuse to continue if we aren't
166	if [ ! -d "$EDK2_DIR"/BaseTools ]
167	then
168		if [ -d "$PWD"/edk2/BaseTools ]; then
169			EDK2_DIR="$PWD"/edk2
170		else
171			echo "ERROR: can't locate the edk2 directory" >&2
172			echo "       please specify -e/--edk2-dir" >&2
173			exit 1
174		fi
175	fi
176
177	GLOBAL_PACKAGES_PATH="$EDK2_DIR"
178
179	# locate edk2-platforms
180	if [ -z "$PLATFORMS_DIR" -a -d "$PWD"/edk2-platforms ]; then
181		PLATFORMS_DIR="$PWD"/edk2-platforms
182	fi
183	if [ -n "$PLATFORMS_DIR" ]; then
184		GLOBAL_PACKAGES_PATH="$GLOBAL_PACKAGES_PATH:$PLATFORMS_DIR"
185	fi
186
187	# locate edk2-non-osi
188	if [ -z "$NON_OSI_DIR" -a -d "$PWD"/edk2-non-osi ]; then
189		NON_OSI_DIR="$PWD"/edk2-non-osi
190	fi
191	if [ -n "$NON_OSI_DIR" ]; then
192		GLOBAL_PACKAGES_PATH="$GLOBAL_PACKAGES_PATH:$NON_OSI_DIR"
193	fi
194
195	# locate arm-trusted-firmware
196	if [ -z "$ATF_DIR" -a -d "$PWD"/arm-trusted-firmware ]; then
197		ATF_DIR="$PWD"/arm-trusted-firmware
198	fi
199
200	export WORKSPACE
201}
202
203
204function prepare_build
205{
206	get_build_arch
207	export ARCH=$BUILD_ARCH
208
209	export ARCH
210	cd $EDK2_DIR
211	PACKAGES_PATH=$GLOBAL_PACKAGES_PATH . edksetup.sh --reconfig
212	if [ $? -ne 0 ]; then
213		echo "Sourcing edksetup.sh failed!" >&2
214		exit 1
215	fi
216	if [ $VERBOSE -eq 1 ]; then
217		echo "Building BaseTools"
218	fi
219	make -C BaseTools
220	RET=$?
221	cd -
222	if [ $RET -ne 0 ]; then
223		echo " !!! BaseTools failed to build !!! " >&2
224		exit 1
225	fi
226
227	if [ "$IMPORT_OPENSSL" = "TRUE" ]; then
228		cd $EDK2_DIR
229		import_openssl
230		if [ $? -ne 0 ]; then
231			echo "Importing OpenSSL failed - aborting!" >&2
232			echo "  specify --no-openssl to attempt build anyway." >&2
233			exit 1
234		fi
235		cd $WORKSPACE
236	fi
237}
238
239
240function usage
241{
242	echo "usage:"
243	echo -n "uefi-build.sh [-b DEBUG | RELEASE] [ all "
244	for board in "${boards[@]}" ; do
245	    echo -n "| $board "
246	done
247	echo "]"
248	printf "%8s\tbuild %s\n" "all" "all supported platforms"
249	for board in "${boards[@]}" ; do
250		PLATFORM_NAME="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o longname`"
251		printf "%8s\tbuild %s\n" "$board" "${PLATFORM_NAME}"
252	done
253}
254
255#
256# Since we do a command line validation on whether specified platforms exist or
257# not, do a first pass of command line to see if there is an explicit config
258# file there to read valid platforms from.
259#
260commandline=( "$@" )
261i=0
262for arg;
263do
264	if [ $arg == "-c" ]; then
265		FILE_ARG=${commandline[i + 1]}
266		if [ ! -f "$FILE_ARG" ]; then
267			echo "ERROR: configuration file '$FILE_ARG' not found" >&2
268			exit 1
269		fi
270		case "$FILE_ARG" in
271			/*)
272				PLATFORM_CONFIG="-c $FILE_ARG"
273			;;
274			*)
275				PLATFORM_CONFIG="-c `readlink -f \"$FILE_ARG\"`"
276			;;
277		esac
278		echo "Platform config file: '$FILE_ARG'"
279	fi
280	i=$(($i + 1))
281done
282
283export PLATFORM_CONFIG
284
285builds=()
286boards=()
287boardlist="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG shortlist`"
288for board in $boardlist; do
289    boards=(${boards[@]} $board)
290done
291
292NUM_TARGETS=0
293
294while [ "$1" != "" ]; do
295	case $1 in
296		-1)     # Disable build parallellism
297			NUM_THREADS=1
298			;;
299		-a | --arm-tf-dir)
300			shift
301			ATF_DIR="`readlink -f $1`"
302			;;
303		-c)     # Already parsed above - skip this + option
304			shift
305			;;
306		-b | --build-target)
307			shift
308			echo "Adding Build target: $1"
309			TARGETS=(${TARGETS[@]} $1)
310			;;
311		-D)     # Pass through as -D option to 'build'
312			shift
313			echo "Adding Macro: -D $1"
314			EXTRA_OPTIONS=(${EXTRA_OPTIONS[@]} "-D" $1)
315			;;
316		-e | --edk2-dir)
317			shift
318			export EDK2_DIR="`readlink -f $1`"
319			;;
320		-h | --help)
321			usage
322			exit
323			;;
324		--no-openssl)
325			IMPORT_OPENSSL=FALSE
326			;;
327		-n | --non-osi-dir)
328			shift
329			NON_OSI_DIR="`readlink -f $1`"
330			;;
331		-p | --platforms-dir)
332			shift
333			PLATFORMS_DIR="`readlink -f $1`"
334			;;
335		-s | --tos-dir)
336			shift
337			export TOS_DIR="`readlink -f $1`"
338			;;
339		-T)     # Set specific toolchain tag, or clang/gcc for autoselection
340			shift
341			echo "Setting toolchain tag to '$1'"
342			TOOLCHAIN="$1"
343			;;
344		-v)
345			VERBOSE=1
346			;;
347		all)    # Add all targets in configuration file to list
348			builds=(${boards[@]})
349			NUM_TARGETS=$(($NUM_TARGETS + 1))
350			;;
351		*)      # Try to match target in configuration file, add to list
352			MATCH=0
353			for board in "${boards[@]}" ; do
354				if [ "`echo $1 | cut -d: -f1`" == $board ]; then
355					MATCH=1
356					builds=(${builds[@]} "$1")
357					break
358				fi
359			done
360
361			if [ $MATCH -eq 0 ]; then
362				echo "unknown arg $1"
363				usage
364				exit 1
365			fi
366			NUM_TARGETS=$(($NUM_TARGETS + 1))
367			;;
368	esac
369	shift
370done
371
372if [ $NUM_TARGETS -le  0 ]; then
373	echo "No targets specified - exiting!" >&2
374	exit 0
375fi
376
377export VERBOSE
378
379configure_paths
380
381prepare_build
382
383if [[ "${EXTRA_OPTIONS[@]}" != *"FIRMWARE_VER"* ]]; then
384	if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
385		FIRMWARE_VER=`git rev-parse --short HEAD`
386		if ! git diff-index --quiet HEAD --; then
387			FIRMWARE_VER="${FIRMWARE_VER}-dirty"
388		fi
389		EXTRA_OPTIONS=( ${EXTRA_OPTIONS[@]} "-D" FIRMWARE_VER=$FIRMWARE_VER )
390		if [ $VERBOSE -eq 1 ]; then
391			echo "FIRMWARE_VER=$FIRMWARE_VER"
392			echo "EXTRA_OPTIONS=$EXTRA_OPTIONS"
393		fi
394	fi
395fi
396
397for board in "${builds[@]}" ; do
398	do_build
399done
400
401result_print
402