Added alternative packaging method for windows

This commit is contained in:
Veronica K. B. Olsen
2021-01-21 00:50:13 +01:00
parent 799c833a66
commit d425cdc27d
2 changed files with 94 additions and 55 deletions
+87 -47
View File
@@ -174,15 +174,12 @@ def freezePackage(buildWindowed, oneFile, makeSetup, hostOS):
# Make Simple Package # Make Simple Package
# =============================================================================================== # # =============================================================================================== #
def simplePackage(hostOS): def makeWindowsPackage():
"""Run zipapp to freeze the packages. This assumes zipapp and pip """Run zipapp to freeze the packages. This assumes zipapp and pip
are already installed. are already installed.
""" """
# import zipapp import urllib.request
import zipfile
from nw import __version__
exName = f"novelwriter-{__version__}-zipapp"
# Set Up Folder # Set Up Folder
# ============= # =============
@@ -190,7 +187,7 @@ def simplePackage(hostOS):
if not os.path.isdir("dist"): if not os.path.isdir("dist"):
os.mkdir("dist") os.mkdir("dist")
outDir = os.path.join("dist", exName) outDir = os.path.join("dist", "novelWriter")
libDir = os.path.join(outDir, "lib") libDir = os.path.join(outDir, "lib")
if os.path.isdir(outDir): if os.path.isdir(outDir):
shutil.rmtree(outDir) shutil.rmtree(outDir)
@@ -198,22 +195,63 @@ def simplePackage(hostOS):
os.mkdir(outDir) os.mkdir(outDir)
os.mkdir(libDir) os.mkdir(libDir)
# Download Python Embeddable
# ==========================
print("")
print("# Downloading Python Embeddable")
print("# =============================")
print("")
pyUrl = "https://www.python.org/ftp/python/3.8.7/python-3.8.7-embed-amd64.zip"
pyZip = os.path.join(outDir, "python_embed.zip")
print("URL: %s" % pyUrl)
urllib.request.urlretrieve(pyUrl, pyZip)
print("Extracting ...")
with zipfile.ZipFile(pyZip, "r") as inFile:
inFile.extractall(outDir)
os.unlink(pyZip)
print("")
# Make sample.zip
# ===============
try:
subprocess.call([sys.executable, "setup.py", "sample"])
except Exception as e:
print("Failed with error:")
print(str(e))
sys.exit(1)
# Copy Package Files # Copy Package Files
# ================== # ==================
print("")
print("# Copying Package Files")
print("# =====================")
print("")
copyList = ["CHANGELOG.md", "LICENSE.md", "requirements.txt"] copyList = ["CHANGELOG.md", "LICENSE.md", "requirements.txt"]
iconList = ["novelwriter.ico", "x-novelwriter-project.ico"] iconList = ["novelwriter.ico", "x-novelwriter-project.ico"]
cpIgnore = shutil.ignore_patterns("__pycache__") cpIgnore = shutil.ignore_patterns("__pycache__")
print("Copying: nw")
shutil.copytree("nw", os.path.join(outDir, "nw"), ignore=cpIgnore) shutil.copytree("nw", os.path.join(outDir, "nw"), ignore=cpIgnore)
for copyFile in copyList: for copyFile in copyList:
print("Copying: %s" % copyFile)
shutil.copy2(copyFile, os.path.join(outDir, copyFile)) shutil.copy2(copyFile, os.path.join(outDir, copyFile))
for iconFile in iconList: for iconFile in iconList:
print("Copying: %s" % iconFile)
shutil.copy2(os.path.join("setup", "icons", iconFile), os.path.join(outDir, iconFile)) shutil.copy2(os.path.join("setup", "icons", iconFile), os.path.join(outDir, iconFile))
with open(os.path.join(outDir, "__main__.py"), mode="w") as outFile: print("Writing: novelWriter.pyw")
with open(os.path.join(outDir, "novelWriter.pyw"), mode="w") as outFile:
outFile.write( outFile.write(
"#!/usr/bin/env python3\n" "#!\"pythonw.exe\"\n"
"\n"
"import os\n" "import os\n"
"import sys\n" "import sys\n"
"\n" "\n"
@@ -224,10 +262,16 @@ def simplePackage(hostOS):
" import nw\n" " import nw\n"
" nw.main()\n" " nw.main()\n"
) )
print("")
# Install Dependencies # Install Dependencies
# ==================== # ====================
print("")
print("# Installing Dependencies")
print("# =======================")
print("")
sysCmd = [sys.executable] sysCmd = [sys.executable]
sysCmd += "-m pip install -r requirements.txt --target".split() sysCmd += "-m pip install -r requirements.txt --target".split()
sysCmd += [libDir] sysCmd += [libDir]
@@ -243,39 +287,37 @@ def simplePackage(hostOS):
if os.path.isdir(chkDir) and chkDir.endswith(".dist-info"): if os.path.isdir(chkDir) and chkDir.endswith(".dist-info"):
shutil.rmtree(chkDir) shutil.rmtree(chkDir)
print("")
# Remove Unneeded Library Files # Remove Unneeded Library Files
# ============================= # =============================
delQtLibs = [ delQtLibs = [
"Qt5DBus", "opengl32sw.dll",
"Qt5Network", "Qt5DBus.dll",
"Qt5Qml", "Qt5Designer.dll",
"Qt5QmlModels", "Qt5Network.dll",
"Qt5QmlWorkerScript", "Qt5OpenGL.dll",
"Qt5Quick", "Qt5Qml.dll",
"Qt5Quick3D", "Qt5QmlModels.dll",
"Qt5Quick3DAssetImport", "Qt5QmlWorkerScript.dll",
"Qt5Quick3DRender", "Qt5Quick.dll",
"Qt5Quick3DRuntimeRender", "Qt5Quick3D.dll",
"Qt5Quick3DUtils", "Qt5Quick3DAssetImport.dll",
"Qt5QuickControls2", "Qt5Quick3DRender.dll",
"Qt5QuickParticles", "Qt5Quick3DRuntimeRender.dll",
"Qt5QuickShapes", "Qt5Quick3DUtils.dll",
"Qt5QuickTemplates2", "Qt5QuickControls2.dll",
"Qt5QuickTest", "Qt5QuickParticles.dll",
"Qt5QuickWidgets", "Qt5QuickShapes.dll",
"Qt5Sql", "Qt5QuickTemplates2.dll",
"Qt5QuickTest.dll",
"Qt5QuickWidgets.dll",
"Qt5Sql.dll",
] ]
qtLibDir = os.path.join(libDir, "PyQt5", "Qt", "lib") qtLibDir = os.path.join(libDir, "PyQt5", "Qt", "bin")
for libName in delQtLibs: for libName in delQtLibs:
if hostOS == OS_WIN: delFile = os.path.join(qtLibDir, libName)
libFile = f"{libName}.dll"
elif hostOS == OS_LINUX:
libFile = f"lib{libName}.so.5"
else:
continue
delFile = os.path.join(qtLibDir, libFile)
if os.path.isfile(delFile): if os.path.isfile(delFile):
print("Deleting: %s" % delFile) print("Deleting: %s" % delFile)
os.unlink(delFile) os.unlink(delFile)
@@ -284,11 +326,9 @@ def simplePackage(hostOS):
if os.path.isdir(qmlDir): if os.path.isdir(qmlDir):
shutil.rmtree(qmlDir) shutil.rmtree(qmlDir)
# zipapp.create_archive( print("")
# outDir, print("Done!")
# target=os.path.join("dist", f"{exName}.pyz"), print("")
# interpreter="/usr/bin/env python3"
# )
return return
@@ -387,7 +427,7 @@ if __name__ == "__main__":
oneFile = False oneFile = False
makeSetup = False makeSetup = False
doFreeze = False doFreeze = False
simPack = False winPack = False
helpMsg = ( helpMsg = (
"\n" "\n"
@@ -438,9 +478,9 @@ if __name__ == "__main__":
doFreeze = True doFreeze = True
oneFile = True oneFile = True
if "package" in sys.argv: if "winpack" in sys.argv:
sys.argv.remove("package") sys.argv.remove("winpack")
simPack = True winPack = True
if "setup" in sys.argv: if "setup" in sys.argv:
sys.argv.remove("setup") sys.argv.remove("setup")
@@ -451,8 +491,8 @@ if __name__ == "__main__":
print("Error: Argument 'setup' for Inno Setup is Windows only.") print("Error: Argument 'setup' for Inno Setup is Windows only.")
sys.exit(1) sys.exit(1)
if simPack: if winPack:
simplePackage(hostOS) makeWindowsPackage()
if doFreeze: if doFreeze:
freezePackage(buildWindowed, oneFile, makeSetup, hostOS) freezePackage(buildWindowed, oneFile, makeSetup, hostOS)
+7 -8
View File
@@ -6,7 +6,7 @@
#define nwAppVersion "%%version%%" #define nwAppVersion "%%version%%"
#define nwAppPublisher "novelWriter" #define nwAppPublisher "novelWriter"
#define nwAppURL "http://novelWriter.io" #define nwAppURL "http://novelWriter.io"
#define nwAppExeName "novelWriter.exe" #define nwAppExeName "novelWriter.pyw"
[Setup] [Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
@@ -45,16 +45,15 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip
Source: "{#nwAppDir}\novelWriter\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "{#nwAppDir}\novelWriter\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons] [Icons]
Name: "{autoprograms}\{#nwAppName}"; Filename: "{app}\{#nwAppExeName}" Name: "{autoprograms}\{#nwAppName}"; Filename: "{app}\pythonw.exe"; Parameters: "{#nwAppExeName}"; IconFilename: "{app}\novelwriter.ico"
Name: "{autodesktop}\{#nwAppName}"; Filename: "{app}\{#nwAppExeName}"; Tasks: desktopicon Name: "{autodesktop}\{#nwAppName}"; Filename: "{app}\pythonw.exe"; Parameters: "{#nwAppExeName}"; IconFilename: "{app}\novelwriter.ico"; Tasks: desktopicon;
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#nwAppName}"; Filename: "{app}\{#nwAppExeName}"; Tasks: quicklaunchicon
[Run] [Run]
Filename: "{app}\{#nwAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(nwAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent Filename: "{app}\pythonw.exe"; Parameters: "{#nwAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(nwAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Registry] [Registry]
Root: HKA; Subkey: "Software\Classes\.nwx\OpenWithProgids"; ValueType: string; ValueName: "novelWriterProject.nwx"; ValueData: ""; Flags: uninsdeletevalue Root: HKA; Subkey: "Software\Classes\.nwx\OpenWithProgids"; ValueType: string; ValueName: "novelWriterProject.nwx"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx"; ValueType: string; ValueName: ""; ValueData: "novelWriter Project File"; Flags: uninsdeletekey Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx"; ValueType: string; ValueName: ""; ValueData: "novelWriter Project File"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\assets\icons\x-novelwriter-project.ico" Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\nw\assets\icons\x-novelwriter-project.ico"
Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\novelWriter.exe"" ""%1""" Root: HKA; Subkey: "Software\Classes\novelWriterProject.nwx\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\pythonw.exe"" ""{app}\{#nwAppExeName}"" ""%1"""
Root: HKA; Subkey: "Software\Classes\Applications\novelWriter.exe\SupportedTypes"; ValueType: string; ValueName: ".nwx"; ValueData: "" Root: HKA; Subkey: "Software\Classes\Applications\{#nwAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".nwx"; ValueData: ""