18adfeba9SMarc-André Lureau#!/usr/bin/env python3 28adfeba9SMarc-André Lureau# 38adfeba9SMarc-André Lureau# Copyright (C) 2020 Red Hat, Inc. 48adfeba9SMarc-André Lureau# 58adfeba9SMarc-André Lureau# SPDX-License-Identifier: GPL-2.0-or-later 68adfeba9SMarc-André Lureau 78adfeba9SMarc-André Lureauimport argparse 88adfeba9SMarc-André Lureauimport glob 98adfeba9SMarc-André Lureauimport os 108adfeba9SMarc-André Lureauimport shutil 118adfeba9SMarc-André Lureauimport subprocess 128adfeba9SMarc-André Lureauimport tempfile 138adfeba9SMarc-André Lureau 148adfeba9SMarc-André Lureau 158adfeba9SMarc-André Lureaudef signcode(path): 168adfeba9SMarc-André Lureau cmd = os.environ.get("SIGNCODE") 178adfeba9SMarc-André Lureau if not cmd: 188adfeba9SMarc-André Lureau return 198adfeba9SMarc-André Lureau subprocess.run([cmd, path]) 208adfeba9SMarc-André Lureau 21*a3c1e645SBin Mengdef find_deps(exe_or_dll, search_path, analyzed_deps): 22*a3c1e645SBin Meng deps = [exe_or_dll] 23*a3c1e645SBin Meng output = subprocess.check_output(["objdump", "-p", exe_or_dll], text=True) 24*a3c1e645SBin Meng output = output.split("\n") 25*a3c1e645SBin Meng for line in output: 26*a3c1e645SBin Meng if not line.startswith("\tDLL Name: "): 27*a3c1e645SBin Meng continue 28*a3c1e645SBin Meng 29*a3c1e645SBin Meng dep = line.split("DLL Name: ")[1].strip() 30*a3c1e645SBin Meng if dep in analyzed_deps: 31*a3c1e645SBin Meng continue 32*a3c1e645SBin Meng 33*a3c1e645SBin Meng dll = os.path.join(search_path, dep) 34*a3c1e645SBin Meng if not os.path.exists(dll): 35*a3c1e645SBin Meng # assume it's a Windows provided dll, skip it 36*a3c1e645SBin Meng continue 37*a3c1e645SBin Meng 38*a3c1e645SBin Meng analyzed_deps.add(dep) 39*a3c1e645SBin Meng # locate the dll dependencies recursively 40*a3c1e645SBin Meng rdeps = find_deps(dll, search_path, analyzed_deps) 41*a3c1e645SBin Meng deps.extend(rdeps) 42*a3c1e645SBin Meng 43*a3c1e645SBin Meng return deps 448adfeba9SMarc-André Lureau 458adfeba9SMarc-André Lureaudef main(): 468adfeba9SMarc-André Lureau parser = argparse.ArgumentParser(description="QEMU NSIS build helper.") 478adfeba9SMarc-André Lureau parser.add_argument("outfile") 488adfeba9SMarc-André Lureau parser.add_argument("prefix") 498adfeba9SMarc-André Lureau parser.add_argument("srcdir") 50*a3c1e645SBin Meng parser.add_argument("dlldir") 518adfeba9SMarc-André Lureau parser.add_argument("cpu") 528adfeba9SMarc-André Lureau parser.add_argument("nsisargs", nargs="*") 538adfeba9SMarc-André Lureau args = parser.parse_args() 548adfeba9SMarc-André Lureau 5593dbca2cSBin Meng # canonicalize the Windows native prefix path 5693dbca2cSBin Meng prefix = os.path.splitdrive(args.prefix)[1] 578adfeba9SMarc-André Lureau destdir = tempfile.mkdtemp() 588adfeba9SMarc-André Lureau try: 597f8c0440SBin Meng subprocess.run(["make", "install", "DESTDIR=" + destdir]) 608adfeba9SMarc-André Lureau with open( 6193dbca2cSBin Meng os.path.join(destdir + prefix, "system-emulations.nsh"), "w" 62c0879637SPeter Maydell ) as nsh, open( 6393dbca2cSBin Meng os.path.join(destdir + prefix, "system-mui-text.nsh"), "w" 64c0879637SPeter Maydell ) as muinsh: 65e422d92aSPeter Maydell for exe in sorted(glob.glob( 6693dbca2cSBin Meng os.path.join(destdir + prefix, "qemu-system-*.exe") 67e422d92aSPeter Maydell )): 688adfeba9SMarc-André Lureau exe = os.path.basename(exe) 698adfeba9SMarc-André Lureau arch = exe[12:-4] 708adfeba9SMarc-André Lureau nsh.write( 718adfeba9SMarc-André Lureau """ 728adfeba9SMarc-André Lureau Section "{0}" Section_{0} 738adfeba9SMarc-André Lureau SetOutPath "$INSTDIR" 748adfeba9SMarc-André Lureau File "${{BINDIR}}\\{1}" 758adfeba9SMarc-André Lureau SectionEnd 768adfeba9SMarc-André Lureau """.format( 778adfeba9SMarc-André Lureau arch, exe 788adfeba9SMarc-André Lureau ) 798adfeba9SMarc-André Lureau ) 80c0879637SPeter Maydell if arch.endswith('w'): 81c0879637SPeter Maydell desc = arch[:-1] + " emulation (GUI)." 82c0879637SPeter Maydell else: 83c0879637SPeter Maydell desc = arch + " emulation." 84c0879637SPeter Maydell 85c0879637SPeter Maydell muinsh.write( 86c0879637SPeter Maydell """ 87c0879637SPeter Maydell !insertmacro MUI_DESCRIPTION_TEXT ${{Section_{0}}} "{1}" 88c0879637SPeter Maydell """.format(arch, desc)) 898adfeba9SMarc-André Lureau 90*a3c1e645SBin Meng search_path = args.dlldir 91*a3c1e645SBin Meng print("Searching '%s' for the dependent dlls ..." % search_path) 92*a3c1e645SBin Meng dlldir = os.path.join(destdir + prefix, "dll") 93*a3c1e645SBin Meng os.mkdir(dlldir) 94*a3c1e645SBin Meng 9593dbca2cSBin Meng for exe in glob.glob(os.path.join(destdir + prefix, "*.exe")): 968adfeba9SMarc-André Lureau signcode(exe) 978adfeba9SMarc-André Lureau 98*a3c1e645SBin Meng # find all dll dependencies 99*a3c1e645SBin Meng deps = set(find_deps(exe, search_path, set())) 100*a3c1e645SBin Meng deps.remove(exe) 101*a3c1e645SBin Meng 102*a3c1e645SBin Meng # copy all dlls to the DLLDIR 103*a3c1e645SBin Meng for dep in deps: 104*a3c1e645SBin Meng dllfile = os.path.join(dlldir, os.path.basename(dep)) 105*a3c1e645SBin Meng if (os.path.exists(dllfile)): 106*a3c1e645SBin Meng continue 107*a3c1e645SBin Meng print("Copying '%s' to '%s'" % (dep, dllfile)) 108*a3c1e645SBin Meng shutil.copy(dep, dllfile) 109*a3c1e645SBin Meng 1108adfeba9SMarc-André Lureau makensis = [ 1118adfeba9SMarc-André Lureau "makensis", 1128adfeba9SMarc-André Lureau "-V2", 1138adfeba9SMarc-André Lureau "-NOCD", 1148adfeba9SMarc-André Lureau "-DSRCDIR=" + args.srcdir, 11593dbca2cSBin Meng "-DBINDIR=" + destdir + prefix, 1168adfeba9SMarc-André Lureau ] 1178adfeba9SMarc-André Lureau if args.cpu == "x86_64": 1188adfeba9SMarc-André Lureau makensis += ["-DW64"] 119*a3c1e645SBin Meng makensis += ["-DDLLDIR=" + dlldir] 1208adfeba9SMarc-André Lureau 1218adfeba9SMarc-André Lureau makensis += ["-DOUTFILE=" + args.outfile] + args.nsisargs 1228adfeba9SMarc-André Lureau subprocess.run(makensis) 1238adfeba9SMarc-André Lureau signcode(args.outfile) 1248adfeba9SMarc-André Lureau finally: 1258adfeba9SMarc-André Lureau shutil.rmtree(destdir) 1268adfeba9SMarc-André Lureau 1278adfeba9SMarc-André Lureau 1288adfeba9SMarc-André Lureauif __name__ == "__main__": 1298adfeba9SMarc-André Lureau main() 130