On Sat, Sep 10, 2022 at 12:49 AM Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> wrote: > > On 08/09/2022 14:28, Bin Meng wrote: > > > From: Bin Meng <bin.m...@windriver.com> > > > > At present packaging the required DLLs of QEMU executables is a > > manual process, and error prone. > > > > Actually build/config-host.mak contains a GLIB_BINDIR variable > > which is the directory where glib and other DLLs reside. This > > works for both Windows native build and cross-build on Linux. > > We can use it as the search directory for DLLs and automate > > the whole DLL packaging process. > > > > Signed-off-by: Bin Meng <bin.m...@windriver.com> > > --- > > > > meson.build | 1 + > > scripts/nsis.py | 46 ++++++++++++++++++++++++++++++++++++++++++---- > > 2 files changed, 43 insertions(+), 4 deletions(-) > > > > diff --git a/meson.build b/meson.build > > index c2adb7caf4..4c03850f9f 100644 > > --- a/meson.build > > +++ b/meson.build > > @@ -3657,6 +3657,7 @@ if host_machine.system() == 'windows' > > '@OUTPUT@', > > get_option('prefix'), > > meson.current_source_dir(), > > + config_host['GLIB_BINDIR'], > > host_machine.cpu(), > > '--', > > '-DDISPLAYVERSION=' + meson.project_version(), > > diff --git a/scripts/nsis.py b/scripts/nsis.py > > index baa6ef9594..03ed7608a2 100644 > > --- a/scripts/nsis.py > > +++ b/scripts/nsis.py > > @@ -18,12 +18,36 @@ def signcode(path): > > return > > subprocess.run([cmd, path]) > > > > +def find_deps(exe_or_dll, search_path, analyzed_deps): > > + deps = [exe_or_dll] > > + output = subprocess.check_output(["objdump", "-p", exe_or_dll], > > text=True) > > + output = output.split("\n") > > + for line in output: > > + if not line.startswith("\tDLL Name: "): > > + continue > > + > > + dep = line.split("DLL Name: ")[1].strip() > > + if dep in analyzed_deps: > > + continue > > + > > + dll = os.path.join(search_path, dep) > > + if not os.path.exists(dll): > > + # assume it's a Windows provided dll, skip it > > + continue > > + > > + analyzed_deps.add(dep) > > + # locate the dll dependencies recursively > > + rdeps = find_deps(dll, search_path, analyzed_deps) > > + deps.extend(rdeps) > > + > > + return deps > > > > def main(): > > parser = argparse.ArgumentParser(description="QEMU NSIS build > > helper.") > > parser.add_argument("outfile") > > parser.add_argument("prefix") > > parser.add_argument("srcdir") > > + parser.add_argument("dlldir") > > parser.add_argument("cpu") > > parser.add_argument("nsisargs", nargs="*") > > args = parser.parse_args() > > @@ -63,9 +87,26 @@ def main(): > > !insertmacro MUI_DESCRIPTION_TEXT ${{Section_{0}}} "{1}" > > """.format(arch, desc)) > > > > + search_path = args.dlldir > > + print("Searching '%s' for the dependent dlls ..." % search_path) > > + dlldir = os.path.join(destdir + prefix, "dll") > > + os.mkdir(dlldir) > > + > > for exe in glob.glob(os.path.join(destdir + prefix, "*.exe")): > > signcode(exe) > > > > + # find all dll dependencies > > + deps = set(find_deps(exe, search_path, set())) > > + deps.remove(exe) > > + > > + # copy all dlls to the DLLDIR > > + for dep in deps: > > + dllfile = os.path.join(dlldir, os.path.basename(dep)) > > + if (os.path.exists(dllfile)): > > + continue > > + print("Copying '%s' to '%s'" % (dep, dllfile)) > > + shutil.copy(dep, dllfile) > > + > > makensis = [ > > "makensis", > > "-V2", > > @@ -73,12 +114,9 @@ def main(): > > "-DSRCDIR=" + args.srcdir, > > "-DBINDIR=" + destdir + prefix, > > ] > > - dlldir = "w32" > > if args.cpu == "x86_64": > > - dlldir = "w64" > > makensis += ["-DW64"] > > - if os.path.exists(os.path.join(args.srcdir, "dll")): > > - makensis += ["-DDLLDIR={0}/dll/{1}".format(args.srcdir, > > dlldir)] > > + makensis += ["-DDLLDIR=" + dlldir] > > > > makensis += ["-DOUTFILE=" + args.outfile] + args.nsisargs > > subprocess.run(makensis) > > FWIW I wrote a similar script a while back to help package a custom Windows > build for > a client, however I used ldd instead of objdump since it provided the full > paths for > DLLs installed in the msys2/mingw-w64 environment via pacman which were > outside the > QEMU build tree. >
Yep, ldd also works, but only on Windows native build. objdump can work on both Windows native and Linux cross builds. > Once the complete list of DLLs was obtained, it was simple matter of > filtering out > those DLLs that started with the %WINDIR% prefix before copying them to the > final > distribution directory. > Regards, Bin