Home | History | Annotate | Download | only in uefi-tools
      1 #!/bin/bash
      2 
      3 #
      4 # edk2-build.sh: evolution of uefi-build.sh for edk2-platforms
      5 #
      6 
      7 unset MAKEFLAGS  # BaseTools not safe to build parallel, prevent env overrides
      8 
      9 TOOLS_DIR="`dirname $0`"
     10 TOOLS_DIR="`readlink -f \"$TOOLS_DIR\"`"
     11 export TOOLS_DIR
     12 . "$TOOLS_DIR"/common-functions
     13 PLATFORM_CONFIG="-c $TOOLS_DIR/edk2-platforms.config"
     14 ARCH=
     15 VERBOSE=0                  # Override with -v
     16 ATF_DIR=
     17 TOS_DIR=
     18 TOOLCHAIN="gcc"            # Override with -T
     19 WORKSPACE=
     20 EDK2_DIR=
     21 PLATFORMS_DIR=
     22 NON_OSI_DIR=
     23 IMPORT_OPENSSL=TRUE
     24 OPENSSL_CONFIGURED=FALSE
     25 
     26 # Number of threads to use for build
     27 export NUM_THREADS=$((`getconf _NPROCESSORS_ONLN` + `getconf _NPROCESSORS_ONLN`))
     28 
     29 function 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 
    160 function 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 
    204 function 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 
    240 function 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 #
    260 commandline=( "$@" )
    261 i=0
    262 for arg;
    263 do
    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))
    281 done
    282 
    283 export PLATFORM_CONFIG
    284 
    285 builds=()
    286 boards=()
    287 boardlist="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG shortlist`"
    288 for board in $boardlist; do
    289     boards=(${boards[@]} $board)
    290 done
    291 
    292 NUM_TARGETS=0
    293 
    294 while [ "$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
    370 done
    371 
    372 if [ $NUM_TARGETS -le  0 ]; then
    373 	echo "No targets specified - exiting!" >&2
    374 	exit 0
    375 fi
    376 
    377 export VERBOSE
    378 
    379 configure_paths
    380 
    381 prepare_build
    382 
    383 if [[ "${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
    395 fi
    396 
    397 for board in "${builds[@]}" ; do
    398 	do_build
    399 done
    400 
    401 result_print
    402