solus-packages/common/Scripts/find_deps.py
Ikey Doherty f30fa302cf common: Add initial version of find_deps
Signed-off-by: Ikey Doherty <ikey@solus-project.com>
2016-04-04 03:11:08 +01:00

96 lines
2.6 KiB
Python
Executable file

#!/usr/bin/env python2
from pisi.db.filesdb import FilesDB
import pisi.api
import magic
import os
import re
import subprocess
valid_dyn = ""
v_dyn = re.compile(r"ELF (64|32)\-bit LSB shared object,")
v_bin = re.compile(r"ELF (64|32)\-bit LSB executable,")
shared_lib = re.compile(r".*Shared library: \[(.*)\].*")
r_path = re.compile(r".*Library rpath: \[(.*)\].*")
def accumulate_dependencies(path, emul32=False):
output = subprocess.check_output("/usr/bin/readelf -d {}".format(path), shell=True)
check_deps = set()
r_paths = set()
valid_libs = set()
if emul32:
valid_libs.update(["/usr/lib32"])
else:
# Currently on Solus this is the same thing as /usr/lib.
valid_libs.update(["/usr/lib64"])
for line in output.split("\n"):
line = line.strip()
g = shared_lib.match(line)
if g:
check_deps.add(g.group(1))
r = r_path.match(line)
if r:
r_paths.add(r.group(1))
print("Deps: {}".format(", ".join(check_deps)))
dirname = os.path.dirname(path)
filter_deps = [x for x in check_deps for y in r_paths if os.path.exists(os.path.join(y, x)) or os.path.exists(os.path.join(dirname, x))]
print("Filtered by rpath: {}".format(", ".join(filter_deps)))
print("Got %d of rpath:" % len(filter_deps))
ret_deps = filter(lambda s: s not in filter_deps, check_deps)
print("Remaining deps: {}".format(", ".join(ret_deps)))
full_paths = [os.path.join(y,x) for x in ret_deps for y in valid_libs if os.path.exists(os.path.join(y,x))]
print("Full paths is now: {}".format(", ".join(full_paths)))
return full_paths
def is_dynamic_binary(path):
if not os.path.exists(path) or not os.path.isfile(path):
return (False,False)
try:
mg = magic.from_file(path)
except Exception, e:
return (False,False)
emul32 = "ELF 32" in mg
if v_bin.match(mg):
return (True,emul32)
if v_dyn.match(mg):
return (True,emul32)
return (False,False)
def clean_path(p):
if not p[0] == '/':
return "/%s" % p
def main():
le_files = set()
packages = ["gedit"]
for pkg in packages:
(stuff,files,repo) = pisi.api.info_name(pkg, True)
deps = set()
for f in files.list:
f = clean_path(f.path)
(dyn,emul32) = is_dynamic_binary(f)
if not dyn:
continue
deps.update(accumulate_dependencies(f, emul32))
print("Full binary dependencies for %s" % pkg)
for dep in deps:
print(" -> {}".format(dep))
if __name__ == "__main__":
main()