split_link.py revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)# found in the LICENSE file. 4a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)"""Takes the same arguments as Windows link.exe, and a definition of libraries 6a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)to split into subcomponents. Does multiple passes of link.exe invocation to 7a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)determine exports between parts and generates .def and import libraries to 8a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)cause symbols to be available to other parts.""" 9a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import _winreg 11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import ctypes 12a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import os 13a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import re 14a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import subprocess 15a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)import sys 16a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 18a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 20a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def Log(message): 22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print 'split_link:', message 23a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def GetFlagsAndInputs(argv): 26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Parses the command line intended for link.exe and return the flags and 27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) input files.""" 28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) rsp_expanded = [] 29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for arg in argv: 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if arg[0] == '@': 31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) with open(arg[1:]) as rsp: 32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) rsp_expanded.extend(rsp.read().splitlines()) 33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) rsp_expanded.append(arg) 35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Use CommandLineToArgvW so we match link.exe parsing. 37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) try: 38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size = ctypes.c_int() 39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ptr = ctypes.windll.shell32.CommandLineToArgvW( 40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ctypes.create_unicode_buffer(' '.join(rsp_expanded)), 41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ctypes.byref(size)) 42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ref = ctypes.c_wchar_p * size.value 43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) raw = ref.from_address(ptr) 44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) args = [arg for arg in raw] 45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) finally: 46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ctypes.windll.kernel32.LocalFree(ptr) 47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs = [] 49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags = [] 50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for arg in args: 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) lower_arg = arg.lower() 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # We'll be replacing this ourselves. 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if lower_arg.startswith('/out:'): 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) continue 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (not lower_arg.startswith('/') and 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) lower_arg.endswith(('.obj', '.lib', '.res'))): 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs.append(arg) 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags.append(arg) 60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return flags, inputs 62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def GetOriginalLinkerPath(): 65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) try: 66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) val = _winreg.QueryValue(_winreg.HKEY_CURRENT_USER, 67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'Software\\Chromium\\split_link_installed') 68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if os.path.exists(val): 69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return val 70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) except WindowsError: 71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pass 72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) raise SystemExit("Couldn't read linker location from registry") 74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def PartFor(input_file, description_parts, description_all): 77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Determines which part a given link input should be put into (or all).""" 78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Check if it should go in all parts. 79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) input_file = input_file.lower() 80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if any(re.search(spec, input_file) for spec in description_all): 81a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return -1 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Or pick which particular one it belongs in. 83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for i, spec_list in enumerate(description_parts): 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if any(re.search(spec, input_file) for spec in spec_list): 85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return i 86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) raise ValueError("couldn't find location for %s" % input_file) 87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def ParseOutExternals(output): 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Given the stdout of link.exe, parses the error messages to retrieve all 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) symbols that are unresolved.""" 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) result = set() 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Styles of messages for unresolved externals, and a boolean to indicate 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # whether the error message emits the symbols with or without a leading 95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # underscore. 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unresolved_regexes = [ 97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) (re.compile(r' : error LNK2019: unresolved external symbol ".*" \((.*)\)' 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) r' referenced in function'), 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) False), 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) (re.compile(r' : error LNK2001: unresolved external symbol ".*" \((.*)\)$'), 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) False), 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) (re.compile(r' : error LNK2019: unresolved external symbol (.*)' 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) r' referenced in function '), 104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) True), 105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) (re.compile(r' : error LNK2001: unresolved external symbol (.*)$'), 106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) True), 107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ] 108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for line in output.splitlines(): 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) line = line.strip() 110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for regex, strip_leading_underscore in unresolved_regexes: 111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) mo = regex.search(line) 112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if mo: 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if strip_leading_underscore: 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) result.add(mo.group(1)[1:]) 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) result.add(mo.group(1)) 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) mo = re.search(r'fatal error LNK1120: (\d+) unresolved externals', output) 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Make sure we have the same number that the linker thinks we have. 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) assert mo or not result 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if len(result) != int(mo.group(1)): 123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print output 124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print 'Expecting %d, got %d' % (int(mo.group(1)), len(result)) 125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) assert len(result) == int(mo.group(1)) 126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return sorted(result) 127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def AsCommandLineArgs(items): 130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Intended for output to a response file. Quotes all arguments.""" 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return '\n'.join('"' + x + '"' for x in items) 132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def OutputNameForIndex(index): 135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Gets the final output DLL name, given a zero-based index.""" 136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if index == 0: 137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return "chrome.dll" 138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 'chrome%d.dll' % index 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def RunLinker(flags, index, inputs, phase): 143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Invokes the linker and returns the stdout, returncode and target name.""" 144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) rspfile = 'part%d_%s.rsp' % (index, phase) 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) with open(rspfile, 'w') as f: 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, AsCommandLineArgs(inputs) 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, AsCommandLineArgs(flags) 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) output_name = OutputNameForIndex(index) 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, '/ENTRY:ChromeEmptyEntry@12' 150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, '/OUT:' + output_name 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Log('[[[\n' + open(rspfile).read() + '\n]]]') 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) link_exe = GetOriginalLinkerPath() 153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) popen = subprocess.Popen([link_exe, '@' + rspfile], stdout=subprocess.PIPE) 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stdout, _ = popen.communicate() 155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return stdout, popen.returncode, output_name 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def GenerateDefFiles(unresolved_by_part): 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Given a list of unresolved externals, generates a .def file that will 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) cause all those symbols to be exported.""" 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) deffiles = [] 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('generating .def files') 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for i, part in enumerate(unresolved_by_part): 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) deffile = 'part%d.def' % i 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) with open(deffile, 'w') as f: 166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, 'LIBRARY %s' % OutputNameForIndex(i) 167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, 'EXPORTS' 168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for j, part in enumerate(unresolved_by_part): 169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if i == j: 170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) continue 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) print >> f, '\n'.join(' ' + export for export in part) 172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) deffiles.append(deffile) 173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return deffiles 174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def BuildImportLibs(flags, inputs_by_part, deffiles): 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Runs the linker to generate an import library.""" 178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) import_libs = [] 179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('building import libs') 180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for i, (inputs, deffile) in enumerate(zip(inputs_by_part, deffiles)): 181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) libfile = 'part%d.lib' % i 182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags_with_implib_and_deffile = flags + ['/IMPLIB:%s' % libfile, 183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) '/DEF:%s' % deffile] 184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RunLinker(flags_with_implib_and_deffile, i, inputs, 'implib') 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) import_libs.append(libfile) 186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return import_libs 187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def AttemptLink(flags, inputs_by_part, unresolved_by_part, deffiles, 190a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) import_libs): 191a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) """Tries to run the linker for all parts using the current round of 192a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) generated import libs and .def files. If the link fails, updates the 193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unresolved externals list per part.""" 194a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) dlls = [] 195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) all_succeeded = True 196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) new_externals = [] 197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('unresolveds now: %r' % [len(part) for part in unresolved_by_part]) 198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for i, (inputs, deffile) in enumerate(zip(inputs_by_part, deffiles)): 199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('running link, part %d' % i) 200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) others_implibs = import_libs[:] 201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) others_implibs.pop(i) 202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs_with_implib = inputs + filter(lambda x: x, others_implibs) 203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if deffile: 204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags = flags + ['/DEF:%s' % deffile, '/LTCG'] 205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stdout, rc, output = RunLinker(flags, i, inputs_with_implib, 'final') 206a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if rc != 0: 207a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) all_succeeded = False 208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) new_externals.append(ParseOutExternals(stdout)) 209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) new_externals.append([]) 211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) dlls.append(output) 212a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) combined_externals = [sorted(set(prev) | set(new)) 213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for prev, new in zip(unresolved_by_part, new_externals)] 214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return all_succeeded, dlls, combined_externals 215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)def main(): 218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags, inputs = GetFlagsAndInputs(sys.argv[1:]) 219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) partition_file = os.path.normpath( 220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) os.path.join(BASE_DIR, '../../../build/split_link_partition.py')) 221a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) with open(partition_file) as partition: 222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) description = eval(partition.read()) 223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs_by_part = [] 224a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) description_parts = description['parts'] 225a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # We currently assume that if a symbols isn't in dll 0, then it's in dll 1 226a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # when generating def files. Otherwise, we'd need to do more complex things 227a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # to figure out where each symbol actually is to assign it to the correct 228a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # .def file. 229a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) num_parts = len(description_parts) 230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) assert num_parts == 2, "Can't handle > 2 dlls currently" 231a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) description_parts.reverse() 232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs_by_part = [[] for _ in range(num_parts)] 233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for input_file in inputs: 234a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) i = PartFor(input_file, description_parts, description['all']) 235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if i == -1: 236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for part in inputs_by_part: 237a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) part.append(input_file) 238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs_by_part[i].append(input_file) 240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) inputs_by_part.reverse() 241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unresolved_by_part = [[] for _ in range(num_parts)] 243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) import_libs = [None] * num_parts 244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) deffiles = [None] * num_parts 245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for i in range(5): 247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('--- starting pass %d' % i) 248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ok, dlls, unresolved_by_part = AttemptLink( 249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flags, inputs_by_part, unresolved_by_part, deffiles, import_libs) 250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if ok: 251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break 252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) deffiles = GenerateDefFiles(unresolved_by_part) 253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) import_libs = BuildImportLibs(flags, inputs_by_part, deffiles) 254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else: 255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 1 256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Log('built %r' % dlls) 257a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 0 259a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 260a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)if __name__ == '__main__': 262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) sys.exit(main()) 263