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: Mark Cave-Ayland
Subject: Re: [PATCH 3/7] scripts/nsis.py: Automatically package required DLLs of QEMU executables
Date: Fri, 9 Sep 2022 17:49:33 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.10.0

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.

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.


ATB,

Mark.



reply via email to

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