-
-
Save kushaldas/d1e639d58eb86191d2485de0c6a59a0a to your computer and use it in GitHub Desktop.
Script to find the library dependencies from the PyQt5 wheel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import json | |
import subprocess | |
from pprint import pprint | |
from collections import defaultdict | |
dirname = "./venv/lib/python3.7/site-packages/PyQt5/" | |
alldetails = {} | |
reverse_deps = defaultdict(list) | |
deps = {} | |
missing = set() | |
filepath_missing = {} | |
def travarse_dir(path): | |
"Travarse a given directory" | |
for dirs, subdirs, files in os.walk(path): | |
for filename in files: | |
if filename.endswith(".so"): | |
yield os.path.join(dirs, filename) | |
def ldd(filepath): | |
"""Finds the library dependencies of a given library .so file. | |
""" | |
global alldetails | |
text = subprocess.check_output(["ldd", filepath]).decode("utf-8") | |
missing_deps = [] | |
deps = [] | |
for line in text.split("\n"): | |
line = line.strip() | |
line = line.replace("\t", " ") | |
words = line.split(" ") | |
# proper files will have 4 parts | |
if len(words) == 1: | |
continue | |
if len(words) != 4: | |
missing_deps.append(words[0]) | |
continue | |
# now properly parse | |
# system files will not have dirname | |
if words[2].find("venv") == -1: | |
deps.append(words[2]) | |
else: | |
print(f"Dependency found in the virtualenv {words[2]}") | |
result = {"missing": list(set(missing_deps)), "deps": list(set(deps))} | |
alldetails[os.path.basename(filepath)] = result | |
return result | |
def deb_package_name(filepath): | |
"returns the debian package name for a given file" | |
global reverse_deps | |
global missing | |
# first check cache | |
if filepath in deps: | |
print("Found it cache.") | |
return deps[filepath] | |
if filepath in missing: | |
print("Found it missing cache.") | |
return "" | |
text = "" | |
real = os.path.basename(filepath) | |
try: | |
text = ( | |
subprocess.check_output(["apt-file", "search", filepath]) | |
.decode("utf-8") | |
.strip() | |
) | |
for line in text.split("\n"): | |
words = line.split(":") | |
found = os.path.basename(words[1].strip()) | |
if real != found: | |
continue | |
name = words[0] | |
# Store in the global variables | |
reverse_deps[name].append(filepath) | |
deps[filepath] = name | |
print("Executed command to find") | |
return name | |
except subprocess.CalledProcessError: | |
print("Missing the above file.") | |
missing.add(filepath) | |
return "" | |
raise Exception("Should not reach") | |
return "" | |
def main(): | |
count = 0 | |
packages = set() | |
for name in travarse_dir(dirname): | |
# This variable stores for every .so file, which all are the missing dependency .so file. | |
local_missing = [] | |
result = ldd(name) | |
print(f"Processing {name}\n") | |
for dep in result["deps"]: | |
print(f"Finding package name for {dep}", end=" ") | |
package_name = deb_package_name(dep) | |
if package_name: | |
packages.add(package_name) | |
else: | |
local_missing.append(dep) | |
filepath_missing[name] = local_missing | |
pprint(packages) | |
print("The following files are missing:") | |
pprint(missing) | |
data = { | |
"alldetails": alldetails, | |
"missing": list(missing), | |
"filepath_missing": filepath_missing, | |
"deps": deps, | |
"reverse_deps": reverse_deps, | |
} | |
with open("libsearresult.josn", "w") as fobj: | |
json.dump(data, fp=fobj) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment