[libcxx] r287336 - Add merge_archives.py utility

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 18 03:26:15 PST 2016


Author: ericwf
Date: Fri Nov 18 05:26:14 2016
New Revision: 287336

URL: http://llvm.org/viewvc/llvm-project?rev=287336&view=rev
Log:
Add merge_archives.py utility

Added:
    libcxx/trunk/utils/merge_archives.py

Added: libcxx/trunk/utils/merge_archives.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/merge_archives.py?rev=287336&view=auto
==============================================================================
--- libcxx/trunk/utils/merge_archives.py (added)
+++ libcxx/trunk/utils/merge_archives.py Fri Nov 18 05:26:14 2016
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+#===----------------------------------------------------------------------===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is dual licensed under the MIT and the University of Illinois Open
+# Source Licenses. See LICENSE.TXT for details.
+#
+#===----------------------------------------------------------------------===##
+
+from argparse import ArgumentParser
+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 diagnose_missing(file):
+    if not os.path.exists(file):
+        print_and_exit("input '%s' does not exist" % file)
+
+
+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)
+
+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(
+        'archives', metavar='archives',  nargs='+',
+        help='The archives to merge')
+
+    args = parser.parse_args()
+
+    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 = []
+    for ar in args.archives:
+        diagnose_missing(ar)
+        # Make the path absolute so it isn't affected when we change the PWD.
+        archives += [os.path.abspath(ar)]
+
+    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')
+
+    for arc in archives:
+        execute_command_verbose([ar_exe, '-x', arc], cwd=temp_directory_root,
+                                verbose=args.verbose)
+
+    files = glob.glob(os.path.join(temp_directory_root, '*.o'))
+    if not files:
+        print_and_exit('Failed to glob for %s' % glob_path)
+    cmd = [ar_exe, '-qc', args.output] + files
+    execute_command_verbose(cmd, cwd=temp_directory_root, verbose=args.verbose)
+
+
+if __name__ == '__main__':
+    main()
+    exit_with_cleanups(0)




More information about the cfe-commits mailing list