def getneeded(self, lib_path): """Given a path to a shared library, return a list containing the ICU and iKnow engine direct dependencies of that shared library. The list may contain the names of the dependencies or paths to the dependencies, depending on what is embedded in the executable.""" if sys.platform == 'darwin': cmd = ['otool', '-L', lib_path] p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True) lib_name = os.path.basename(lib_path) needed = map(up_to_first_space, p.stdout.rstrip().split('\n')) needed = (s.strip() for s in needed) return [ s for s in needed if os.path.basename(s) != lib_name and ( fnmatch.fnmatch(s, '*' + iculibs_name_pattern) or fnmatch.fnmatch(s, '*' + enginelibs_name_pattern)) ] elif sys.platform == 'linux': cmd = self._patchelf + ['--print-needed', lib_path] p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True) return [ s for s in p.stdout.split() if fnmatch.fnmatch(s, iculibs_name_pattern) or fnmatch.fnmatch(s, enginelibs_name_pattern) ] else: # win32 pe = pefile.PE(lib_path) needed = [] if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): for entry in pe.DIRECTORY_ENTRY_IMPORT: dll_name = entry.dll.decode('utf-8') if (fnmatch.fnmatch(dll_name, iculibs_name_pattern) or fnmatch.fnmatch(dll_name, enginelibs_name_pattern)): needed.append(dll_name) pe.close() return needed
def replaceneeded(self, lib_path, old_deps, name_map): """For the shared library at lib_path, replace its declared dependencies on old_deps with those in name_map. old_deps: a nonempty list of dependencies (either by name or path, depending on the value currently in the shared library) that the shared library has name_map: a dict that maps an old dependency NAME to a new NAME""" if sys.platform == 'darwin': cmd = ['install_name_tool'] for old_dep in old_deps: cmd.append('-change') cmd.append(old_dep) old_dep_name = os.path.basename(old_dep) new_dep_name = name_map[old_dep_name] new_dep = os.path.join('@loader_path', new_dep_name) cmd.append(new_dep) cmd.append(lib_path) subprocess.run(cmd, check=True) elif sys.platform == 'linux': cmd = self._patchelf[:] for old_dep in old_deps: cmd.append('--replace-needed') cmd.append(old_dep) cmd.append(name_map[old_dep]) cmd.append(lib_path) subprocess.run(cmd, check=True) else: # win32 with open(lib_path, 'rb') as f: buf = f.read() buf = machomachomangler.pe.redll( buf, { dep.encode('utf-8'): name_map[dep].encode('utf-8') for dep in old_deps }) with open(lib_path, 'wb') as f: f.write(buf) pe = pefile.PE(lib_path) pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum() pe.write(lib_path) pe.close()