From 827a4e7c7f435feb74fa30f60e9acbe8e28a55c7 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 31 Oct 2024 22:32:42 +0100 Subject: [PATCH] Add Python script which finds Windows dependencies Signed-off-by: Stefan Weil --- nsis/build.sh | 5 +++- nsis/find_deps.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100755 nsis/find_deps.py diff --git a/nsis/build.sh b/nsis/build.sh index 0e09e1e4..983942bb 100755 --- a/nsis/build.sh +++ b/nsis/build.sh @@ -107,8 +107,11 @@ export PKG_CONFIG_PATH make all training MINGW_INSTALL=${PWD}${MINGW} make install-jars install training-install html prefix="$MINGW_INSTALL" +test -d venv || python3 -m venv venv +source venv/bin/activate +pip install pefile mkdir -p dll -ln -sv $($ROOTDIR/nsis/find_deps.py $MINGW_INSTALL/bin/*.exe $MINGW_INSTALL/bin/*.dll | sort | uniq) dll/ +ln -sv $("$ROOTDIR/nsis/find_deps.py" "$MINGW_INSTALL"/bin/*.exe "$MINGW_INSTALL"/bin/*.dll) dll/ make winsetup prefix="$MINGW_INSTALL" # Copy result for upload. diff --git a/nsis/find_deps.py b/nsis/find_deps.py new file mode 100755 index 00000000..0aa12a91 --- /dev/null +++ b/nsis/find_deps.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 Stefan Weil +# +# SPDX-License-Identifier: MIT +# +# Find the DLL files which are required for a given set of +# Windows executables and libraries. + +import argparse +import os +import pefile + +VERBOSE = False + +def find_dependencies(binary, search_path, analyzed_deps): + pe = pefile.PE(binary) + pe.parse_data_directories() + if VERBOSE: + print(f'{binary}:') + # print(pe.dump_info()) + + for entry in pe.DIRECTORY_ENTRY_IMPORT: + name = entry.dll.decode('utf-8') + if name in analyzed_deps: + if VERBOSE: + print(f'skip {name} (already analyzed)') + continue + analyzed_deps.add(name) + fullpath = os.path.join(search_path, name) + if not os.path.exists(fullpath): + # Not found, maybe system DLL. Skip it. + if VERBOSE: + print(f'skip {name} (not found, maybe system DLL)') + continue + print(fullpath) + analyzed_deps = find_dependencies(fullpath, search_path, analyzed_deps) + + return analyzed_deps + +def main(): + """ + Command-line interface for universal dependency scanner. + """ + + parser = argparse.ArgumentParser(description='Find and copy DLL dependencies') + parser.add_argument('files', nargs='+', help='Paths to executable or library files') + parser.add_argument('--dlldir', dest='dlldir', default='/mingw64/bin/', + help='path to dll files') + + args = parser.parse_args() + + # try: + # Find dependencies + analyzed_deps = set() + for binary in args.files: + if True: + analyzed_deps = find_dependencies(binary, args.dlldir, analyzed_deps) + # except: + # print(f'error: failed to find dependencies for {binary}') + + +if __name__ == '__main__': + main()