| Index: third_party/instrumented_libraries/download_build_install.py
 | 
| diff --git a/third_party/instrumented_libraries/download_build_install.py b/third_party/instrumented_libraries/download_build_install.py
 | 
| index ef9a838cb14d909518db7aaf9c359f4f15257586..1135ee33ad7c6258208438de368ab7f99f768807 100755
 | 
| --- a/third_party/instrumented_libraries/download_build_install.py
 | 
| +++ b/third_party/instrumented_libraries/download_build_install.py
 | 
| @@ -8,37 +8,11 @@
 | 
|  import argparse
 | 
|  import os
 | 
|  import platform
 | 
| +import shlex
 | 
|  import shutil
 | 
|  import subprocess
 | 
|  import sys
 | 
|  
 | 
| -# Build parameters for different sanitizers.
 | 
| -# We use XORIGIN as RPATH and after building library replace it to $ORIGIN
 | 
| -# The reason: this flag goes through configure script and makefiles
 | 
| -# differently for different libraries. So the dollar sign '$' should be
 | 
| -# differently escaped. Instead of having problems with that it just
 | 
| -# uses XORIGIN to build library and after that replaces it to $ORIGIN
 | 
| -# directly in .so file.
 | 
| -SUPPORTED_SANITIZERS = {
 | 
| -    'asan': {
 | 
| -        'compiler_flags': '-O2 -fsanitize=address -gline-tables-only -fPIC -w '
 | 
| -                          '-U_FORITFY_SOURCE',
 | 
| -        'linker_flags': '-fsanitize=address -Wl,-z,origin -Wl,-R,XORIGIN/.'
 | 
| -    },
 | 
| -    'msan': {
 | 
| -        'compiler_flags': '-O2 -fsanitize=memory '
 | 
| -                          '-fsanitize-memory-track-origins '
 | 
| -                          '-gline-tables-only -fPIC -w -U_FORTIFY_SOURCE',
 | 
| -        'linker_flags': '-fsanitize=memory -Wl,-z,origin -Wl,-R,XORIGIN/.'
 | 
| -    },
 | 
| -    'tsan': {
 | 
| -        'compiler_flags': '-O2 -fsanitize=thread -gline-tables-only -fPIC -w '
 | 
| -                          '-U_FORTIFY_SOURCE',
 | 
| -        'linker_flags': '-fsanitize=thread -Wl,-z,origin -Wl,-R,XORIGIN/.'
 | 
| -    },
 | 
| -}
 | 
| -
 | 
| -
 | 
|  class ScopedChangeDirectory(object):
 | 
|    """Changes current working directory and restores it back automatically."""
 | 
|  
 | 
| @@ -59,22 +33,22 @@ def get_script_absolute_path():
 | 
|    return os.path.dirname(os.path.abspath(__file__))
 | 
|  
 | 
|  
 | 
| -def get_library_build_dependencies(library):
 | 
| -  command = 'apt-get -s build-dep %s | grep Inst | cut -d " " -f 2' % library
 | 
| +def get_package_build_dependencies(package):
 | 
| +  command = 'apt-get -s build-dep %s | grep Inst | cut -d " " -f 2' % package
 | 
|    command_result = subprocess.Popen(command, stdout=subprocess.PIPE,
 | 
|                                      shell=True)
 | 
|    if command_result.wait():
 | 
| -    raise Exception('Failed to determine build dependencies for %s' % library)
 | 
| +    raise Exception('Failed to determine build dependencies for %s' % package)
 | 
|    build_dependencies = [l.strip() for l in command_result.stdout]
 | 
|    return build_dependencies
 | 
|  
 | 
|  
 | 
| -def check_library_build_dependencies(library):
 | 
| -  build_dependencies = get_library_build_dependencies(library)
 | 
| +def check_package_build_dependencies(package):
 | 
| +  build_dependencies = get_package_build_dependencies(package)
 | 
|    if len(build_dependencies):
 | 
| -    print >> sys.stderr, 'Please, install build-dependencies for %s' % library
 | 
| +    print >> sys.stderr, 'Please, install build-dependencies for %s' % package
 | 
|      print >> sys.stderr, 'One-liner for APT:'
 | 
| -    print >> sys.stderr, 'sudo apt-get -y --no-remove build-dep %s' % library
 | 
| +    print >> sys.stderr, 'sudo apt-get -y --no-remove build-dep %s' % package
 | 
|      sys.exit(1)
 | 
