# Copyright 2018 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.

"""Creates a archive manifest used for Fuchsia package generation.

Arguments:
  root_dir: The absolute path to the Chromium source tree root.

  out_dir: The absolute path to the Chromium build directory.

  app_name: The filename of the package's executable target.

  runtime_deps: The path to the GN runtime deps file.

  output_path: The path of the manifest file which will be written.
"""

import json
import os
import re
import subprocess
import sys
import tempfile


def ReadDynamicLibDeps(paths):
  """Returns a list of NEEDED libraries read from a binary's ELF header."""

  LIBRARY_RE = re.compile(r'.*\(NEEDED\)\s+Shared library: \[(?P<lib>.*)\]')
  elfinfo = subprocess.check_output(['readelf', '-d'] + paths,
                                    stderr=open(os.devnull, 'w'))
  libs = []
  for line in elfinfo.split('\n'):
    match = LIBRARY_RE.match(line.rstrip())
    if match:
      lib = match.group('lib')

      # Skip libzircon.so, as it is supplied by the OS loader.
      if lib != 'libzircon.so':
        libs.append(match.group('lib'))

  return libs


def ComputeTransitiveLibDeps(executable_path, available_libs):
  """Returns a set representing the library dependencies of |executable_path|,
  the dependencies of its dependencies, and so on.

  A list of candidate library filesystem paths is passed using |available_libs|
  to help with resolving full paths from the short ELF header filenames."""

  # Stack of binaries (libraries, executables) awaiting traversal.
  to_visit = [executable_path]

  # The computed set of visited transitive dependencies.
  deps = set()

  while to_visit:
    deps = deps.union(to_visit)

    # Resolve the full paths for all of |cur_path|'s NEEDED libraries.
    dep_paths = {available_libs[dep]
                 for dep in ReadDynamicLibDeps(list(to_visit))}

    # Add newly discovered dependencies to the pending traversal stack.
    to_visit = dep_paths.difference(deps)

  return deps


def EnumerateDirectoryFiles(path):
  """Returns a flattened list of all files contained under |path|."""

  output = set()
  for dirname, _, files in os.walk(path):
    output = output.union({os.path.join(dirname, f) for f in files})
  return output


def MakePackagePath(file_path, roots):
  """Computes a path for |file_path| that is relative to one of the directory
  paths in |roots|.

  file_path: The absolute file path to relativize.
  roots: A list of absolute directory paths which may serve as a relative root
         for |file_path|. At least one path must contain |file_path|.
         Overlapping roots are permitted; the deepest matching root will be
         chosen.

  Examples:

  >>> MakePackagePath('/foo/bar.txt', ['/foo/'])
  'bar.txt'

  >>> MakePackagePath('/foo/dir/bar.txt', ['/foo/'])
  'dir/bar.txt'

  >>> MakePackagePath('/foo/out/Debug/bar.exe', ['/foo/', '/foo/out/Debug/'])
  'bar.exe'
  """

  # Prevents greedily matching against a shallow path when a deeper, better
  # matching path exists.
  roots.sort(key=len, reverse=True)

  for next_root in roots:
    if not next_root.endswith(os.sep):
      next_root += os.sep

    if file_path.startswith(next_root):
      relative_path = file_path[len(next_root):]

      # Move all dynamic libraries (ending in .so or .so.<number>) to lib/.
      if re.search('.*\.so(\.\d+)?$', file_path):
        relative_path = 'lib/' + os.path.basename(relative_path)

      return relative_path

  raise Exception('Error: no matching root paths found for \'%s\'.' % file_path)


def _GetStrippedPath(bin_path):
  """Finds the stripped version of the binary |bin_path| in the build
  output directory."""

  # Skip the resolution step for binaries that don't have stripped counterparts,
  # like system libraries or other libraries built outside the Chromium build.
  if not '.unstripped' in bin_path:
    return bin_path

  return os.path.normpath(os.path.join(bin_path,
                                       os.path.pardir,
                                       os.path.pardir,
                                       os.path.basename(bin_path)))


def _IsBinary(path):
  """Checks if the file at |path| is an ELF executable by inspecting its FourCC
  header."""

  with open(path, 'rb') as f:
    file_tag = f.read(4)
  return file_tag == '\x7fELF'


def BuildManifest(root_dir, out_dir, app_name, app_filename,
                  sandbox_policy_path, runtime_deps_file, depfile_path,
                  dynlib_paths, output_path):
  with open(output_path, 'w') as manifest, open(depfile_path, 'w') as depfile:
    # Process the runtime deps file for file paths, recursively walking
    # directories as needed. File paths are stored in absolute form,
    # so that MakePackagePath() may relativize to either the source root or
    # output directory.
    # runtime_deps may contain duplicate paths, so use a set for
    # de-duplication.
    expanded_files = set()
    for next_path in open(runtime_deps_file, 'r'):
      next_path = next_path.strip()
      if os.path.isdir(next_path):
        for root, _, files in os.walk(next_path):
          for current_file in files:
            if current_file.startswith('.'):
              continue
            expanded_files.add(os.path.abspath(
                os.path.join(root, current_file)))
      else:
        expanded_files.add(os.path.abspath(next_path))

    # Get set of dist libraries available for dynamic linking.
    dist_libs = set()
    for next_dir in dynlib_paths.split(','):
      dist_libs = dist_libs.union(EnumerateDirectoryFiles(next_dir))

    # Compute the set of dynamic libraries used by the application or its
    # transitive dependencies (dist libs and components), and merge the result
    # with |expanded_files| so that they are included in the manifest.
    expanded_files = expanded_files.union(
        ComputeTransitiveLibDeps(
            app_filename,
            {os.path.basename(f): f for f in expanded_files.union(dist_libs)}))

    # Format and write out the manifest contents.
    app_found = False
    for current_file in expanded_files:
      if _IsBinary(current_file):
        current_file = _GetStrippedPath(current_file)

      in_package_path = MakePackagePath(os.path.join(out_dir, current_file),
                                        [root_dir, out_dir])
      if in_package_path == app_filename:
        in_package_path = 'bin/app'
        app_found = True

      # The source path is relativized so that it can be used on multiple
      # environments with differing parent directory structures,
      # e.g. builder bots and swarming clients.
      manifest.write('%s=%s\n' % (in_package_path,
                                  os.path.relpath(current_file, out_dir)))

      # Use libc.so's dynamic linker by aliasing libc.so to ld.so.1.
      # Fuchsia always looks for the linker implementation in ld.so.1.
      if os.path.basename(in_package_path) == 'libc.so':
        manifest.write(
            '%s=%s\n' % (os.path.dirname(in_package_path) + '/ld.so.1',
                         os.path.relpath(current_file, out_dir)))

    if not app_found:
      raise Exception('Could not locate executable inside runtime_deps.')

    with open(os.path.join(os.path.dirname(output_path), 'package'), 'w') \
        as package_json:
      json.dump({'version': '0', 'name': app_name}, package_json)
      manifest.write('meta/package=%s\n' %
                   os.path.relpath(package_json.name, out_dir))

    manifest.write('meta/sandbox=%s\n' %
                 os.path.relpath(os.path.join(root_dir, sandbox_policy_path),
                                 out_dir))
    depfile.write(
        "%s: %s" % (os.path.relpath(output_path, out_dir),
                    " ".join([os.path.relpath(f, out_dir)
                              for f in expanded_files])))
  return 0


if __name__ == '__main__':
  sys.exit(BuildManifest(*sys.argv[1:]))
