#!/usr/bin/python
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Downloads, builds (with instrumentation) and installs shared libraries."""

import argparse
import os
import platform
import shlex
import shutil
import subprocess
import sys

class ScopedChangeDirectory(object):
  """Changes current working directory and restores it back automatically."""

  def __init__(self, path):
    self.path = path
    self.old_path = ''

  def __enter__(self):
    self.old_path = os.getcwd()
    os.chdir(self.path)
    return self

  def __exit__(self, exc_type, exc_value, traceback):
    os.chdir(self.old_path)


def get_script_absolute_path():
  return os.path.dirname(os.path.abspath(__file__))


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' % package)
  build_dependencies = [l.strip() for l in command_result.stdout]
  return build_dependencies


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' % package
    print >> sys.stderr, 'One-liner for APT:'
    print >> sys.stderr, 'sudo apt-get -y --no-remove build-dep %s' % package
    sys.exit(1)


def shell_call(command, verbose=False, environment=None):
  """ Wrapper on subprocess.Popen

  Calls command with specific environment and verbosity using
  subprocess.Popen

  Args:
    command: Command to run in shell.
    verbose: If False, hides all stdout and stderr in case of successful build.
        Otherwise, always prints stdout and stderr.
    environment: Parameter 'env' for subprocess.Popen.

  Returns:
    None

  Raises:
    Exception: if return code after call is not zero.
  """
  child = subprocess.Popen(
      command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
      env=environment, shell=True)
  stdout, stderr = child.communicate()
  if verbose or child.returncode:
    print stdout
  if child.returncode:
    raise Exception('Failed to run: %s' % command)


def run_shell_commands(commands, verbose=False, environment=None):
  for command in commands:
    shell_call(command, verbose, environment)


def destdir_configure_make_install(parsed_arguments, environment,
                                   install_prefix):
  configure_command = './configure %s' % parsed_arguments.extra_configure_flags
  configure_command += ' --libdir=/lib/'
  # Installing to a temporary directory allows us to safely clean up the .la
  # files below.
  destdir = '%s/debian/instrumented_build' % os.getcwd()
  # Some makefiles use BUILDROOT instead of DESTDIR.
  make_command = 'make DESTDIR=%s BUILDROOT=%s' % (destdir, destdir)
  run_shell_commands([
      configure_command,
      '%s -j%s' % (make_command, parsed_arguments.jobs),
      # Parallel install is flaky for some packages.
      '%s install -j1' % make_command,
      # Kill the .la files. They contain absolute paths, and will cause build
      # errors in dependent libraries.
      'rm %s/lib/*.la -f' % destdir,
      # Now move the contents of the temporary destdir to their final place.
      'cp %s/* %s/ -rdf' % (destdir, install_prefix)],
                     parsed_arguments.verbose, environment)


def nss_make_and_copy(parsed_arguments, environment, install_prefix):
  # NSS uses a build system that's different from configure/make/install. All
  # flags must be passed as arguments to make.
  make_args = []
  # Do an optimized build.
  make_args.append('BUILD_OPT=1')
  # Set USE_64=1 on x86_64 systems.
  if platform.architecture()[0] == '64bit':
    make_args.append('USE_64=1')
  # Passing C(XX)FLAGS overrides the defaults, and EXTRA_C(XX)FLAGS is not
  # supported. Append our extra flags to CC/CXX.
  make_args.append('CC="%s %s"' % (environment['CC'], environment['CFLAGS']))
  make_args.append('CXX="%s %s"' %
                   (environment['CXX'], environment['CXXFLAGS']))
  # We need to override ZDEFS_FLAG at least to prevent -Wl,-z,defs.
  # Might as well use this to pass the linker flags, since ZDEF_FLAG is always
  # added during linking on Linux.
  make_args.append('ZDEFS_FLAG="-Wl,-z,nodefs %s"' % environment['LDFLAGS'])
  make_args.append('NSPR_INCLUDE_DIR=/usr/include/nspr')
  make_args.append('NSPR_LIB_DIR=%s/lib' % install_prefix)
  make_args.append('NSS_ENABLE_ECC=1')
  # Make sure we don't override the default flags.
  for variable in ['CFLAGS', 'CXXFLAGS', 'LDFLAGS']:
    del environment[variable]
  with ScopedChangeDirectory('nss') as cd_nss:
    # -j is not supported
    shell_call('make %s' % ' '.join(make_args), parsed_arguments.verbose,
               environment)
    # 'make install' is not supported. Copy the DSOs manually.
    install_dir = '%s/lib/' % install_prefix
    for (dirpath, dirnames, filenames) in os.walk('./lib/'):
      for filename in filenames:
        if filename.endswith('.so'):
          full_path = os.path.join(dirpath, filename)
          if parsed_arguments.verbose:
            print 'download_build_install.py: installing %s' % full_path
          shutil.copy(full_path, install_dir)


def libcap2_make_install(parsed_arguments, environment, install_prefix):
  # libcap2 doesn't come with a configure script
  make_args = [
      '%s="%s"' % (name, environment[name])
      for name in['CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS']]
  shell_call('make -j%s %s' % (parsed_arguments.jobs, ' '.join(make_args)),
             parsed_arguments.verbose, environment)
  install_args = [
      'DESTDIR=%s' % install_prefix,
      # Do not install in lib64/.
      'lib=lib',
      # Skip a step that requires sudo.
      'RAISE_SETFCAP=no'
  ]
  shell_call('make -j%s install %s' %
             (parsed_arguments.jobs, ' '.join(install_args)),
             parsed_arguments.verbose, environment)


def libpci3_make_install(parsed_arguments, environment, install_prefix):
  # pciutils doesn't have a configure script
  # This build script follows debian/rules.

  # `make install' will create a "$(DESTDIR)-udeb" directory alongside destdir.
  # We don't want that in our product dir, so we use an intermediate directory.
  destdir = '%s/debian/pciutils' % os.getcwd()
  make_args = [
      '%s="%s"' % (name, environment[name])
      for name in['CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS']]
  make_args.append('SHARED=yes')
  paths = [
      'LIBDIR=/lib/',
      'PREFIX=/usr',
      'SBINDIR=/usr/bin',
      'IDSDIR=/usr/share/misc',
  ]
  install_args = ['DESTDIR=%s' % destdir]
  run_shell_commands([
      'mkdir -p %s-udeb/usr/bin' % destdir,
      'make -j%s %s' % (parsed_arguments.jobs, ' '.join(make_args + paths)),
      'make -j%s %s install' % (
          parsed_arguments.jobs,
          ' '.join(install_args + paths))],
                     parsed_arguments.verbose, environment)
  # Now move the contents of the temporary destdir to their final place.
  run_shell_commands([
      'cp %s/* %s/ -rd' % (destdir, install_prefix),
      'install -m 644 lib/libpci.so* %s/lib/' % install_prefix,
      'ln -sf libpci.so.3.1.8 %s/lib/libpci.so.3' % install_prefix],
                     parsed_arguments.verbose, environment)


def build_and_install(parsed_arguments, environment, install_prefix):
  if parsed_arguments.build_method == 'destdir':
    destdir_configure_make_install(
        parsed_arguments, environment, install_prefix)
  elif parsed_arguments.build_method == 'custom_nss':
    nss_make_and_copy(parsed_arguments, environment, install_prefix)
  elif parsed_arguments.build_method == 'custom_libcap':
    libcap2_make_install(parsed_arguments, environment, install_prefix)
  elif parsed_arguments.build_method == 'custom_libpci3':
    libpci3_make_install(parsed_arguments, environment, install_prefix)
  else:
    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 build_environment(parsed_arguments, product_directory, install_prefix):
  environment = os.environ.copy()
  # 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:
    environment['CXX'] = parsed_arguments.cxx

  cflags = unescape_flags(parsed_arguments.cflags)
  if parsed_arguments.sanitizer_blacklist:
    cflags += ' -fsanitize-blacklist=%s/%s' % (
        get_script_absolute_path(),
        parsed_arguments.sanitizer_blacklist)
  environment['CFLAGS'] = cflags
  environment['CXXFLAGS'] = cflags

  ldflags = unescape_flags(parsed_arguments.ldflags)
  # Make sure the linker searches the instrumented libraries dir for
  # library dependencies.
  environment['LDFLAGS'] = '%s -L%s/lib' % (ldflags, install_prefix)

  if parsed_arguments.sanitizer_type == 'asan':
    # Do not report leaks during the build process.
    environment['ASAN_OPTIONS'] = '%s:detect_leaks=0' % \
        environment.get('ASAN_OPTIONS', '')

  # libappindicator1 needs this.
  environment['CSC'] = '/usr/bin/mono-csc'
  return environment



def download_build_install(parsed_arguments):
  product_directory = os.path.normpath('%s/%s' % (
      get_script_absolute_path(),
      parsed_arguments.product_directory))

  install_prefix = '%s/instrumented_libraries/%s' % (
      product_directory,
      parsed_arguments.sanitizer_type)

  environment = build_environment(parsed_arguments, product_directory,
                                  install_prefix)

  package_directory = '%s/%s' % (parsed_arguments.intermediate_directory,
                                 parsed_arguments.package)

  # Clobber by default, unless the developer wants to hack on the package's
  # source code.
  clobber = (environment.get('INSTRUMENTED_LIBRARIES_NO_CLOBBER', '') != '1')

  download_source = True
  if os.path.exists(package_directory):
    if clobber:
      shell_call('rm -rf %s' % package_directory, parsed_arguments.verbose)
    else:
      download_source = False
  if download_source:
    os.makedirs(package_directory)

  with ScopedChangeDirectory(package_directory) as cd_package:
    if download_source:
      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('apt-get source %s must create exactly one subdirectory.'
         % parsed_arguments.package)
    with ScopedChangeDirectory(subdirectories[0]):
      # Here we are in the package directory.
      if download_source:
        # Patch/run_before_build steps are only done once.
        if parsed_arguments.patch:
          shell_call(
              'patch -p1 -i %s/%s' %
              (os.path.relpath(cd_package.old_path),
               parsed_arguments.patch),
              parsed_arguments.verbose)
        if parsed_arguments.run_before_build:
          shell_call(
              '%s/%s' %
              (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 package %s.' % parsed_arguments.package
        print ('Probably, some of its dependencies are not installed: %s' %
               ' '.join(get_package_build_dependencies(parsed_arguments.package)))
        sys.exit(1)

  # 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.
  if clobber:
    shell_call('rm -rf %s' % package_directory, parsed_arguments.verbose)

def main():
  argument_parser = argparse.ArgumentParser(
      description='Download, build and install instrumented package')

  argument_parser.add_argument('-j', '--jobs', type=int, default=1)
  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')
  argument_parser.add_argument(
      '-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('--cflags', default='')
  argument_parser.add_argument('--ldflags', default='')
  argument_parser.add_argument('-s', '--sanitizer-type', required=True,
                               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')
  argument_parser.add_argument('--cxx')
  argument_parser.add_argument('--patch', default='')
  # This should be a shell script to run before building specific libraries.
  # This will be run after applying the patch above.
  argument_parser.add_argument('--run-before-build', default='')
  argument_parser.add_argument('--build-method', default='destdir')
  argument_parser.add_argument('--sanitizer-blacklist', default='')

  # Ignore all empty arguments because in several cases gyp passes them to the
  # script, but ArgumentParser treats them as positional arguments instead of
  # ignoring (and doesn't have such options).
  parsed_arguments = argument_parser.parse_args(
      [arg for arg in sys.argv[1:] if len(arg) != 0])
  # Ensure current working directory is this script directory.
  os.chdir(get_script_absolute_path())
  # Ensure all build dependencies are installed.
  if parsed_arguments.check_build_deps:
    check_package_build_dependencies(parsed_arguments.package)

  download_build_install(parsed_arguments)


if __name__ == '__main__':
  main()
