Example #1
0
 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
Example #2
0
    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()