Warning, /pim/trojita/packaging/mingw-bundledlls is written in an unsupported language. File is not indexed.
0001 #!/usr/bin/python3
0002
0003 # The MIT License (MIT)
0004 #
0005 # Copyright (c) 2015 Martin Preisler
0006 #
0007 # Permission is hereby granted, free of charge, to any person obtaining a copy
0008 # of this software and associated documentation files (the "Software"), to deal
0009 # in the Software without restriction, including without limitation the rights
0010 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0011 # copies of the Software, and to permit persons to whom the Software is
0012 # furnished to do so, subject to the following conditions:
0013 #
0014 # The above copyright notice and this permission notice shall be included in all
0015 # copies or substantial portions of the Software.
0016 #
0017 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0020 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0022 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0023 # SOFTWARE.
0024
0025
0026 import subprocess
0027 import os.path
0028 import argparse
0029 import shutil
0030
0031 # The mingw path matches where Fedora 21 installs mingw32
0032 default_path_prefixes = [
0033 "", "/usr/bin", "/usr/i686-w64-mingw32/sys-root/mingw/bin", "/mingw64/bin",
0034 ]
0035
0036 # This blacklist may need extending
0037 blacklist = [
0038 "advapi32.dll", "kernel32.dll", "msvcrt.dll", "ole32.dll", "user32.dll",
0039 "ws2_32.dll", "comdlg32.dll", "gdi32.dll", "imm32.dll", "oleaut32.dll",
0040 "shell32.dll", "winmm.dll", "winspool.drv", "wldap32.dll",
0041 "ntdll.dll", "d3d9.dll", "mpr.dll", "crypt32.dll", "dnsapi.dll",
0042 "shlwapi.dll", "version.dll", "iphlpapi.dll",
0043 ]
0044
0045
0046 def find_full_path(filename, path_prefixes):
0047 path = None
0048
0049 for path_prefix in path_prefixes:
0050 path_candidate = os.path.join(path_prefix, filename)
0051
0052 if os.path.exists(path_candidate):
0053 path = path_candidate
0054 break
0055
0056 if path is None:
0057 raise RuntimeError(
0058 "Can't find " + filename + ". If it is an inbuilt Windows DLL, "
0059 "please add it to the blacklist variable in the script and send "
0060 "a pull request!"
0061 )
0062
0063 return path
0064
0065
0066 def gather_deps(path, path_prefixes, seen):
0067 ret = [path]
0068 output = subprocess.check_output(["objdump", "-p", path]).decode('utf-8').split("\n")
0069 for line in output:
0070 if not line.startswith("\tDLL Name: "):
0071 continue
0072
0073 dep = line.split("DLL Name: ")[1].strip()
0074 ldep = dep.lower()
0075
0076 if ldep in blacklist:
0077 continue
0078
0079 if ldep in seen:
0080 continue
0081
0082 dep_path = find_full_path(dep, path_prefixes)
0083 seen.extend([ldep])
0084 subdeps = gather_deps(dep_path, path_prefixes, seen)
0085 ret.extend(subdeps)
0086
0087 return ret
0088
0089
0090 def main():
0091 parser = argparse.ArgumentParser()
0092 parser.add_argument(
0093 "exe_file",
0094 nargs='+',
0095 help="EXE or DLL file that you need to bundle dependencies for"
0096 )
0097 parser.add_argument(
0098 "--copy",
0099 action="store_true",
0100 help="In addition to printing out the dependencies, also copy them next to the exe_file"
0101 )
0102 parser.add_argument(
0103 "--upx",
0104 action="store_true",
0105 help="Only valid if --copy is provided. Run UPX on all the DLLs and EXE."
0106 )
0107 args = parser.parse_args()
0108
0109 if args.upx and not args.copy:
0110 raise RuntimeError("Can't run UPX if --copy hasn't been provided.")
0111
0112 seen = []
0113 all_deps = []
0114 for exe in args.exe_file:
0115 all_deps.extend(set(gather_deps(exe, default_path_prefixes, seen)))
0116 for exe in args.exe_file:
0117 all_deps.remove(exe)
0118
0119 print("\n".join(all_deps))
0120
0121 if args.copy:
0122 print("Copying enabled, will now copy all dependencies next to the exe_file.\n")
0123
0124 parent_dir = os.path.dirname(os.path.abspath(args.exe_file))
0125
0126 for dep in all_deps:
0127 target = os.path.join(parent_dir, os.path.basename(dep))
0128 print("Copying '%s' to '%s'" % (dep, target))
0129 shutil.copy(dep, parent_dir)
0130
0131 if args.upx:
0132 subprocess.call(["upx", target])
0133
0134
0135 if __name__ == "__main__":
0136 main()