Browse Source

makepanda: Create 7-zip debug symbol archives by default, if available

7-zip archives will only be created if 7-zip is available during the build phase. When 7-zip is unavailable, ZIP archives will be created as a fallback.

Benchmarks:

- Default ZIP compression: ~23.5 seconds, 162 MB
- 7-zip compression: ~7.5 seconds, 108 MB
- 7-zip compression, --lzma set: ~44 seconds, 88 MB
- 7-zip compression, solid archive: ~5 minutes, 83 MB (not implemented)

Closes #1261
Disyer 3 years ago
parent
commit
a08e42d015
2 changed files with 67 additions and 10 deletions
  1. 47 10
      makepanda/makepackage.py
  2. 20 0
      makepanda/makepandacore.py

+ 47 - 10
makepanda/makepackage.py

@@ -189,31 +189,65 @@ def MakeInstallerNSIS(version, file, title, installdir, compressor="lzma", **kwa
     oscmd(cmd)
 
 
-def MakeDebugSymbolArchive(zipname, dirname):
-    outputdir = GetOutputDir()
-
+def MakeDebugSymbolZipArchive(zipname):
     import zipfile
 
-    zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
+    outputdir = GetOutputDir()
+    zip = zipfile.ZipFile(zipname + '.zip', 'w', zipfile.ZIP_DEFLATED)
 
     for fn in glob.glob(os.path.join(outputdir, 'bin', '*.pdb')):
-        zip.write(fn, dirname + '/bin/' + os.path.basename(fn))
+        zip.write(fn, 'bin/' + os.path.basename(fn))
 
     for fn in glob.glob(os.path.join(outputdir, 'panda3d', '*.pdb')):
-        zip.write(fn, dirname + '/panda3d/' + os.path.basename(fn))
+        zip.write(fn, 'panda3d/' + os.path.basename(fn))
 
     for fn in glob.glob(os.path.join(outputdir, 'plugins', '*.pdb')):
-        zip.write(fn, dirname + '/plugins/' + os.path.basename(fn))
+        zip.write(fn, 'plugins/' + os.path.basename(fn))
 
     for fn in glob.glob(os.path.join(outputdir, 'python', '*.pdb')):
-        zip.write(fn, dirname + '/python/' + os.path.basename(fn))
+        zip.write(fn, 'python/' + os.path.basename(fn))
 
     for fn in glob.glob(os.path.join(outputdir, 'python', 'DLLs', '*.pdb')):
-        zip.write(fn, dirname + '/python/DLLs/' + os.path.basename(fn))
+        zip.write(fn, 'python/DLLs/' + os.path.basename(fn))
 
     zip.close()
 
 
+def MakeDebugSymbolSevenZipArchive(zipname, compressor):
+    zipname += '.7z'
+    flags = ['-t7z', '-y']
+
+    if compressor == 'zlib':
+        # This will still build an LZMA2 archive by default,
+        # but will complete significantly faster.
+        flags.extend(['-mx=3'])
+
+    # Remove the old archive before proceeding.
+    if os.path.exists(zipname):
+        os.remove(zipname)
+
+    outputdir = GetOutputDir()
+
+    # We'll be creating the archive inside the output
+    # directory, so we need the relative path to the archive
+    zipname = os.path.relpath(zipname, outputdir)
+
+    # Create a 7-zip archive, including all *.pdb files
+    # that are not in the tmp folder
+    cmd = [GetSevenZip(), 'a']
+    cmd.extend(flags)
+    cmd.extend(['-ir!*.pdb', '-x!' + os.path.join('tmp', '*'), zipname])
+
+    subprocess.call(cmd, stdout=subprocess.DEVNULL, cwd=outputdir)
+
+
+def MakeDebugSymbolArchive(zipname, compressor):
+    if HasSevenZip():
+        MakeDebugSymbolSevenZipArchive(zipname, compressor)
+    else:
+        MakeDebugSymbolZipArchive(zipname)
+
+
 def MakeInstallerLinux(version, debversion=None, rpmversion=None, rpmrelease=1,
                        python_versions=[], **kwargs):
     outputdir = GetOutputDir()
@@ -969,6 +1003,7 @@ def MakeInstallerAndroid(version, **kwargs):
 
 def MakeInstaller(version, **kwargs):
     target = GetTarget()
+
     if target == 'windows':
         dir = kwargs.pop('installdir', None)
         if dir is None:
@@ -991,8 +1026,10 @@ def MakeInstaller(version, **kwargs):
         if GetTargetArch() == 'x64':
             fn += '-x64'
 
+        compressor = kwargs.get('compressor')
+
         MakeInstallerNSIS(version, fn + '.exe', title, dir, **kwargs)
-        MakeDebugSymbolArchive(fn + '-pdb.zip', dir)
+        MakeDebugSymbolArchive(fn + '-pdb', compressor)
     elif target == 'linux':
         MakeInstallerLinux(version, **kwargs)
     elif target == 'darwin':

+ 20 - 0
makepanda/makepandacore.py

@@ -572,6 +572,26 @@ def GetFlexVersion():
         Warn("Unable to detect flex version")
         return (0, 0, 0)
 
+SEVENZIP = None
+def GetSevenZip():
+    global SEVENZIP
+    if SEVENZIP is not None:
+        return SEVENZIP
+
+    win_util = os.path.join(GetThirdpartyBase(), 'win-util')
+    if GetHost() == 'windows' and os.path.isdir(win_util):
+        SEVENZIP = GetThirdpartyBase() + "/win-util/7za.exe"
+    elif LocateBinary('7z'):
+        SEVENZIP = '7z'
+    else:
+        # We don't strictly need it, so don't give an error
+        return None
+
+    return SEVENZIP
+
+def HasSevenZip():
+    return GetSevenZip() is not None
+
 ########################################################################
 ##
 ## LocateBinary