Skip to content

Commit

Permalink
scripts/nsis.py: Automatically package required DLLs of QEMU executables
Browse files Browse the repository at this point in the history
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>
Message-Id: <20220908132817.1831008-4-bmeng.cn@gmail.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
  • Loading branch information
lbmeng authored and stweil committed Oct 31, 2022
1 parent 93dbca2 commit a3c1e64
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
1 change: 1 addition & 0 deletions meson.build
Expand Up @@ -3616,6 +3616,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(),
Expand Down
46 changes: 42 additions & 4 deletions scripts/nsis.py
Expand Up @@ -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()
Expand Down Expand Up @@ -63,22 +87,36 @@ 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",
"-NOCD",
"-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)
Expand Down

0 comments on commit a3c1e64

Please sign in to comment.