link_exe.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import sys
  2. import subprocess
  3. import optparse
  4. from process_whole_archive_option import ProcessWholeArchiveOption
  5. def get_leaks_suppressions(cmd):
  6. supp, newcmd = [], []
  7. for arg in cmd:
  8. if arg.endswith(".supp"):
  9. supp.append(arg)
  10. else:
  11. newcmd.append(arg)
  12. return supp, newcmd
  13. MUSL_LIBS = '-lc', '-lcrypt', '-ldl', '-lm', '-lpthread', '-lrt', '-lutil'
  14. CUDA_LIBRARIES = {
  15. '-lcublas_static': '-lcublas',
  16. '-lcublasLt_static': '-lcublasLt',
  17. '-lcudart_static': '-lcudart',
  18. '-lcudnn_static': '-lcudnn',
  19. '-lcufft_static_nocallback': '-lcufft',
  20. '-lcurand_static': '-lcurand',
  21. '-lcusolver_static': '-lcusolver',
  22. '-lcusparse_static': '-lcusparse',
  23. '-lmyelin_compiler_static': '-lmyelin',
  24. '-lmyelin_executor_static': '-lnvcaffe_parser',
  25. '-lmyelin_pattern_library_static': '',
  26. '-lmyelin_pattern_runtime_static': '',
  27. '-lnvinfer_static': '-lnvinfer',
  28. '-lnvinfer_plugin_static': '-lnvinfer_plugin',
  29. '-lnvonnxparser_static': '-lnvonnxparser',
  30. '-lnvparsers_static': '-lnvparsers'
  31. }
  32. def remove_excessive_flags(cmd):
  33. flags = []
  34. for flag in cmd:
  35. if not flag.endswith('.ios.interface') and not flag.endswith('.pkg.fake'):
  36. flags.append(flag)
  37. return flags
  38. def fix_sanitize_flag(cmd):
  39. """
  40. Remove -fsanitize=address flag if sanitazers are linked explicitly for linux target.
  41. """
  42. for flag in cmd:
  43. if flag.startswith('--target') and 'linux' not in flag.lower():
  44. # use toolchained sanitize libraries
  45. return cmd
  46. CLANG_RT = 'contrib/libs/clang14-rt/lib/'
  47. sanitize_flags = {
  48. '-fsanitize=address': CLANG_RT + 'asan',
  49. '-fsanitize=memory': CLANG_RT + 'msan',
  50. '-fsanitize=leak': CLANG_RT + 'lsan',
  51. '-fsanitize=undefined': CLANG_RT + 'ubsan',
  52. '-fsanitize=thread': CLANG_RT + 'tsan'
  53. }
  54. used_sanitize_libs = []
  55. aux = []
  56. for flag in cmd:
  57. if flag.startswith('-fsanitize-coverage='):
  58. # do not link sanitizer libraries from clang
  59. aux.append('-fno-sanitize-link-runtime')
  60. if flag in sanitize_flags and any(s.startswith(sanitize_flags[flag]) for s in cmd):
  61. # exclude '-fsanitize=' if appropriate library is linked explicitly
  62. continue
  63. if any(flag.startswith(lib) for lib in sanitize_flags.values()):
  64. used_sanitize_libs.append(flag)
  65. continue
  66. aux.append(flag)
  67. # move sanitize libraries out of the repeatedly searched group of archives
  68. flags = []
  69. for flag in aux:
  70. if flag == '-Wl,--start-group':
  71. flags += ['-Wl,--whole-archive'] + used_sanitize_libs + ['-Wl,--no-whole-archive']
  72. flags.append(flag)
  73. return flags
  74. def fix_cmd_for_musl(cmd):
  75. flags = []
  76. for flag in cmd:
  77. if flag not in MUSL_LIBS:
  78. flags.append(flag)
  79. return flags
  80. def fix_cmd_for_dynamic_cuda(cmd):
  81. flags = []
  82. for flag in cmd:
  83. if flag in CUDA_LIBRARIES:
  84. flags.append(CUDA_LIBRARIES[flag])
  85. else:
  86. flags.append(flag)
  87. return flags
  88. def gen_default_suppressions(inputs, output, source_root):
  89. import collections
  90. import os
  91. supp_map = collections.defaultdict(set)
  92. for filename in inputs:
  93. sanitizer = os.path.basename(filename).split('.', 1)[0]
  94. with open(os.path.join(source_root, filename)) as src:
  95. for line in src:
  96. line = line.strip()
  97. if not line or line.startswith('#'):
  98. continue
  99. supp_map[sanitizer].add(line)
  100. with open(output, "wb") as dst:
  101. for supp_type, supps in supp_map.items():
  102. dst.write('extern "C" const char *__%s_default_suppressions() {\n' % supp_type)
  103. dst.write(' return "{}";\n'.format('\\n'.join(sorted(supps))))
  104. dst.write('}\n')
  105. def parse_args():
  106. parser = optparse.OptionParser()
  107. parser.disable_interspersed_args()
  108. parser.add_option('--musl', action='store_true')
  109. parser.add_option('--custom-step')
  110. parser.add_option('--python')
  111. parser.add_option('--source-root')
  112. parser.add_option('--dynamic-cuda', action='store_true')
  113. parser.add_option('--arch')
  114. parser.add_option('--linker-output')
  115. parser.add_option('--whole-archive-peers', action='append')
  116. parser.add_option('--whole-archive-libs', action='append')
  117. return parser.parse_args()
  118. if __name__ == '__main__':
  119. opts, args = parse_args()
  120. cmd = remove_excessive_flags(args)
  121. if opts.musl:
  122. cmd = fix_cmd_for_musl(cmd)
  123. cmd = fix_sanitize_flag(cmd)
  124. if opts.dynamic_cuda:
  125. cmd = fix_cmd_for_dynamic_cuda(cmd)
  126. cmd = ProcessWholeArchiveOption(opts.arch, opts.whole_archive_peers, opts.whole_archive_libs).construct_cmd(cmd)
  127. if opts.custom_step:
  128. assert opts.python
  129. subprocess.check_call([opts.python] + [opts.custom_step] + args)
  130. supp, cmd = get_leaks_suppressions(cmd)
  131. if supp:
  132. src_file = "default_suppressions.cpp"
  133. gen_default_suppressions(supp, src_file, opts.source_root)
  134. cmd += [src_file]
  135. if opts.linker_output:
  136. stdout = open(opts.linker_output, 'w')
  137. else:
  138. stdout = sys.stdout
  139. rc = subprocess.call(cmd, shell=False, stderr=sys.stderr, stdout=stdout)
  140. sys.exit(rc)