link_lib.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import sys
  2. import subprocess
  3. import tempfile
  4. import os
  5. class Opts(object):
  6. def __init__(self, args):
  7. self.archiver = args[0]
  8. self.arch_type = args[1]
  9. self.llvm_ar_format = args[2]
  10. self.build_root = args[3]
  11. self.plugin = args[4]
  12. self.output = args[5]
  13. auto_input = args[6:]
  14. if self.arch_type == 'GNU_AR':
  15. self.create_flags = ['rcs']
  16. self.modify_flags = ['-M']
  17. elif self.arch_type == 'LLVM_AR':
  18. self.create_flags = ['rcs', '--format=%s' % self.llvm_ar_format]
  19. self.modify_flags = ['-M']
  20. elif self.arch_type == 'LIBTOOL':
  21. self.create_flags = ['-static', '-o']
  22. self.modify_flags = []
  23. need_modify = self.arch_type != 'LIBTOOL' and any(item.endswith('.a') for item in auto_input)
  24. if need_modify:
  25. self.objs = filter(lambda x: x.endswith('.o'), auto_input)
  26. self.libs = filter(lambda x: x.endswith('.a'), auto_input)
  27. else:
  28. self.objs = auto_input
  29. self.libs = []
  30. self.plugin_flags = ['--plugin', self.plugin] if self.plugin != 'None' else []
  31. def get_opts(args):
  32. return Opts(args)
  33. if __name__ == "__main__":
  34. opts = get_opts(sys.argv[1:])
  35. # There is a bug in llvm-ar. Some files with size slightly greater 2^32
  36. # still have GNU format instead of GNU64 and cause link problems.
  37. # Workaround just lowers llvm-ar's GNU64 threshold to 2^31.
  38. if opts.arch_type == 'LLVM_AR':
  39. os.environ['SYM64_THRESHOLD'] = '31'
  40. def call():
  41. try:
  42. p = subprocess.Popen(cmd, stdin=stdin, cwd=opts.build_root)
  43. rc = p.wait()
  44. return rc
  45. except OSError as e:
  46. raise Exception('while running %s: %s' % (' '.join(cmd), e))
  47. try:
  48. os.unlink(opts.output)
  49. except OSError:
  50. pass
  51. if not opts.libs:
  52. cmd = [opts.archiver] + opts.create_flags + opts.plugin_flags + [opts.output] + opts.objs
  53. stdin = None
  54. exit_code = call()
  55. else:
  56. temp = tempfile.NamedTemporaryFile(dir=os.path.dirname(opts.output), delete=False)
  57. with open(temp.name, 'w') as tmp:
  58. tmp.write('CREATE {0}\n'.format(opts.output))
  59. for lib in opts.libs:
  60. tmp.write('ADDLIB {0}\n'.format(lib))
  61. for obj in opts.objs:
  62. tmp.write('ADDMOD {0}\n'.format(obj))
  63. tmp.write('SAVE\n')
  64. tmp.write('END\n')
  65. cmd = [opts.archiver] + opts.modify_flags + opts.plugin_flags
  66. stdin = open(temp.name)
  67. exit_code = call()
  68. os.remove(temp.name)
  69. if exit_code != 0:
  70. raise Exception('{0} returned non-zero exit code {1}. Stop.'.format(' '.join(cmd), exit_code))