#!/usr/bin/env python
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##

from argparse import ArgumentParser
from ctypes.util import find_library
import distutils.spawn
import glob
import tempfile
import os
import shutil
import subprocess
import signal
import sys

temp_directory_root = None
def exit_with_cleanups(status):
    if temp_directory_root is not None:
        shutil.rmtree(temp_directory_root)
    sys.exit(status)

def print_and_exit(msg):
    sys.stderr.write(msg + '\n')
    exit_with_cleanups(1)

def find_and_diagnose_missing(lib, search_paths):
    if os.path.exists(lib):
        return os.path.abspath(lib)
    if not lib.startswith('lib') or not lib.endswith('.a'):
        print_and_exit(("input file '%s' not not name a static library. "
                       "It should start with 'lib' and end with '.a") % lib)
    for sp in search_paths:
        assert type(sp) is list and len(sp) == 1
        path = os.path.join(sp[0], lib)
        if os.path.exists(path):
            return os.path.abspath(path)
    print_and_exit("input '%s' does not exist" % lib)


def execute_command(cmd, cwd=None):
    """
    Execute a command, capture and return its output.
    """
    kwargs = {
        'stdin': subprocess.PIPE,
        'stdout': subprocess.PIPE,
        'stderr': subprocess.PIPE,
        'cwd': cwd
    }
    p = subprocess.Popen(cmd, **kwargs)
    out, err = p.communicate()
    exitCode = p.wait()
    if exitCode == -signal.SIGINT:
        raise KeyboardInterrupt
    return out, err, exitCode


def execute_command_verbose(cmd, cwd=None, verbose=False):
    """
    Execute a command and print its output on failure.
    """
    out, err, exitCode = execute_command(cmd, cwd=cwd)
    if exitCode != 0 or verbose:
        report = "Command: %s\n" % ' '.join(["'%s'" % a for a in cmd])
        if exitCode != 0:
            report += "Exit Code: %d\n" % exitCode
        if out:
            report += "Standard Output:\n--\n%s--" % out
        if err:
            report += "Standard Error:\n--\n%s--" % err
        if exitCode != 0:
            report += "\n\nFailed!"
        sys.stderr.write('%s\n' % report)
        if exitCode != 0:
            exit_with_cleanups(exitCode)
    return out

def main():
    parser = ArgumentParser(
        description="Merge multiple archives into a single library")
    parser.add_argument(
        '-v', '--verbose', dest='verbose', action='store_true', default=False)
    parser.add_argument(
        '-o', '--output', dest='output', required=True,
        help='The output file. stdout is used if not given',
        type=str, action='store')
    parser.add_argument(
        '-L', dest='search_paths',
        help='Paths to search for the libraries along', action='append',
        nargs=1)
    parser.add_argument(
        '--ar', dest='ar_exe', required=False,
        help='The ar executable to use, finds \'ar\' in the path if not given',
        type=str, action='store')
    parser.add_argument(
        'archives', metavar='archives',  nargs='+',
        help='The archives to merge')

    args = parser.parse_args()

    ar_exe = args.ar_exe
    if not ar_exe:
        ar_exe = distutils.spawn.find_executable('ar')
    if not ar_exe:
        print_and_exit("failed to find 'ar' executable")

    if len(args.archives) < 2:
        print_and_exit('fewer than 2 inputs provided')
    archives = [find_and_diagnose_missing(ar, args.search_paths)
                for ar in args.archives]
    print ('Merging archives: %s' % archives)
    if not os.path.exists(os.path.dirname(args.output)):
        print_and_exit("output path doesn't exist: '%s'" % args.output)

    global temp_directory_root
    temp_directory_root = tempfile.mkdtemp('.libcxx.merge.archives')

    files = []
    for arc in archives:
        execute_command_verbose([ar_exe, 'x', arc],
                                cwd=temp_directory_root, verbose=args.verbose)
        out = execute_command_verbose([ar_exe, 't', arc])
        files.extend(out.splitlines())

    execute_command_verbose([ar_exe, 'rcs', args.output] + files,
                            cwd=temp_directory_root, verbose=args.verbose)


if __name__ == '__main__':
    main()
    exit_with_cleanups(0)
