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