|  
 | 
|  
 | 
| @@ -258,13 +232,16 @@ def build_and_install(parsed_arguments, environment, install_prefix):
 | 
|      raise Exception('Unrecognized build method: %s' %
 | 
|                      parsed_arguments.build_method)
 | 
|  
 | 
| +def unescape_flags(s):
 | 
| +  # GYP escapes the build flags as if they are going to be inserted directly
 | 
| +  # into the command line. Since we pass them via CFLAGS/LDFLAGS, we must drop
 | 
| +  # the double quotes accordingly. 
 | 
| +  return ' '.join(shlex.split(s))
 | 
|  
 | 
|  def download_build_install(parsed_arguments):
 | 
| -  sanitizer_params = SUPPORTED_SANITIZERS[parsed_arguments.sanitizer_type]
 | 
| -
 | 
|    environment = os.environ.copy()
 | 
| -  # Usage of environment variables CC and CXX prefers usage flags --c-compiler
 | 
| -  # and --cxx-compiler
 | 
| +  # The CC/CXX environment variables take precedence over the command line
 | 
| +  # flags.
 | 
|    if 'CC' not in environment and parsed_arguments.cc:
 | 
|      environment['CC'] = parsed_arguments.cc
 | 
|    if 'CXX' not in environment and parsed_arguments.cxx:
 | 
| @@ -274,75 +251,70 @@ def download_build_install(parsed_arguments):
 | 
|        get_script_absolute_path(),
 | 
|        parsed_arguments.product_directory))
 | 
|  
 | 
| -  compiler_flags = sanitizer_params['compiler_flags']
 | 
| +  cflags = unescape_flags(parsed_arguments.cflags)
 | 
|    if parsed_arguments.sanitizer_blacklist:
 | 
| -    compiler_flags += ' -fsanitize-blacklist=%s/%s' % (
 | 
| +    cflags += ' -fsanitize-blacklist=%s/%s' % (
 | 
|          product_directory,
 | 
|          parsed_arguments.sanitizer_blacklist)
 | 
| -  environment['CFLAGS'] = '%s %s' % (compiler_flags,
 | 
| -                                     parsed_arguments.extra_cflags)
 | 
| -  environment['CXXFLAGS'] = '%s %s' % (
 | 
| -      compiler_flags,
 | 
| -      parsed_arguments.extra_cxxflags)
 | 
| +  environment['CFLAGS'] = cflags
 | 
| +  environment['CXXFLAGS'] = cflags
 | 
|  
 | 
|    install_prefix = '%s/instrumented_libraries/%s' % (
 | 
|        product_directory,
 | 
|        parsed_arguments.sanitizer_type)
 | 
|  
 | 
| +  ldflags = unescape_flags(parsed_arguments.ldflags)
 | 
|    # Make sure the linker searches the instrumented libraries dir for
 | 
|    # library dependencies.
 | 
| -  environment['LDFLAGS'] = '%s -L%s/lib %s' % (
 | 
| -      sanitizer_params['linker_flags'],
 | 
| -      install_prefix, parsed_arguments.extra_ldflags)
 | 
| +  environment['LDFLAGS'] = '%s -L%s/lib' % (ldflags, install_prefix)
 | 
|  
 | 
| -  library_directory = '%s/%s' % (parsed_arguments.intermediate_directory,
 | 
| -                                 parsed_arguments.library)
 | 
| +  package_directory = '%s/%s' % (parsed_arguments.intermediate_directory,
 | 
| +                                 parsed_arguments.package)
 | 
|  
 | 
|    # A failed build might have left a dirty source tree behind.
 | 
| -  if os.path.exists(library_directory):
 | 
| -    shell_call('rm -rf %s' % library_directory, parsed_arguments.verbose)
 | 
| -  os.makedirs(library_directory)
 | 
| +  if os.path.exists(package_directory):
 | 
| +    shell_call('rm -rf %s' % package_directory, parsed_arguments.verbose)
 | 
| +  os.makedirs(package_directory)
 | 
|  
 | 
| -  with ScopedChangeDirectory(library_directory) as cd_library:
 | 
| -    shell_call('apt-get source %s' % parsed_arguments.library,
 | 
| +  with ScopedChangeDirectory(package_directory) as cd_package:
 | 
| +    shell_call('apt-get source %s' % parsed_arguments.package,
 | 
|                 parsed_arguments.verbose)
 | 
|      # There should be exactly one subdirectory after downloading a package.
 | 
|      subdirectories = [d for d in os.listdir('.') if os.path.isdir(d)]
 | 
|      if len(subdirectories) != 1:
 | 
|        raise (Exception('There was not one directory after downloading '
 | 
| -                       'a package %s' % parsed_arguments.library))
 | 
| +                       'a package %s' % parsed_arguments.package))
 | 
