1#!/bin/bash 2# 3# Copyright (C) 2017 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17if [[ ! -d art ]]; then 18 echo "Script needs to be run at the root of the android tree" 19 exit 1 20fi 21 22ALL_CONFIGS=(linux-ia32 linux-x64 linux-armv8 linux-armv7 android-armv8 android-armv7) 23 24usage() { 25 local config 26 local golem_target 27 28 (cat << EOF 29 Usage: $(basename "${BASH_SOURCE[0]}") [--golem=<target>] --machine-type=MACHINE_TYPE 30 [--tarball[=<target>.tar.gz]] 31 32 Build minimal art binaries required to run golem benchmarks either 33 locally or on the golem servers. 34 35 Creates the \$MACHINE_TYPE binaries in your \$OUT_DIR, and if --tarball was specified, 36 it also tars the results of the build together into your <target.tar.gz> file. 37 -------------------------------------------------------- 38 Required Flags: 39 --machine-type=MT Specify the machine type that will be built. 40 41 Optional Flags": 42 --golem=<target> Builds with identical commands that Golem servers use. 43 --tarball[=o.tgz] Tar/gz the results. File name defaults to <machine_type>.tar.gz 44 -j<num> Specify how many jobs to use for parallelism. 45 --help Print this help listing. 46 --showcommands Show commands as they are being executed. 47 --simulate Print commands only, don't execute commands. 48EOF 49 ) | sed -e 's/^[[:space:]][[:space:]]//g' >&2 # Strip leading whitespace from heredoc. 50 51 echo >&2 "Available machine types:" 52 for config in "${ALL_CONFIGS[@]}"; do 53 echo >&2 " $config" 54 done 55 56 echo >&2 57 echo >&2 "Available Golem targets:" 58 while IFS='' read -r golem_target; do 59 echo >&2 " $golem_target" 60 done < <("$(thisdir)/env" --list-targets) 61} 62 63# Check if $1 element is in array $2 64contains_element() { 65 local e 66 for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done 67 return 1 68} 69 70# Display a command, but don't execute it, if --showcommands was set. 71show_command() { 72 if [[ $showcommands == "showcommands" ]]; then 73 echo "$@" 74 fi 75} 76 77# Execute a command, displaying it if --showcommands was set. 78# If --simulate is used, command is not executed. 79execute() { 80 show_command "$@" 81 execute_noshow "$@" 82} 83 84# Execute a command unless --simulate was used. 85execute_noshow() { 86 if [[ $simulate == "simulate" ]]; then 87 return 0 88 fi 89 90 local prog="$1" 91 shift 92 "$prog" "$@" 93} 94 95# Export environment variable, echoing it to screen. 96setenv() { 97 local name="$1" 98 local value="$2" 99 100 export $name="$value" 101 echo export $name="$value" 102} 103 104# Export environment variable, echoing $3 to screen ($3 is meant to be unevaluated). 105setenv_escape() { 106 local name="$1" 107 local value="$2" 108 local escaped_value="$3" 109 110 export $name="$value" 111 echo export $name="$escaped_value" 112} 113 114log_usage_error() { 115 echo >&2 "ERROR: " "$@" 116 echo >&2 " See --help for the correct usage information." 117 exit 1 118} 119 120log_fatal() { 121 echo >&2 "FATAL: " "$@" 122 exit 2 123} 124 125# Get the directory of this script. 126thisdir() { 127 (\cd "$(dirname "${BASH_SOURCE[0]}")" && pwd ) 128} 129 130# Get the path to the top of the Android source tree. 131gettop() { 132 if [[ "x$ANDROID_BUILD_TOP" != "x" ]]; then 133 echo "$ANDROID_BUILD_TOP"; 134 else 135 echo "$(thisdir)/../../.." 136 fi 137} 138 139# Get a build variable from the Android build system. 140get_build_var() { 141 local varname="$1" 142 143 # include the desired target product/build-variant 144 # which won't be set in our env if neither we nor the user first executed 145 # source build/envsetup.sh (e.g. if simulating from a fresh shell). 146 local extras 147 [[ -n $target_product ]] && extras+=" TARGET_PRODUCT=$target_product" 148 [[ -n $target_build_variant ]] && extras+=" TARGET_BUILD_VARIANT=$target_build_variant" 149 150 # call dumpvar-$name from the makefile system. 151 (\cd "$(gettop)"; 152 CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ 153 command make --no-print-directory -f build/core/config.mk \ 154 $extras \ 155 dumpvar-$varname) 156} 157 158# Defaults from command-line. 159 160mode="" # blank or 'golem' if --golem was specified. 161golem_target="" # --golem=$golem_target 162config="" # --machine-type=$config 163j_arg="-j8" 164showcommands="" 165simulate="" 166make_tarball="" 167tarball="" 168 169# Parse command line arguments 170 171while [[ "$1" != "" ]]; do 172 case "$1" in 173 --help) 174 usage 175 exit 1 176 ;; 177 --golem=*) 178 mode="golem" 179 golem_target="${1##--golem=}" 180 181 if [[ "x$golem_target" == x ]]; then 182 log_usage_error "Missing --golem target type." 183 fi 184 185 shift 186 ;; 187 --machine-type=*) 188 config="${1##--machine-type=}" 189 if ! contains_element "$config" "${ALL_CONFIGS[@]}"; then 190 log_usage_error "Invalid --machine-type value '$config'" 191 fi 192 shift 193 ;; 194 --tarball) 195 tarball="" # reuse the machine type name. 196 make_tarball="make_tarball" 197 shift 198 ;; 199 --tarball=*) 200 tarball="${1##--tarball=}" 201 make_tarball="make_tarball" 202 shift 203 ;; 204 -j*) 205 j_arg="$1" 206 shift 207 ;; 208 --showcommands) 209 showcommands="showcommands" 210 shift 211 ;; 212 --simulate) 213 simulate="simulate" 214 shift 215 ;; 216 *) 217 log_usage_error "Unknown options $1" 218 ;; 219 esac 220done 221 222################################### 223################################### 224################################### 225 226if [[ -z $config ]]; then 227 log_usage_error "--machine-type option is required." 228fi 229 230# --tarball defaults to the --machine-type value with .tar.gz. 231tarball="${tarball:-$config.tar.gz}" 232 233target_product="$TARGET_PRODUCT" 234target_build_variant="$TARGET_BUILD_VARIANT" 235 236# If not using --golem, use whatever the user had lunch'd prior to this script. 237if [[ $mode == "golem" ]]; then 238 # This section is intended solely to be executed by a golem build server. 239 240 target_build_variant=eng 241 case "$config" in 242 *-armv7) 243 target_product="arm_krait" 244 ;; 245 *-armv8) 246 target_product="armv8" 247 ;; 248 *) 249 target_product="sdk" 250 ;; 251 esac 252 253 if [[ $target_product = arm* ]]; then 254 # If using the regular manifest, e.g. 'master' 255 # The lunch command for arm will assuredly fail because we don't have device/generic/art. 256 # 257 # Print a human-readable error message instead of trying to lunch and failing there. 258 if ! [[ -d "$(gettop)/device/generic/art" ]]; then 259 log_fatal "Missing device/generic/art directory. Perhaps try master-art repo manifest?\n" \ 260 " Cannot build ARM targets (arm_krait, armv8) for Golem." >&2 261 fi 262 # We could try to keep on simulating but it seems brittle because we won't have the proper 263 # build variables to output the right strings. 264 fi 265 266 # Get this particular target's environment variables (e.g. ART read barrier on/off). 267 source "$(thisdir)"/env "$golem_target" || exit 1 268 269 lunch_target="$target_product-$target_build_variant" 270 271 execute 'source' build/envsetup.sh 272 # Build generic targets (as opposed to something specific like aosp_angler-eng). 273 execute lunch "$lunch_target" 274 setenv JACK_SERVER false 275 setenv_escape JACK_REPOSITORY "$PWD/prebuilts/sdk/tools/jacks" '$PWD/prebuilts/sdk/tools/jacks' 276 # Golem uses master-art repository which is missing a lot of other libraries. 277 setenv SOONG_ALLOW_MISSING_DEPENDENCIES true 278 # Golem may be missing tools such as javac from its path. 279 setenv_escape PATH "/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH" '/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH' 280else 281 # Look up the default variables from the build system if they weren't set already. 282 [[ -z $target_product ]] && target_product="$(get_build_var TARGET_PRODUCT)" 283 [[ -z $target_build_variant ]] && target_build_variant="$(get_build_var TARGET_BUILD_VARIANT)" 284fi 285 286# Defaults for all machine types. 287make_target="build-art-target-golem" 288out_dir="out/x86_64" 289root_dir_var="PRODUCT_OUT" 290strip_symbols=false 291bit64_suffix="" 292tar_directories=(system data/art-test) 293 294# Per-machine type overrides 295if [[ $config == linux-arm* ]]; then 296 setenv ART_TARGET_LINUX true 297fi 298 299case "$config" in 300 linux-ia32|linux-x64) 301 root_dir_var="HOST_OUT" 302 # Android strips target builds automatically, but not host builds. 303 strip_symbols=true 304 make_target="build-art-host-golem" 305 306 if [[ $config == linux-ia32 ]]; then 307 out_dir="out/x86" 308 setenv HOST_PREFER_32_BIT true 309 else 310 bit64_suffix="64" 311 fi 312 313 tar_directories=(bin framework usr lib${bit64_suffix}) 314 ;; 315 *-armv8) 316 bit64_suffix="64" 317 ;; 318 *-armv7) 319 ;; 320 *) 321 log_fatal "Unsupported machine-type '$config'" 322esac 323 324# Golem benchmark run commands expect a certain $OUT_DIR to be set, 325# so specify it here. 326# 327# Note: It is questionable if we want to customize this since users 328# could alternatively probably use their own build directly (and forgo this script). 329setenv OUT_DIR "$out_dir" 330root_dir="$(get_build_var "$root_dir_var")" 331 332if [[ $mode == "golem" ]]; then 333 # For golem-style running only. 334 # Sets the DT_INTERP to this path in every .so we can run the 335 # non-system version of dalvikvm with our own copies of the dependencies (e.g. our own libc++). 336 if [[ $config == android-* ]]; then 337 # TODO: the linker can be relative to the binaries 338 # (which is what we do for linux-armv8 and linux-armv7) 339 golem_run_path="/data/local/tmp/runner/" 340 else 341 golem_run_path="" 342 fi 343 344 # Only do this for target builds. Host doesn't need this. 345 if [[ $config == *-arm* ]]; then 346 setenv CUSTOM_TARGET_LINKER "${golem_run_path}${root_dir}/system/bin/linker${bit64_suffix}" 347 fi 348fi 349 350# 351# Main command execution below here. 352# (everything prior to this just sets up environment variables, 353# and maybe calls lunch). 354# 355 356execute make "${j_arg}" "${make_target}" 357 358if $strip_symbols; then 359 # Further reduce size by stripping symbols. 360 execute_noshow strip $root_dir/bin/* || true 361 show_command strip $root_dir/bin/'*' '|| true' 362 execute_noshow strip $root_dir/lib${bit64_suffix}/'*' 363 show_command strip $root_dir/lib${bit64_suffix}/'*' 364fi 365 366if [[ "$make_tarball" == "make_tarball" ]]; then 367 # Create a tarball which is required for the golem build resource. 368 # (In particular, each golem benchmark's run commands depend on a list of resource files 369 # in order to have all the files it needs to actually execute, 370 # and this tarball would satisfy that particular target+machine-type's requirements). 371 dirs_rooted=() 372 for tar_dir in "${tar_directories[@]}"; do 373 dirs_rooted+=("$root_dir/$tar_dir") 374 done 375 376 execute tar -czf "${tarball}" "${dirs_rooted[@]}" --exclude .git --exclude .gitignore 377 tar_result=$? 378 if [[ $tar_result -ne 0 ]]; then 379 [[ -f $tarball ]] && rm $tarball 380 fi 381 382 show_command '[[ $? -ne 0 ]] && rm' "$tarball" 383fi 384 385