#!/usr/bin/python
#
# libjingle
# Copyright 2015 Google Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  1. Redistributions of source code must retain the above copyright notice,
#     this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#  3. The name of the author may not be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Script for merging generated iOS libraries."""

import optparse
import os
import re
import subprocess
import sys


def MergeLibs(lib_base_dir):
  """Merges generated iOS libraries for different archs.

  Uses libtool to generate FAT archive files for each generated library.

  Args:
    lib_base_dir: directory whose subdirectories are named by architecture and
                  contain the built libraries for that architecture

  Returns:
    Exit code of libtool.
  """
  output_dir_name = 'fat'
  archs = [arch for arch in os.listdir(lib_base_dir)
           if arch[:1] != '.' and arch != output_dir_name]
  # For each arch, find (library name, libary path) for arch. We will merge
  # all libraries with the same name.
  libs = {}
  for dirpath, _, filenames in os.walk(lib_base_dir):
    if dirpath.endswith(output_dir_name):
      continue
    for filename in filenames:
      if not filename.endswith('.a'):
        continue
      entry = libs.get(filename, [])
      entry.append(os.path.join(dirpath, filename))
      libs[filename] = entry
  # Some sublibaries are only present in certain architectures. We merge
  # them into their parent library so that the library list is consistent
  # across architectures.
  libs_copy = dict(libs)
  for library, paths in libs.items():
    if len(paths) < len(archs):
      # Hacky: we find parent libraries by stripping off each name component.
      components = library.strip('.a').split('_')[:-1]
      found = False
      while components:
        parent_library = '_'.join(components) + '.a'
        if (parent_library in libs_copy
            and len(libs_copy[parent_library]) >= len(archs)):
          libs[parent_library].extend(paths)
          del libs[library]
          found = True
          break
        components = components[:-1]
      assert found

  # Create output directory.
  output_dir_path = os.path.join(lib_base_dir, output_dir_name)
  if not os.path.exists(output_dir_path):
    os.mkdir(output_dir_path)

  # Use this so libtool merged binaries are always the same.
  env = os.environ.copy()
  env['ZERO_AR_DATE'] = '1'

  # Ignore certain errors.
  libtool_re = re.compile(r'^.*libtool:.*file: .* has no symbols$')

  # Merge libraries using libtool.
  for library, paths in libs.items():
    cmd_list = ['libtool', '-static', '-v', '-o',
                os.path.join(output_dir_path, library)] + paths
    libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env)
    _, err = libtoolout.communicate()
    for line in err.splitlines():
      if not libtool_re.match(line):
        print >>sys.stderr, line
    # Unconditionally touch the output .a file on the command line if present
    # and the command succeeded. A bit hacky.
    if not libtoolout.returncode:
      for i in range(len(cmd_list) - 1):
        if cmd_list[i] == '-o' and cmd_list[i+1].endswith('.a'):
          os.utime(cmd_list[i+1], None)
          break
    else:
      return libtoolout.returncode
  return libtoolout.returncode


def Main():
  parser = optparse.OptionParser()
  _, args = parser.parse_args()
  if len(args) != 1:
    parser.error('Error: Exactly 1 argument required.')
  lib_base_dir = args[0]
  MergeLibs(lib_base_dir)

if __name__ == '__main__':
  sys.exit(Main())
