Home | History | Annotate | Line # | Download | only in test
      1 #===----------------------------------------------------------------------===##
      2 #
      3 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 # See https://llvm.org/LICENSE.txt for license information.
      5 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 #
      7 #===----------------------------------------------------------------------===##
      8 
      9 import copy
     10 import os
     11 import pkgutil
     12 import pipes
     13 import re
     14 import shlex
     15 import shutil
     16 import sys
     17 
     18 from libcxx.compiler import CXXCompiler
     19 from libcxx.test.target_info import make_target_info
     20 import libcxx.util
     21 import libcxx.test.features
     22 import libcxx.test.newconfig
     23 import libcxx.test.params
     24 
     25 def loadSiteConfig(lit_config, config, param_name, env_name):
     26     # We haven't loaded the site specific configuration (the user is
     27     # probably trying to run on a test file directly, and either the site
     28     # configuration hasn't been created by the build system, or we are in an
     29     # out-of-tree build situation).
     30     site_cfg = lit_config.params.get(param_name,
     31                                      os.environ.get(env_name))
     32     if not site_cfg:
     33         lit_config.warning('No site specific configuration file found!'
     34                            ' Running the tests in the default configuration.')
     35     elif not os.path.isfile(site_cfg):
     36         lit_config.fatal(
     37             "Specified site configuration file does not exist: '%s'" %
     38             site_cfg)
     39     else:
     40         lit_config.note('using site specific configuration at %s' % site_cfg)
     41         ld_fn = lit_config.load_config
     42 
     43         # Null out the load_config function so that lit.site.cfg doesn't
     44         # recursively load a config even if it tries.
     45         # TODO: This is one hell of a hack. Fix it.
     46         def prevent_reload_fn(*args, **kwargs):
     47             pass
     48         lit_config.load_config = prevent_reload_fn
     49         ld_fn(config, site_cfg)
     50         lit_config.load_config = ld_fn
     51 
     52 # Extract the value of a numeric macro such as __cplusplus or a feature-test
     53 # macro.
     54 def intMacroValue(token):
     55     return int(token.rstrip('LlUu'))
     56 
     57 class Configuration(object):
     58     # pylint: disable=redefined-outer-name
     59     def __init__(self, lit_config, config):
     60         self.lit_config = lit_config
     61         self.config = config
     62         self.cxx = None
     63         self.cxx_is_clang_cl = None
     64         self.cxx_stdlib_under_test = None
     65         self.project_obj_root = None
     66         self.libcxx_src_root = None
     67         self.libcxx_obj_root = None
     68         self.cxx_library_root = None
     69         self.cxx_runtime_root = None
     70         self.abi_library_root = None
     71         self.link_shared = self.get_lit_bool('enable_shared', default=True)
     72         self.debug_build = self.get_lit_bool('debug_build',   default=False)
     73         self.exec_env = dict()
     74         self.use_clang_verify = False
     75 
     76     def get_lit_conf(self, name, default=None):
     77         val = self.lit_config.params.get(name, None)
     78         if val is None:
     79             val = getattr(self.config, name, None)
     80             if val is None:
     81                 val = default
     82         return val
     83 
     84     def get_lit_bool(self, name, default=None, env_var=None):
     85         def check_value(value, var_name):
     86             if value is None:
     87                 return default
     88             if isinstance(value, bool):
     89                 return value
     90             if not isinstance(value, str):
     91                 raise TypeError('expected bool or string')
     92             if value.lower() in ('1', 'true'):
     93                 return True
     94             if value.lower() in ('', '0', 'false'):
     95                 return False
     96             self.lit_config.fatal(
     97                 "parameter '{}' should be true or false".format(var_name))
     98 
     99         conf_val = self.get_lit_conf(name)
    100         if env_var is not None and env_var in os.environ and \
    101                 os.environ[env_var] is not None:
    102             val = os.environ[env_var]
    103             if conf_val is not None:
    104                 self.lit_config.warning(
    105                     'Environment variable %s=%s is overriding explicit '
    106                     '--param=%s=%s' % (env_var, val, name, conf_val))
    107             return check_value(val, env_var)
    108         return check_value(conf_val, name)
    109 
    110     def make_static_lib_name(self, name):
    111         """Return the full filename for the specified library name"""
    112         if self.target_info.is_windows() and not self.target_info.is_mingw():
    113             assert name == 'c++'  # Only allow libc++ to use this function for now.
    114             return 'lib' + name + '.lib'
    115         else:
    116             return 'lib' + name + '.a'
    117 
    118     def configure(self):
    119         self.target_info = make_target_info(self)
    120         self.executor = self.get_lit_conf('executor')
    121         self.configure_cxx()
    122         self.configure_src_root()
    123         self.configure_obj_root()
    124         self.cxx_stdlib_under_test = self.get_lit_conf('cxx_stdlib_under_test', 'libc++')
    125         self.cxx_library_root = self.get_lit_conf('cxx_library_root', self.libcxx_obj_root)
    126         self.abi_library_root = self.get_lit_conf('abi_library_root') or self.cxx_library_root
    127         self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root', self.cxx_library_root)
    128         self.abi_runtime_root = self.get_lit_conf('abi_runtime_root', self.abi_library_root)
    129         self.configure_compile_flags()
    130         self.configure_link_flags()
    131         self.configure_env()
    132         self.configure_coverage()
    133         self.configure_modules()
    134         self.configure_substitutions()
    135         self.configure_features()
    136 
    137         libcxx.test.newconfig.configure(
    138             libcxx.test.params.DEFAULT_PARAMETERS,
    139             libcxx.test.features.DEFAULT_FEATURES,
    140             self.config,
    141             self.lit_config
    142         )
    143 
    144         self.lit_config.note("All available features: {}".format(self.config.available_features))
    145 
    146     def print_config_info(self):
    147         if self.cxx.use_modules:
    148             self.lit_config.note('Using modules flags: %s' %
    149                                  self.cxx.modules_flags)
    150         if len(self.cxx.warning_flags):
    151             self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags)
    152         show_env_vars = {}
    153         for k,v in self.exec_env.items():
    154             if k not in os.environ or os.environ[k] != v:
    155                 show_env_vars[k] = v
    156         self.lit_config.note('Adding environment variables: %r' % show_env_vars)
    157         self.lit_config.note("Linking against the C++ Library at {}".format(self.cxx_library_root))
    158         self.lit_config.note("Running against the C++ Library at {}".format(self.cxx_runtime_root))
    159         self.lit_config.note("Linking against the ABI Library at {}".format(self.abi_library_root))
    160         self.lit_config.note("Running against the ABI Library at {}".format(self.abi_runtime_root))
    161         sys.stderr.flush()  # Force flushing to avoid broken output on Windows
    162 
    163     def get_test_format(self):
    164         from libcxx.test.format import LibcxxTestFormat
    165         return LibcxxTestFormat(
    166             self.cxx,
    167             self.use_clang_verify,
    168             self.executor,
    169             exec_env=self.exec_env)
    170 
    171     def configure_cxx(self):
    172         # Gather various compiler parameters.
    173         cxx = self.get_lit_conf('cxx_under_test')
    174         self.cxx_is_clang_cl = cxx is not None and \
    175                                os.path.basename(cxx).startswith('clang-cl')
    176         # If no specific cxx_under_test was given, attempt to infer it as
    177         # clang++.
    178         if cxx is None or self.cxx_is_clang_cl:
    179             search_paths = self.config.environment['PATH']
    180             if cxx is not None and os.path.isabs(cxx):
    181                 search_paths = os.path.dirname(cxx)
    182             clangxx = libcxx.util.which('clang++', search_paths)
    183             if clangxx:
    184                 cxx = clangxx
    185                 self.lit_config.note(
    186                     "inferred cxx_under_test as: %r" % cxx)
    187             elif self.cxx_is_clang_cl:
    188                 self.lit_config.fatal('Failed to find clang++ substitution for'
    189                                       ' clang-cl')
    190         if not cxx:
    191             self.lit_config.fatal('must specify user parameter cxx_under_test '
    192                                   '(e.g., --param=cxx_under_test=clang++)')
    193         self.cxx = CXXCompiler(self, cxx) if not self.cxx_is_clang_cl else \
    194                    self._configure_clang_cl(cxx)
    195         self.cxx.compile_env = dict(os.environ)
    196 
    197     def _configure_clang_cl(self, clang_path):
    198         def _split_env_var(var):
    199             return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()]
    200 
    201         def _prefixed_env_list(var, prefix):
    202             from itertools import chain
    203             return list(chain.from_iterable((prefix, path) for path in _split_env_var(var)))
    204 
    205         assert self.cxx_is_clang_cl
    206         flags = []
    207         compile_flags = []
    208         link_flags = _prefixed_env_list('LIB', '-L')
    209         return CXXCompiler(self, clang_path, flags=flags,
    210                            compile_flags=compile_flags,
    211                            link_flags=link_flags)
    212 
    213     def configure_src_root(self):
    214         self.libcxx_src_root = self.get_lit_conf(
    215             'libcxx_src_root', os.path.dirname(self.config.test_source_root))
    216 
    217     def configure_obj_root(self):
    218         self.project_obj_root = self.get_lit_conf('project_obj_root')
    219         self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root')
    220         if not self.libcxx_obj_root and self.project_obj_root is not None:
    221             possible_roots = [
    222                 os.path.join(self.project_obj_root, 'libcxx'),
    223                 os.path.join(self.project_obj_root, 'projects', 'libcxx'),
    224                 os.path.join(self.project_obj_root, 'runtimes', 'libcxx'),
    225             ]
    226             for possible_root in possible_roots:
    227                 if os.path.isdir(possible_root):
    228                     self.libcxx_obj_root = possible_root
    229                     break
    230             else:
    231                 self.libcxx_obj_root = self.project_obj_root
    232 
    233     def configure_features(self):
    234         additional_features = self.get_lit_conf('additional_features')
    235         if additional_features:
    236             for f in additional_features.split(','):
    237                 self.config.available_features.add(f.strip())
    238 
    239         if self.target_info.is_windows():
    240             if self.cxx_stdlib_under_test == 'libc++':
    241                 # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
    242                 # initial Windows failures until they can be properly diagnosed
    243                 # and fixed. This allows easier detection of new test failures
    244                 # and regressions. Note: New failures should not be suppressed
    245                 # using this feature. (Also see llvm.org/PR32730)
    246                 self.config.available_features.add('LIBCXX-WINDOWS-FIXME')
    247 
    248     def configure_compile_flags(self):
    249         self.configure_default_compile_flags()
    250         # Configure extra flags
    251         compile_flags_str = self.get_lit_conf('compile_flags', '')
    252         self.cxx.compile_flags += shlex.split(compile_flags_str)
    253         if self.target_info.is_windows():
    254             self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS']
    255             # Don't warn about using common but nonstandard unprefixed functions
    256             # like chdir, fileno.
    257             self.cxx.compile_flags += ['-D_CRT_NONSTDC_NO_WARNINGS']
    258             # Build the tests in the same configuration as libcxx itself,
    259             # to avoid mismatches if linked statically.
    260             self.cxx.compile_flags += ['-D_CRT_STDIO_ISO_WIDE_SPECIFIERS']
    261             # Required so that tests using min/max don't fail on Windows,
    262             # and so that those tests don't have to be changed to tolerate
    263             # this insanity.
    264             self.cxx.compile_flags += ['-DNOMINMAX']
    265         additional_flags = self.get_lit_conf('test_compiler_flags')
    266         if additional_flags:
    267             self.cxx.compile_flags += shlex.split(additional_flags)
    268 
    269     def configure_default_compile_flags(self):
    270         # Configure include paths
    271         self.configure_compile_flags_header_includes()
    272         self.target_info.add_cxx_compile_flags(self.cxx.compile_flags)
    273         self.target_info.add_cxx_flags(self.cxx.flags)
    274         # Configure feature flags.
    275         enable_32bit = self.get_lit_bool('enable_32bit', False)
    276         if enable_32bit:
    277             self.cxx.flags += ['-m32']
    278         # Use verbose output for better errors
    279         self.cxx.flags += ['-v']
    280         sysroot = self.get_lit_conf('sysroot')
    281         if sysroot:
    282             self.cxx.flags += ['--sysroot=' + sysroot]
    283         gcc_toolchain = self.get_lit_conf('gcc_toolchain')
    284         if gcc_toolchain:
    285             self.cxx.flags += ['--gcc-toolchain=' + gcc_toolchain]
    286         # NOTE: the _DEBUG definition must preceed the triple check because for
    287         # the Windows build of libc++, the forced inclusion of a header requires
    288         # that _DEBUG is defined.  Incorrect ordering will result in -target
    289         # being elided.
    290         if self.target_info.is_windows() and self.debug_build:
    291             self.cxx.compile_flags += ['-D_DEBUG']
    292 
    293         # Add includes for support headers used in the tests.
    294         support_path = os.path.join(self.libcxx_src_root, 'test/support')
    295         self.cxx.compile_flags += ['-I' + support_path]
    296 
    297         # On GCC, the libc++ headers cause errors due to throw() decorators
    298         # on operator new clashing with those from the test suite, so we
    299         # don't enable warnings in system headers on GCC.
    300         if self.cxx.type != 'gcc':
    301             self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER']
    302 
    303         # Add includes for the PSTL headers
    304         pstl_src_root = self.get_lit_conf('pstl_src_root')
    305         pstl_obj_root = self.get_lit_conf('pstl_obj_root')
    306         if pstl_src_root is not None and pstl_obj_root is not None:
    307             self.cxx.compile_flags += ['-I' + os.path.join(pstl_src_root, 'include')]
    308             self.cxx.compile_flags += ['-I' + os.path.join(pstl_obj_root, 'generated_headers')]
    309             self.cxx.compile_flags += ['-I' + os.path.join(pstl_src_root, 'test')]
    310             self.config.available_features.add('parallel-algorithms')
    311 
    312     def configure_compile_flags_header_includes(self):
    313         support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
    314         if self.cxx_stdlib_under_test != 'libstdc++' and \
    315            not self.target_info.is_windows() and \
    316            not self.target_info.is_zos():
    317             self.cxx.compile_flags += [
    318                 '-include', os.path.join(support_path, 'nasty_macros.h')]
    319         if self.cxx_stdlib_under_test == 'msvc':
    320             self.cxx.compile_flags += [
    321                 '-include', os.path.join(support_path,
    322                                          'msvc_stdlib_force_include.h')]
    323             pass
    324         if self.target_info.is_windows() and self.debug_build and \
    325                 self.cxx_stdlib_under_test != 'msvc':
    326             self.cxx.compile_flags += [
    327                 '-include', os.path.join(support_path,
    328                                          'set_windows_crt_report_mode.h')
    329             ]
    330         cxx_headers = self.get_lit_conf('cxx_headers')
    331         if cxx_headers is None and self.cxx_stdlib_under_test != 'libc++':
    332             self.lit_config.note('using the system cxx headers')
    333             return
    334         self.cxx.compile_flags += ['-nostdinc++']
    335         if not os.path.isdir(cxx_headers):
    336             self.lit_config.fatal("cxx_headers='{}' is not a directory.".format(cxx_headers))
    337         (path, version) = os.path.split(cxx_headers)
    338         (path, cxx) = os.path.split(path)
    339         triple = self.get_lit_conf('target_triple', None)
    340         if triple is not None:
    341             cxx_target_headers = os.path.join(path, triple, cxx, version)
    342             if os.path.isdir(cxx_target_headers):
    343                 self.cxx.compile_flags += ['-I' + cxx_target_headers]
    344         self.cxx.compile_flags += ['-I' + cxx_headers]
    345         if self.libcxx_obj_root is not None:
    346             cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include',
    347                                           'c++build')
    348             if os.path.isdir(cxxabi_headers):
    349                 self.cxx.compile_flags += ['-I' + cxxabi_headers]
    350 
    351     def configure_link_flags(self):
    352         # Configure library path
    353         self.configure_link_flags_cxx_library_path()
    354         self.configure_link_flags_abi_library_path()
    355 
    356         # Configure libraries
    357         if self.cxx_stdlib_under_test == 'libc++':
    358             if self.target_info.is_mingw():
    359                 self.cxx.link_flags += ['-nostdlib++']
    360             else:
    361                 self.cxx.link_flags += ['-nodefaultlibs']
    362             # FIXME: Handle MSVCRT as part of the ABI library handling.
    363             if self.target_info.is_windows() and not self.target_info.is_mingw():
    364                 self.cxx.link_flags += ['-nostdlib']
    365             self.configure_link_flags_cxx_library()
    366             self.configure_link_flags_abi_library()
    367             self.configure_extra_library_flags()
    368         elif self.cxx_stdlib_under_test == 'libstdc++':
    369             self.cxx.link_flags += ['-lstdc++fs', '-lm', '-pthread']
    370         elif self.cxx_stdlib_under_test == 'msvc':
    371             # FIXME: Correctly setup debug/release flags here.
    372             pass
    373         elif self.cxx_stdlib_under_test == 'cxx_default':
    374             self.cxx.link_flags += ['-pthread']
    375         else:
    376             self.lit_config.fatal('invalid stdlib under test')
    377 
    378         link_flags_str = self.get_lit_conf('link_flags', '')
    379         self.cxx.link_flags += shlex.split(link_flags_str)
    380 
    381     def configure_link_flags_cxx_library_path(self):
    382         if self.cxx_library_root:
    383             self.cxx.link_flags += ['-L' + self.cxx_library_root]
    384             if self.target_info.is_windows() and self.link_shared:
    385                 self.add_path(self.cxx.compile_env, self.cxx_library_root)
    386         if self.cxx_runtime_root:
    387             if not self.target_info.is_windows():
    388                 self.cxx.link_flags += ['-Wl,-rpath,' +
    389                                         self.cxx_runtime_root]
    390             elif self.target_info.is_windows() and self.link_shared:
    391                 self.add_path(self.exec_env, self.cxx_runtime_root)
    392         additional_flags = self.get_lit_conf('test_linker_flags')
    393         if additional_flags:
    394             self.cxx.link_flags += shlex.split(additional_flags)
    395 
    396     def configure_link_flags_abi_library_path(self):
    397         # Configure ABI library paths.
    398         if self.abi_library_root:
    399             self.cxx.link_flags += ['-L' + self.abi_library_root]
    400         if self.abi_runtime_root:
    401             if not self.target_info.is_windows():
    402                 self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_runtime_root]
    403             else:
    404                 self.add_path(self.exec_env, self.abi_runtime_root)
    405 
    406     def configure_link_flags_cxx_library(self):
    407         if self.link_shared:
    408             self.cxx.link_flags += ['-lc++']
    409         else:
    410             if self.cxx_library_root:
    411                 libname = self.make_static_lib_name('c++')
    412                 abs_path = os.path.join(self.cxx_library_root, libname)
    413                 assert os.path.exists(abs_path) and \
    414                        "static libc++ library does not exist"
    415                 self.cxx.link_flags += [abs_path]
    416             else:
    417                 self.cxx.link_flags += ['-lc++']
    418 
    419     def configure_link_flags_abi_library(self):
    420         cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
    421         if cxx_abi == 'libstdc++':
    422             self.cxx.link_flags += ['-lstdc++']
    423         elif cxx_abi == 'libsupc++':
    424             self.cxx.link_flags += ['-lsupc++']
    425         elif cxx_abi == 'libcxxabi':
    426             # If the C++ library requires explicitly linking to libc++abi, or
    427             # if we're testing libc++abi itself (the test configs are shared),
    428             # then link it.
    429             testing_libcxxabi = self.get_lit_conf('name', '') == 'libc++abi'
    430             if self.target_info.allow_cxxabi_link() or testing_libcxxabi:
    431                 libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True)
    432                 if libcxxabi_shared:
    433                     self.cxx.link_flags += ['-lc++abi']
    434                 else:
    435                     if self.abi_library_root:
    436                         libname = self.make_static_lib_name('c++abi')
    437                         abs_path = os.path.join(self.abi_library_root, libname)
    438                         self.cxx.link_flags += [abs_path]
    439                     else:
    440                         self.cxx.link_flags += ['-lc++abi']
    441         elif cxx_abi == 'libcxxrt':
    442             self.cxx.link_flags += ['-lcxxrt']
    443         elif cxx_abi == 'vcruntime':
    444             debug_suffix = 'd' if self.debug_build else ''
    445             # This matches the set of libraries linked in the toplevel
    446             # libcxx CMakeLists.txt if building targeting msvc.
    447             self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in
    448                                     ['vcruntime', 'ucrt', 'msvcrt', 'msvcprt']]
    449             # The compiler normally links in oldnames.lib too, but we've
    450             # specified -nostdlib above, so we need to specify it manually.
    451             self.cxx.link_flags += ['-loldnames']
    452         elif cxx_abi == 'none' or cxx_abi == 'default':
    453             if self.target_info.is_windows():
    454                 debug_suffix = 'd' if self.debug_build else ''
    455                 self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
    456         else:
    457             self.lit_config.fatal(
    458                 'C++ ABI setting %s unsupported for tests' % cxx_abi)
    459 
    460     def configure_extra_library_flags(self):
    461         if self.get_lit_bool('cxx_ext_threads', default=False):
    462             self.cxx.link_flags += ['-lc++external_threads']
    463         self.target_info.add_cxx_link_flags(self.cxx.link_flags)
    464 
    465     def configure_coverage(self):
    466         self.generate_coverage = self.get_lit_bool('generate_coverage', False)
    467         if self.generate_coverage:
    468             self.cxx.flags += ['-g', '--coverage']
    469             self.cxx.compile_flags += ['-O0']
    470 
    471     def configure_modules(self):
    472         modules_flags = ['-fmodules', '-Xclang', '-fmodules-local-submodule-visibility']
    473         supports_modules = self.cxx.hasCompileFlag(modules_flags)
    474         enable_modules = self.get_lit_bool('enable_modules', default=False,
    475                                                              env_var='LIBCXX_ENABLE_MODULES')
    476         if enable_modules and not supports_modules:
    477             self.lit_config.fatal(
    478                 '-fmodules is enabled but not supported by the compiler')
    479         if not supports_modules:
    480             return
    481         module_cache = os.path.join(self.config.test_exec_root,
    482                                    'modules.cache')
    483         module_cache = os.path.realpath(module_cache)
    484         if os.path.isdir(module_cache):
    485             shutil.rmtree(module_cache)
    486         os.makedirs(module_cache)
    487         self.cxx.modules_flags += modules_flags + \
    488             ['-fmodules-cache-path=' + module_cache]
    489         if enable_modules:
    490             self.config.available_features.add('-fmodules')
    491             self.cxx.useModules()
    492 
    493     def configure_substitutions(self):
    494         sub = self.config.substitutions
    495         sub.append(('%{cxx}', pipes.quote(self.cxx.path)))
    496         flags = self.cxx.flags + (self.cxx.modules_flags if self.cxx.use_modules else [])
    497         compile_flags = self.cxx.compile_flags + (self.cxx.warning_flags if self.cxx.use_warnings else [])
    498         sub.append(('%{flags}',         ' '.join(map(pipes.quote, flags))))
    499         sub.append(('%{compile_flags}', ' '.join(map(pipes.quote, compile_flags))))
    500         sub.append(('%{link_flags}',    ' '.join(map(pipes.quote, self.cxx.link_flags))))
    501 
    502         codesign_ident = self.get_lit_conf('llvm_codesign_identity', '')
    503         env_vars = ' '.join('%s=%s' % (k, pipes.quote(v)) for (k, v) in self.exec_env.items())
    504         exec_args = [
    505             '--execdir %T',
    506             '--codesign_identity "{}"'.format(codesign_ident),
    507             '--env {}'.format(env_vars)
    508         ]
    509         sub.append(('%{exec}', '{} {} -- '.format(self.executor, ' '.join(exec_args))))
    510 
    511     def configure_env(self):
    512         self.config.environment = dict(os.environ)
    513 
    514     def add_path(self, dest_env, new_path):
    515         self.target_info.add_path(dest_env, new_path)
    516