1import copy 2import os 3import re 4import shlex 5import subprocess 6 7import libcxx.compiler 8 9 10class AndroidCXXCompiler(libcxx.compiler.CXXCompiler): 11 def __init__(self, cxx_under_test, cxx_template, link_template): 12 super(AndroidCXXCompiler, self).__init__(cxx_under_test) 13 self.cxx_template = cxx_template 14 self.link_template = link_template 15 self.build_top = os.getenv('ANDROID_BUILD_TOP') 16 17 # The file system tests require a handful of defines that we can't add 18 # to the Android.bp since they require absolute paths. 19 self.extra_cflags = [] 20 21 def copy(self): 22 return copy.deepcopy(self) 23 24 def get_triple(self): 25 if 'clang' in self.path: 26 return self.get_clang_triple() 27 else: 28 return self.get_gcc_triple() 29 30 raise RuntimeError('Could not determine target triple.') 31 32 def get_clang_triple(self): 33 match = re.search(r'-target\s+(\S+)', self.cxx_template) 34 if match: 35 return match.group(1) 36 return None 37 38 def get_gcc_triple(self): 39 proc = subprocess.Popen([self.path, '-v'], 40 stderr=subprocess.PIPE) 41 _, stderr = proc.communicate() 42 for line in stderr.split('\n'): 43 print 'Checking {}'.format(line) 44 match = re.search(r'^Target: (.+)$', line) 45 if match: 46 return match.group(1) 47 return None 48 49 def compile(self, source_files, out=None, flags=None, cwd=None): 50 flags = [] if flags is None else flags 51 return super(AndroidCXXCompiler, self).compile(source_files, out, flags, 52 self.build_top) 53 54 def link(self, source_files, out=None, flags=None, cwd=None): 55 flags = [] if flags is None else flags 56 return super(AndroidCXXCompiler, self).link(source_files, out, flags, 57 self.build_top) 58 59 def compileCmd(self, source_files, out=None, flags=None): 60 if out is None: 61 raise RuntimeError('The Android compiler requires an out path.') 62 63 if isinstance(source_files, str): 64 source_files = [source_files] 65 cxx_args = self.cxx_template.replace('%OUT%', out) 66 cxx_args = cxx_args.replace('%SOURCE%', ' '.join(source_files)) 67 return [self.path] + shlex.split(cxx_args) + self.extra_cflags 68 69 def linkCmd(self, source_files, out=None, flags=None): 70 if out is None: 71 raise RuntimeError('The Android compiler requires an out path.') 72 73 if isinstance(source_files, str): 74 source_files = [source_files] 75 link_args = self.link_template.replace('%OUT%', out) 76 link_args = link_args.replace('%SOURCE%', ' '.join(source_files)) 77 return [self.path] + shlex.split(link_args) 78 79 def _basicCmd(self, source_files, out, is_link=False, input_is_cxx=False): 80 raise NotImplementedError() 81 82 def _initTypeAndVersion(self): 83 pass 84