|      with ScopedChangeDirectory(subdirectories[0]):
 | 
|        # Here we are in the package directory.
 | 
|        if parsed_arguments.run_before_build:
 | 
|          shell_call(
 | 
|              '%s/%s' %
 | 
| -            (os.path.relpath(cd_library.old_path),
 | 
| +            (os.path.relpath(cd_package.old_path),
 | 
|               parsed_arguments.run_before_build),
 | 
|              parsed_arguments.verbose)
 | 
|        try:
 | 
|          build_and_install(parsed_arguments, environment, install_prefix)
 | 
|        except Exception as exception:
 | 
|          print exception
 | 
| -        print 'Failed to build library %s.' % parsed_arguments.library
 | 
| +        print 'Failed to build package %s.' % parsed_arguments.package
 | 
|          print ('Probably, some of its dependencies are not installed: %s' %
 | 
| -               ' '.join(get_library_build_dependencies(parsed_arguments.library)))
 | 
| +               ' '.join(get_package_build_dependencies(parsed_arguments.package)))
 | 
|          sys.exit(1)
 | 
|  
 | 
| -  # Touch a txt file to indicate library is installed.
 | 
| -  open('%s/%s.txt' % (install_prefix, parsed_arguments.library), 'w').close()
 | 
| +  # Touch a txt file to indicate package is installed.
 | 
| +  open('%s/%s.txt' % (install_prefix, parsed_arguments.package), 'w').close()
 | 
|  
 | 
|    # Remove downloaded package and generated temporary build files.
 | 
|    # Failed builds intentionally skip this step, in order to aid in tracking down
 | 
|    # build failures.
 | 
| -  shell_call('rm -rf %s' % library_directory, parsed_arguments.verbose)
 | 
| -
 | 
| +  shell_call('rm -rf %s' % package_directory, parsed_arguments.verbose)
 | 
|  
 | 
|  def main():
 | 
|    argument_parser = argparse.ArgumentParser(
 | 
| -      description='Download, build and install instrumented library')
 | 
| +      description='Download, build and install instrumented package')
 | 
|  
 | 
|    argument_parser.add_argument('-j', '--jobs', type=int, default=1)
 | 
| -  argument_parser.add_argument('-l', '--library', required=True)
 | 
| +  argument_parser.add_argument('-p', '--package', required=True)
 | 
|    argument_parser.add_argument(
 | 
|        '-i', '--product-directory', default='.',
 | 
|        help='Relative path to the directory with chrome binaries')
 | 
| @@ -350,11 +322,10 @@ def main():
 | 
|        '-m', '--intermediate-directory', default='.',
 | 
|        help='Relative path to the directory for temporary build files')
 | 
|    argument_parser.add_argument('--extra-configure-flags', default='')
 | 
| -  argument_parser.add_argument('--extra-cflags', default='')
 | 
| -  argument_parser.add_argument('--extra-cxxflags', default='')
 | 
| -  argument_parser.add_argument('--extra-ldflags', default='')
 | 
| +  argument_parser.add_argument('--cflags', default='')
 | 
| +  argument_parser.add_argument('--ldflags', default='')
 | 
|    argument_parser.add_argument('-s', '--sanitizer-type', required=True,
 | 
| -                               choices=SUPPORTED_SANITIZERS.keys())
 | 
| +                               choices=['asan', 'msan', 'tsan'])
 | 
|    argument_parser.add_argument('-v', '--verbose', action='store_true')
 | 
|    argument_parser.add_argument('--check-build-deps', action='store_true')
 | 
|    argument_parser.add_argument('--cc')
 | 
| @@ -374,7 +345,7 @@ def main():
 | 
|    os.chdir(get_script_absolute_path())
 | 
|    # Ensure all build dependencies are installed.
 | 
|    if parsed_arguments.check_build_deps:
 | 
| -    check_library_build_dependencies(parsed_arguments.library)
 | 
| +    check_package_build_dependencies(parsed_arguments.package)
 | 
|  
 | 
|    download_build_install(parsed_arguments)
 | 
|  
 | 
| 
 |