1#!/bin/bash
2#
3# Copyright (C) 2018 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
17#
18# !!! Keep up-to-date with var_cache.py
19#
20
21#
22# Provide a soong-build variable query mechanism that is cached
23# in the current process and any other subchild process that knows
24# how to parse the exported variable:
25#
26# export ART_TOOLS_BUILD_VAR_CACHE="..."
27#
28# Of the format:
29#
30#   <key1>='<value1>'\n
31#   <key2>='<value2>'\n
32#   ...
33#   <keyN>='<valueN>'
34#
35# Note: This is intentionally the same output format as
36#     build/soong/soong_ui.bash --dumpvars-mode --vars "key1 key2 ... keyN"
37#
38# For example, this would be a valid var-cache:
39#
40# export ART_TOOLS_BUILD_VAR_CACHE="ART_APEX_JARS='core-oj core-libart'"
41#
42# Calling into soong repeatedly is very slow; whenever it needs to be done
43# more than once, the var_cache.py or var_cache.sh script should be used instead.
44#
45
46# -------------------------------------------------------
47
48# Echoes the result of get_build_var <var_name>.
49# Var lookup is cached, subsequent var lookups in any child process
50# (that includes a var-cache is free). The var must be in 'var_list'
51# to participate in the cache.
52#
53# Example:
54#    local host_out="$(get_build_var HOST_OUT)"
55#
56# Note that build vars can often have spaces in them,
57# so the caller must take care to ensure space-correctness.
58get_build_var() {
59  local var_name="$1"
60
61  _var_cache_populate
62  _var_cache_build_dict
63
64  if [[ ${_VAR_CACHE_DICT[$var_name]+exists} ]]; then
65    echo "${_VAR_CACHE_DICT[$var_name]}"
66    return 0
67  else
68    echo "[ERROR] get_build_var: The variable '$var_name' is not in 'var_list', can't lookup." >&2
69    return 1
70  fi
71}
72
73# The above functions are "public" and are intentionally not exported.
74# User scripts must have "source var_cache.sh" to take advantage of caching.
75
76# -------------------------------------------------------
77# Below functions are "private";
78# do not call them outside of this file.
79
80_var_cache_populate() {
81  if [[ -n $ART_TOOLS_BUILD_VAR_CACHE ]]; then
82    _var_cache_debug "ART_TOOLS_BUILD_VAR_CACHE preset to (quotes added)..."
83    _var_cache_debug \""$ART_TOOLS_BUILD_VAR_CACHE"\"
84    return 0
85  fi
86
87  _var_cache_debug "Varcache missing... repopulate"
88
89  local this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
90  local top="$this_dir/../../.."
91
92  local interesting_vars=()
93  while read -r line; do
94    if [[ -z $line ]] || [[ $line == '#'* ]]; then
95      continue;
96    fi
97    interesting_vars+=($line)
98  done < "$this_dir"/var_list
99
100  _var_cache_debug "Interesting vars: " ${interesting_vars[@]}
101
102  local flat_vars="${interesting_vars[*]}"
103
104  local var_values
105  _var_cache_show_command "$top"/build/soong/soong_ui.bash --dumpvars-mode -vars=\"${interesting_vars[*]}\"
106
107  # Invoke soong exactly once for optimal performance.
108  # soong_ui.bash must be invoked from $ANDROID_BUILD_TOP or it gets confused and breaks.
109  var_values="$(cd "$top" && "$top"/build/soong/soong_ui.bash --dumpvars-mode -vars="$flat_vars")"
110
111  # Export the ART_TOOLS_BUILD_VAR_CACHE in the same format as soong_ui.bash --dumpvars-mode.
112  export ART_TOOLS_BUILD_VAR_CACHE="$var_values"
113
114  _var_cache_debug ART_TOOLS_BUILD_VAR_CACHE=\"$var_values\"
115}
116
117_var_cache_build_dict() {
118  if [[ ${#_VAR_CACHE_DICT[@]} -ne 0 ]]; then
119    # Associative arrays cannot be exported, have
120    # a separate step to reconstruct the associative
121    # array from a flat variable.
122    return 0
123  fi
124
125  # Parse $ART_TOOLS_BUILD_VAR_CACHE, e.g.
126  #   ART_APEX_JARS='core-oj core-libart conscrypt okhttp bouncycastle apache-xml'
127
128  local var_name
129  local var_value
130  local strip_quotes
131
132  _var_cache_debug "_var_cache_build_dict()"
133
134  declare -g -A _VAR_CACHE_DICT  # global associative array.
135  while IFS='=' read -r var_name var_value; do
136    if [[ -z $var_name ]]; then
137      # skip empty lines, e.g. blank newline at the end
138      continue
139    fi
140    _var_cache_debug "Var_name was $var_name"
141    _var_cache_debug "Var_value was $var_value"
142    strip_quotes=${var_value//\'/}
143    _VAR_CACHE_DICT["$var_name"]="$strip_quotes"
144  done < <(echo "$ART_TOOLS_BUILD_VAR_CACHE")
145
146  _var_cache_debug ${#_VAR_CACHE_DICT[@]} -eq 0
147}
148
149_var_cache_debug() {
150  if ((_var_cache_debug_enabled)); then
151    echo "[DBG]: " "$@" >&2
152  fi
153}
154
155_var_cache_show_command() {
156  if (( _var_cache_show_commands || _var_cache_debug_enabled)); then
157    echo "$@" >&2
158  fi
159}
160
161while true; do
162  case $1 in
163    --help)
164      echo "Usage: $0 [--debug] [--show-commands] [--dump-cache] [--var <name>] [--var <name2>...]"
165      echo ""
166      echo "Exposes a function 'get_build_var' which returns the result of"
167      echo "a soong build variable."
168      echo ""
169      echo "Primarily intended to be used as 'source var_cache.sh',"
170      echo "but also allows interactive command line usage for simplifying development."
171      exit 0
172      ;;
173    --var)
174      echo -ne "$2="
175      get_build_var "$2"
176      shift
177      ;;
178    --debug)
179      _var_cache_debug_enabled=1
180      ;;
181    --show-commands)
182      _var_cache_show_commands=1
183      ;;
184    --dump-cache)
185      _var_cache_populate
186      echo "ART_TOOLS_BUILD_VAR_CACHE=\"$ART_TOOLS_BUILD_VAR_CACHE\""
187      ;;
188    *)
189      break
190      ;;
191  esac
192  shift
193done
194