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) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits