1# Copyright 2017, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
16import re
17import tempfile
18import subprocess
19
20_env = dict(os.environ)
21
22def _getEnvBoolean(var, default):
23  val = _env.get(var)
24  if val:
25    if val == "True" or val == "true":
26      return True
27    if val == "False" or val == "false":
28      return False
29  return default
30
31_DUMP_MANY_VARS_LIST = ['HOST_2ND_ARCH_PREFIX',
32                        'TARGET_2ND_ARCH',
33                        'TARGET_ARCH',
34                        'HOST_PREFER_32_BIT',
35                        'HOST_OUT_EXECUTABLES',
36                        'ANDROID_JAVA_TOOLCHAIN',
37                        'ANDROID_COMPILE_WITH_JACK',
38                        'USE_D8_BY_DEFAULT']
39_DUMP_MANY_VARS = None  # To be set to a dictionary with above list being the keys,
40                        # and the build variable being the value.
41def _dump_many_vars(var_name):
42  """
43  Reach into the Android build system to dump many build vars simultaneously.
44  Since the make system is so slow, we want to avoid calling into build frequently.
45  """
46  global _DUMP_MANY_VARS
47  global _DUMP_MANY_VARS_LIST
48
49  # Look up var from cache.
50  if _DUMP_MANY_VARS:
51    return _DUMP_MANY_VARS[var_name]
52
53  all_vars=" ".join(_DUMP_MANY_VARS_LIST)
54
55  # The command is taken from build/envsetup.sh to fetch build variables.
56  command = ("build/soong/soong_ui.bash --dumpvars-mode --vars=\"%s\"") % (all_vars)
57
58  config = subprocess.Popen(command,
59                            stdout=subprocess.PIPE,
60                            universal_newlines=True,
61                            shell=True,
62                            cwd=ANDROID_BUILD_TOP).communicate()[0] # read until EOF, select stdin
63  # Prints out something like:
64  # TARGET_ARCH='arm64'
65  # HOST_ARCH='x86_64'
66  _DUMP_MANY_VARS = {}
67  for line in config.split("\n"):
68    # Split out "$key='$value'" via regex.
69    match = re.search("([^=]+)='([^']*)", line)
70    if not match:
71      continue
72    key = match.group(1)
73    value = match.group(2)
74    _DUMP_MANY_VARS[key] = value
75
76  return _DUMP_MANY_VARS[var_name]
77
78def _get_build_var(var_name):
79  return _dump_many_vars(var_name)
80
81def _get_build_var_boolean(var, default):
82  val = _get_build_var(var)
83  if val:
84    if val == "True" or val == "true":
85      return True
86    if val == "False" or val == "false":
87      return False
88  return default
89
90def get_env(key):
91  return _env.get(key)
92
93def _get_android_build_top():
94  path_to_top = _env.get('ANDROID_BUILD_TOP')
95  if not path_to_top:
96    # nothing set. try to guess it based on the relative path of this env.py file.
97    this_file_path = os.path.realpath(__file__)
98    path_to_top = os.path.join(os.path.dirname(this_file_path), '../../../')
99    path_to_top = os.path.realpath(path_to_top)
100
101  if not os.path.exists(os.path.join(path_to_top, 'build/envsetup.sh')):
102    raise AssertionError("env.py must be located inside an android source tree")
103
104  return path_to_top
105
106ANDROID_BUILD_TOP = _get_android_build_top()
107
108# Compiling with jack? Possible values in (True, False, 'default')
109ANDROID_COMPILE_WITH_JACK = _get_build_var_boolean('ANDROID_COMPILE_WITH_JACK', 'default')
110
111# Follow the build system's D8 usage.
112USE_D8_BY_DEFAULT = _get_build_var_boolean('USE_D8_BY_DEFAULT', False)
113
114# Directory used for temporary test files on the host.
115ART_HOST_TEST_DIR = tempfile.mkdtemp(prefix = 'test-art-')
116
117# Keep going after encountering a test failure?
118ART_TEST_KEEP_GOING = _getEnvBoolean('ART_TEST_KEEP_GOING', True)
119
120# Do you want failed tests to have their artifacts cleaned up?
121ART_TEST_RUN_TEST_ALWAYS_CLEAN = _getEnvBoolean('ART_TEST_RUN_TEST_ALWAYS_CLEAN', True)
122
123ART_TEST_BISECTION = _getEnvBoolean('ART_TEST_BISECTION', False)
124
125DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get('DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
126
127# Do you want run-tests with the host/target's second arch?
128ART_TEST_RUN_TEST_2ND_ARCH = _getEnvBoolean('ART_TEST_RUN_TEST_2ND_ARCH', True)
129
130HOST_2ND_ARCH_PREFIX = _get_build_var('HOST_2ND_ARCH_PREFIX')
131HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get(
132  HOST_2ND_ARCH_PREFIX + 'DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
133
134ART_TEST_ANDROID_ROOT = _env.get('ART_TEST_ANDROID_ROOT')
135
136ART_TEST_WITH_STRACE = _getEnvBoolean('ART_TEST_DEBUG_GC', False)
137
138EXTRA_DISABLED_TESTS = set(_env.get("ART_TEST_RUN_TEST_SKIP", "").split())
139
140ART_TEST_RUN_TEST_BUILD = _getEnvBoolean('ART_TEST_RUN_TEST_BUILD', False)
141
142TARGET_2ND_ARCH = _get_build_var('TARGET_2ND_ARCH')
143TARGET_ARCH = _get_build_var('TARGET_ARCH')
144
145# Note: ART_2ND_PHONY_TEST_TARGET_SUFFIX is 2ND_ART_PHONY_TEST_TARGET_SUFFIX in .mk files
146# Note: ART_2ND_PHONY_TEST_HOST_SUFFIX is 2ND_ART_PHONY_HOST_TARGET_SUFFIX in .mk files
147# Python does not let us have variable names starting with a digit, so it has differ.
148
149if TARGET_2ND_ARCH:
150  if "64" in TARGET_ARCH:
151    ART_PHONY_TEST_TARGET_SUFFIX = "64"
152    ART_2ND_PHONY_TEST_TARGET_SUFFIX = "32"
153  else:
154    ART_PHONY_TEST_TARGET_SUFFIX = "32"
155    ART_2ND_PHONY_TEST_TARGET_SUFFIX = ""
156else:
157  if "64" in TARGET_ARCH:
158    ART_PHONY_TEST_TARGET_SUFFIX = "64"
159    ART_2ND_PHONY_TEST_TARGET_SUFFIX = ""
160  else:
161    ART_PHONY_TEST_TARGET_SUFFIX = "32"
162    ART_2ND_PHONY_TEST_TARGET_SUFFIX = ""
163
164HOST_PREFER_32_BIT = _get_build_var('HOST_PREFER_32_BIT')
165if HOST_PREFER_32_BIT == "true":
166  ART_PHONY_TEST_HOST_SUFFIX = "32"
167  ART_2ND_PHONY_TEST_HOST_SUFFIX = ""
168else:
169  ART_PHONY_TEST_HOST_SUFFIX = "64"
170  ART_2ND_PHONY_TEST_HOST_SUFFIX = "32"
171
172HOST_OUT_EXECUTABLES = os.path.join(ANDROID_BUILD_TOP,
173                                    _get_build_var("HOST_OUT_EXECUTABLES"))
174
175# Set up default values for $JACK, $DX, $SMALI, etc to the $HOST_OUT_EXECUTABLES/$name path.
176for tool in ['jack', 'dx', 'smali', 'jasmin', 'dxmerger']:
177  binary = tool if tool != 'dxmerger' else 'dexmerger'
178  os.environ.setdefault(tool.upper(), HOST_OUT_EXECUTABLES + '/' + binary)
179
180ANDROID_JAVA_TOOLCHAIN = os.path.join(ANDROID_BUILD_TOP,
181                                     _get_build_var('ANDROID_JAVA_TOOLCHAIN'))
182
183# include platform prebuilt java, javac, etc in $PATH.
184os.environ['PATH'] = ANDROID_JAVA_TOOLCHAIN + ':' + os.environ['PATH']
185