qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 3/7] scripts/nsis.py: Automatically package required DLLs of


From: Bin Meng
Subject: Re: [PATCH 3/7] scripts/nsis.py: Automatically package required DLLs of QEMU executables
Date: Sat, 10 Sep 2022 08:37:36 +0800

On Sat, Sep 10, 2022 at 12:49 AM Mark Cave-Ayland
<mark.cave-ayland@ilande.co.uk> wrote:
>
> On 08/09/2022 14:28, Bin Meng wrote:
>
> > From: Bin Meng <bin.meng@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.meng@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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]