edk2-funcs.sh (6922B)
1# Shell script that defines functions for determining some environmental 2# characteristics for the edk2 "build" utility. 3# 4# This script is meant to be sourced, in a bash environment. 5# 6# Copyright (C) 2019 Red Hat, Inc. 7# 8# This program and the accompanying materials are licensed and made available 9# under the terms and conditions of the BSD License that accompanies this 10# distribution. The full text of the license may be found at 11# <http://opensource.org/licenses/bsd-license.php>. 12# 13# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 14# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 17# Verify whether the QEMU system emulation target is supported by the UEFI spec 18# and edk2. Print a message to the standard error, and return with nonzero 19# status, if verification fails. 20# 21# Parameters: 22# $1: QEMU system emulation target 23qemu_edk2_verify_arch() 24{ 25 local emulation_target="$1" 26 local program_name=$(basename -- "$0") 27 28 case "$emulation_target" in 29 (arm|aarch64|i386|x86_64) 30 ;; 31 (*) 32 printf '%s: unknown/unsupported QEMU system emulation target "%s"\n' \ 33 "$program_name" "$emulation_target" >&2 34 return 1 35 ;; 36 esac 37} 38 39 40# Translate the QEMU system emulation target to the edk2 architecture 41# identifier. Print the result to the standard output. 42# 43# Parameters: 44# $1: QEMU system emulation target 45qemu_edk2_get_arch() 46{ 47 local emulation_target="$1" 48 49 if ! qemu_edk2_verify_arch "$emulation_target"; then 50 return 1 51 fi 52 53 case "$emulation_target" in 54 (arm) 55 printf 'ARM\n' 56 ;; 57 (aarch64) 58 printf 'AARCH64\n' 59 ;; 60 (i386) 61 printf 'IA32\n' 62 ;; 63 (x86_64) 64 printf 'X64\n' 65 ;; 66 esac 67} 68 69 70# Translate the QEMU system emulation target to the gcc cross-compilation 71# architecture identifier. Print the result to the standard output. 72# 73# Parameters: 74# $1: QEMU system emulation target 75qemu_edk2_get_gcc_arch() 76{ 77 local emulation_target="$1" 78 79 if ! qemu_edk2_verify_arch "$emulation_target"; then 80 return 1 81 fi 82 83 case "$emulation_target" in 84 (arm|aarch64|x86_64) 85 printf '%s\n' "$emulation_target" 86 ;; 87 (i386) 88 printf 'i686\n' 89 ;; 90 esac 91} 92 93 94# Determine the gcc cross-compiler prefix (if any) for use with the edk2 95# toolchain. Print the result to the standard output. 96# 97# Parameters: 98# $1: QEMU system emulation target 99qemu_edk2_get_cross_prefix() 100{ 101 local emulation_target="$1" 102 local gcc_arch 103 local host_arch 104 105 if ! gcc_arch=$(qemu_edk2_get_gcc_arch "$emulation_target"); then 106 return 1 107 fi 108 109 host_arch=$(uname -m) 110 111 if [ "$gcc_arch" == "$host_arch" ] || 112 ( [ "$gcc_arch" == i686 ] && [ "$host_arch" == x86_64 ] ); then 113 # no cross-compiler needed 114 : 115 elif ( [ -e /etc/debian_version ] && [ "$gcc_arch" == arm ] ); then 116 # force soft-float cross-compiler on Debian 117 printf 'arm-linux-gnueabi-' 118 else 119 printf '%s-linux-gnu-\n' "$gcc_arch" 120 fi 121} 122 123 124# Determine the edk2 toolchain tag for the QEMU system emulation target. Print 125# the result to the standard output. Print a message to the standard error, and 126# return with nonzero status, if the (conditional) gcc version check fails. 127# 128# Parameters: 129# $1: QEMU system emulation target 130qemu_edk2_get_toolchain() 131{ 132 local emulation_target="$1" 133 local program_name=$(basename -- "$0") 134 local cross_prefix 135 local gcc_version 136 137 if ! qemu_edk2_verify_arch "$emulation_target"; then 138 return 1 139 fi 140 141 case "$emulation_target" in 142 (arm|aarch64) 143 printf 'GCC5\n' 144 ;; 145 146 (i386|x86_64) 147 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 148 return 1 149 fi 150 151 gcc_version=$("${cross_prefix}gcc" -v 2>&1 | tail -1 | awk '{print $3}') 152 # Run "git-blame" on "OvmfPkg/build.sh" in edk2 for more information on 153 # the mapping below. 154 case "$gcc_version" in 155 ([1-3].*|4.[0-7].*) 156 printf '%s: unsupported gcc version "%s"\n' \ 157 "$program_name" "$gcc_version" >&2 158 return 1 159 ;; 160 (4.8.*) 161 printf 'GCC48\n' 162 ;; 163 (4.9.*|6.[0-2].*) 164 printf 'GCC49\n' 165 ;; 166 (*) 167 printf 'GCC5\n' 168 ;; 169 esac 170 ;; 171 esac 172} 173 174 175# Determine the name of the environment variable that exposes the 176# cross-compiler prefix to the edk2 "build" utility. Print the result to the 177# standard output. 178# 179# Parameters: 180# $1: QEMU system emulation target 181qemu_edk2_get_cross_prefix_var() 182{ 183 local emulation_target="$1" 184 local edk2_toolchain 185 local edk2_arch 186 187 if ! edk2_toolchain=$(qemu_edk2_get_toolchain "$emulation_target"); then 188 return 1 189 fi 190 191 case "$emulation_target" in 192 (arm|aarch64) 193 if ! edk2_arch=$(qemu_edk2_get_arch "$emulation_target"); then 194 return 1 195 fi 196 printf '%s_%s_PREFIX\n' "$edk2_toolchain" "$edk2_arch" 197 ;; 198 (i386|x86_64) 199 printf '%s_BIN\n' "$edk2_toolchain" 200 ;; 201 esac 202} 203 204 205# Set and export the environment variable(s) necessary for cross-compilation, 206# whenever needed by the edk2 "build" utility. 207# 208# Parameters: 209# $1: QEMU system emulation target 210qemu_edk2_set_cross_env() 211{ 212 local emulation_target="$1" 213 local cross_prefix 214 local cross_prefix_var 215 216 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 217 return 1 218 fi 219 220 if [ -z "$cross_prefix" ]; then 221 # Nothing to do. 222 return 0 223 fi 224 225 if ! cross_prefix_var=$(qemu_edk2_get_cross_prefix_var \ 226 "$emulation_target"); then 227 return 1 228 fi 229 230 eval "export $cross_prefix_var=\$cross_prefix" 231} 232 233 234# Determine the "-n" option argument (that is, the number of modules to build 235# in parallel) for the edk2 "build" utility. Print the result to the standard 236# output. 237# 238# Parameters: 239# $1: the value of the MAKEFLAGS variable 240qemu_edk2_get_thread_count() 241{ 242 local makeflags="$1" 243 244 if [[ "$makeflags" == *--jobserver-auth=* ]] || 245 [[ "$makeflags" == *--jobserver-fds=* ]]; then 246 # If there is a job server, allow the edk2 "build" utility to parallelize 247 # as many module builds as there are logical CPUs in the system. The "make" 248 # instances forked by "build" are supposed to limit themselves through the 249 # job server. The zero value below causes the edk2 "build" utility to fetch 250 # the logical CPU count with Python's multiprocessing.cpu_count() method. 251 printf '0\n' 252 else 253 # Build a single module at a time. 254 printf '1\n' 255 fi 256} 257 258 259# Work around <https://bugzilla.tianocore.org/show_bug.cgi?id=1607> by 260# filtering jobserver-related flags out of MAKEFLAGS. Print the result to the 261# standard output. 262# 263# Parameters: 264# $1: the value of the MAKEFLAGS variable 265qemu_edk2_quirk_tianocore_1607() 266{ 267 local makeflags="$1" 268 269 printf %s "$makeflags" \ 270 | LC_ALL=C sed --regexp-extended \ 271 --expression='s/--jobserver-(auth|fds)=[0-9]+,[0-9]+//' \ 272 --expression='s/-j([0-9]+)?//' 273}