added actual support for running clang with sanitizers
diff --git a/aos/build/build.py b/aos/build/build.py
index b954379..208b380 100755
--- a/aos/build/build.py
+++ b/aos/build/build.py
@@ -122,19 +122,21 @@
 
 class PrimeProcessor(Processor):
   class Platform(Processor.Platform):
-    def __init__(self, architecture, compiler, debug):
+    def __init__(self, architecture, compiler, debug, sanitizer):
       super(PrimeProcessor.Platform, self).__init__()
 
       self.architecture = architecture
       self.compiler = compiler
       self.debug = debug
+      self.sanitizer = sanitizer
 
     def __repr__(self):
-      return 'PrimeProcessor.Platform(architecture=%s, compiler=%s, debug=%s)' \
-          % (self.architecture, self.compiler, self.debug)
+      return 'PrimeProcessor.Platform(architecture=%s, compiler=%s, debug=%s' \
+          ', sanitizer=%s)' \
+          % (self.architecture, self.compiler, self.debug, self.sanitizer)
     def __str__(self):
-      return '%s-%s%s' % (self.architecture, self.compiler,
-                          '-debug' if self.debug else '')
+      return '%s-%s%s-%s' % (self.architecture, self.compiler,
+                          '-debug' if self.debug else '', self.sanitizer)
 
     def os(self):
       return 'linux'
@@ -182,12 +184,19 @@
       r = {}
       if self.compiler == 'clang':
         r['LD_LIBRARY_PATH'] = '/opt/clang-3.5/lib64'
+      if self.sanitizer == 'address':
         r['ASAN_SYMBOLIZER_PATH'] = '/opt/clang-3.5/bin/llvm-symbolizer'
         r['ASAN_OPTIONS'] = 'detect_leaks=1:check_initialization_order=1:strict_init_order=1'
+      elif self.sanitizer == 'memory':
+        r['MSAN_SYMBOLIZER_PATH'] = '/opt/clang-3.5/bin/llvm-symbolizer'
       return r
 
   ARCHITECTURES = ['arm', 'amd64']
   COMPILERS = ['clang', 'gcc']
+  # TODO(brians): memory doesn't really work because we don't have everything
+  # instrumented. Print out a warning or something.
+  SANITIZERS = ['address', 'undefined', 'integer', 'memory', 'thread', 'none']
+  PIC_SANITIZERS = ['memory', 'thread']
 
   def __init__(self, is_test, is_deploy):
     super(Processor, self).__init__()
@@ -197,7 +206,11 @@
       for compiler in PrimeProcessor.COMPILERS:
         for debug in [True, False]:
           platforms.append(
-              PrimeProcessor.Platform(architecture, compiler, debug))
+              PrimeProcessor.Platform(architecture, compiler, debug, 'none'))
+    for sanitizer in PrimeProcessor.SANITIZERS:
+      if sanitizer != 'none':
+        platforms.append(
+            PrimeProcessor.Platform('amd64', 'clang', True, sanitizer))
     self.platforms = frozenset(platforms)
     if is_test:
       self.default_platforms = self.select_platforms(architecture='amd64',
@@ -232,18 +245,19 @@
           r = selected
     return r
 
-  def select_platforms(self, architecture=None, compiler=None, debug=None):
+  def select_platforms(self, architecture=None, compiler=None, debug=None, sanitizer=None):
     r = []
     for platform in self.platforms:
       if architecture is None or platform.architecture == architecture:
         if compiler is None or platform.compiler == compiler:
           if debug is None or platform.debug == debug:
-            r.append(platform)
+            if sanitizer is None or platform.sanitizer == sanitizer:
+              r.append(platform)
     return set(r)
 
   def select_platforms_string(self, string):
     r = []
-    architecture, compiler, debug = None, None, None
+    architecture, compiler, debug, sanitizer = None, None, None, None
     for part in string.split('-'):
       if part in PrimeProcessor.ARCHITECTURES:
         architecture = part
@@ -253,12 +267,15 @@
         debug = True
       elif part in ['release', 'nodebug', 'ndb']:
         debug = False
+      elif part in PrimeProcessor.SANITIZERS:
+        sanitizer = part
       else:
         raise Processor.UnknownPlatform('Unknown platform string component "%s".' % part)
     return self.select_platforms(
         architecture=architecture,
         compiler=compiler,
-        debug=debug)
+        debug=debug,
+        sanitizer=sanitizer)
 
   def check_installed(self):
     self.do_check_installed(
@@ -363,9 +380,17 @@
   if processor.is_crio():
     download_externals('crio')
   else:
+    to_download = set()
     for architecture in PrimeProcessor.ARCHITECTURES:
-      if platforms & processor.select_platforms(architecture=architecture):
-        download_externals(architecture)
+      for sanitizer in PrimeProcessor.PIC_SANITIZERS:
+        if platforms & processor.select_platforms(architecture=architecture,
+                                                  sanitizer=sanitizer):
+          to_download.add(architecture + '-fPIC')
+        if platforms & processor.select_platforms(architecture=architecture,
+                                                  sanitizer='none'):
+          to_download.add(architecture)
+    for download_target in to_download:
+      download_externals(download_target)
 
   class ToolsConfig(object):
     def __init__(self):
@@ -394,6 +419,8 @@
     raise excinfo[1]
 
   def need_to_run_gyp(platform):
+    if not os.path.exists(platform.build_ninja()):
+      return True
     dirs = os.listdir(os.path.join(aos_path(), '..'))
     # Looking through these folders takes a long time and isn't useful.
     dirs.remove('output')
@@ -430,7 +457,11 @@
              '-DPLATFORM=%s' % platform.gyp_platform(),
              '-DARCHITECTURE=%s' % platform.architecture,
              '-DCOMPILER=%s' % platform.compiler,
-             '-DDEBUG=%s' % ('yes' if platform.debug else 'no')) +
+             '-DDEBUG=%s' % ('yes' if platform.debug else 'no'),
+             '-DSANITIZER=%s' % platform.sanitizer,
+             '-DSANITIZER_FPIC=%s' % ('-fPIC'
+                 if platform.sanitizer in PrimeProcessor.PIC_SANITIZERS
+                 else '')) +
             processor.extra_gyp_flags() + (args.main_gyp,),
             stdin=subprocess.PIPE)
         gyp.communicate(("""