Files
DistMaker/script/windowsUtils.py
Norberto Lopez 8a7a9e5c5f Updated appLauncher.jar to reflect updates from the AppLauncher project
Updated launch4j to ver 3.8
Updated launcher (JavaAppLauncher) on the Apple platform to use InfiniteKind fork
Added support to build Windows executables from the Apple platform
2016-06-15 00:44:20 +00:00

249 lines
8.8 KiB
Python

#! /usr/bin/env python
import copy
import os
import platform
import shutil
import subprocess
import tempfile
import glob
import jreUtils
import miscUtils
def buildRelease(args, buildPath):
# We mutate args - thus make a custom copy
args = copy.copy(args)
# Retrieve vars of interest
appName = args.name
version = args.version
jreVerSpec = args.jreVerSpec
platformStr = 'windows'
# Check our system environment before proceeding
if checkSystemEnvironment() == False:
return
# Select the jreTarGzFile to utilize for static releases
jreTarGzFile = jreUtils.getJreTarGzFile(platformStr, jreVerSpec)
if jreTarGzFile == None:
# Let the user know that a compatible JRE was not found - thus no static release will be made.
print('[Warning] No compatible JRE ({0}) is available for the {1} platform. A static release will not be provided for the platform.'.format(jreVerSpec, platformStr.capitalize()))
# Form the list of distributions to build (dynamic and static JREs)
distList = [(appName + '-' + version, None)]
if jreTarGzFile != None:
distList.append((appName + '-' + version + '-jre', jreTarGzFile))
# Create a tmp (working) folder
tmpPath = tempfile.mkdtemp(prefix=platformStr, dir=buildPath)
# Unpack the proper launch4j release (for the platform we are
# running on) into the tmp (working) folder
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
l4jPath = os.path.join(appInstallRoot, 'template', 'launch4j')
if platform.system() == 'Darwin':
exeCmd = ['tar', '-C', tmpPath, '-xf', l4jPath + '/launch4j-3.8-macosx-x86-10.8.tgz']
else:
exeCmd = ['tar', '-C', tmpPath, '-xf', l4jPath + '/launch4j-3.8-linux.tgz']
retCode = subprocess.call(exeCmd)
if retCode != 0:
print('Failed to extract launch4j package...')
shutil.rmtree(tmpPath)
return
# Create the various distributions
for (aDistName, aJreTarGzFile) in distList:
print('Building {0} distribution: {1}'.format(platformStr.capitalize(), aDistName))
# Let the user know of the JRE tar.gz we are going to build with
if aJreTarGzFile != None:
print('\tUtilizing JRE: ' + aJreTarGzFile)
# Create the (top level) distribution folder
dstPath = os.path.join(tmpPath, aDistName)
os.mkdir(dstPath)
# Build the contents of the distribution folder
buildDistTree(buildPath, dstPath, args, aJreTarGzFile)
# Create the zip file
zipFile = os.path.join(buildPath, aDistName + ".zip")
cmd = ["jar", "-cMf", zipFile, "-C", dstPath, '.']
print('\tForming zip file: ' + zipFile)
proc = miscUtils.executeAndLog(cmd, "\t\tjar: ")
if proc.returncode != 0:
print('\tError: Failed to form zip file. Return code: ' + str(proc.returncode))
print('\tAborting build of release: ' + os.path.basename(zipFile) + '\n')
else:
print('\tFinished building release: ' + os.path.basename(zipFile) + '\n')
# Perform cleanup
shutil.rmtree(tmpPath)
def buildDistTree(buildPath, rootPath, args, jreTarGzFile):
# Retrieve vars of interest
appInstallRoot = miscUtils.getInstallRoot()
appInstallRoot = os.path.dirname(appInstallRoot)
appName = args.name
# Form the app contents folder
srcPath = os.path.join(buildPath, "delta")
dstPath = os.path.join(rootPath, "app")
shutil.copytree(srcPath, dstPath, symlinks=True)
# Copy dlls to the app directory so they can be found at launch
dllDir = os.path.join(rootPath, 'app', 'code', 'win')
for libPath in glob.iglob(os.path.join(dllDir, "*.lib")):
libFileName = os.path.basename(libPath)
srcPath = os.path.join(dllDir, libFileName)
linkPath = os.path.join(dstPath, libFileName)
shutil.copy(srcPath, linkPath)
for dllPath in glob.iglob(os.path.join(dllDir, "*.dll")):
dllFileName = os.path.basename(dllPath)
srcPath = os.path.join(dllDir, dllFileName)
linkPath = os.path.join(dstPath, dllFileName)
shutil.copy(srcPath, linkPath)
# Setup the launcher contents
exePath = os.path.join(rootPath, "launcher")
srcPath = os.path.join(appInstallRoot, "template/appLauncher.jar")
os.makedirs(exePath)
shutil.copy(srcPath, exePath);
# Build the java component of the distribution
if args.javaCode != None:
# Generate the iconFile
winIconFile = None
origIconFile = args.iconFile
if origIconFile != None:
winIconFile = os.path.join(rootPath, os.path.basename(origIconFile) + ".ico")
cmd = ['convert', origIconFile, winIconFile]
proc = miscUtils.executeAndLog(cmd, "\t\t(ImageMagick) convert: ")
if proc.returncode != 0:
if proc.returncode == None:
print('\t\tImageMagick convert does not appear to be properly installed.')
else:
print('\t\tImageMagick convert failed with eCode: ' + str(proc.returncode))
print('\t\tThere will be no windows icon file.')
winIconFile = None
# Form the launch4j config file
configFile = os.path.join(rootPath, appName + ".xml")
buildLaunch4JConfig(configFile, args, jreTarGzFile, winIconFile)
# Build the Windows executable
tmpPath = os.path.dirname(rootPath)
launch4jExe = os.path.join(tmpPath, "launch4j", "launch4j")
cmd = [launch4jExe, configFile]
print('\tBuilding windows executable via launch4j')
proc = miscUtils.executeAndLog(cmd, "\t\t")
if proc.returncode != 0:
print('\tError: Failed to build executable. Return code: ' + str(proc.returncode))
# Unpack the JRE and set up the JRE tree
if jreTarGzFile != None:
jreUtils.unpackAndRenameToStandard(jreTarGzFile, rootPath)
# Perform cleanup
os.remove(configFile)
if winIconFile != None:
os.remove(winIconFile)
def buildLaunch4JConfig(destFile, args, jreTarGzFile, iconFile):
f = open(destFile, 'wb')
writeln(f, 0, "<launch4jConfig>")
if args.debug == True:
writeln(f, 1, "<headerType>console</headerType>");
else:
writeln(f, 1, "<headerType>gui</headerType>");
writeln(f, 1, "<outfile>" + args.name + ".exe</outfile>");
writeln(f, 1, "<dontWrapJar>true</dontWrapJar>");
writeln(f, 1, "<errTitle>" + args.name + "</errTitle>");
writeln(f, 1, "<downloadUrl>http://java.com/download</downloadUrl>");
# writeln(f, 1, "<supportUrl>url</supportUrl>");
writeln(f, 1, "<cmdLine>app.cfg</cmdLine>");
writeln(f, 1, "<chdir>app/</chdir>");
writeln(f, 1, "<priority>normal</priority>");
writeln(f, 1, "<customProcName>true</customProcName>");
writeln(f, 1, "<stayAlive>false</stayAlive>");
if iconFile != None:
writeln(f, 1, "<icon>" + iconFile + "</icon>");
writeln(f, 1, "<classPath>");
writeln(f, 2, "<mainClass>appLauncher.AppLauncher</mainClass>");
writeln(f, 2, "<cp>../launcher/appLauncher.jar</cp>");
writeln(f, 1, "</classPath>");
if args.forceSingleInstance != False:
writeln(f, 0, "");
writeln(f, 1, "<singleInstance>");
writeln(f, 2, "<mutexName>" + args.name + ".mutex</mutexName>");
writeln(f, 2, "<windowTitle>" + args.name + "</windowTitle>");
writeln(f, 1, "</singleInstance>");
writeln(f, 0, "");
writeln(f, 1, "<jre>");
if jreTarGzFile != None:
jrePath = jreUtils.getBasePathForJreTarGzFile(jreTarGzFile)
writeln(f, 2, "<path>" + jrePath + "</path>");
else:
jreVer = getJreMajorVersion(args.jreVerSpec)
writeln(f, 2, "<minVersion>" + jreVer + "</minVersion>"); # Valid values: '1.7.0' or '1.8.0' ...
writeln(f, 2, "<jdkPreference>preferJre</jdkPreference>"); # Valid values: jreOnlyjdkOnly|preferJre|preferJdk
for aJvmArg in args.jvmArgs:
writeln(f, 2, "<opt>" + aJvmArg + "</opt>");
writeln(f, 2, "<opt>-Djava.system.class.loader=appLauncher.RootClassLoader</opt>");
writeln(f, 1, "</jre>");
writeln(f, 0, "");
writeln(f, 1, "<messages>");
writeln(f, 2, "<startupErr>" + args.name + " error...</startupErr>");
writeln(f, 2, "<bundledJreErr>Failed to locate the bundled JRE</bundledJreErr>");
writeln(f, 2, "<jreVersionErr>Located JRE is not the proper version.</jreVersionErr>");
writeln(f, 2, "<launcherErr>Failed to launch " + args.name + "</launcherErr>");
writeln(f, 1, "</messages>");
writeln(f, 0, "")
writeln(f, 0, "</launch4jConfig>")
f.write('\n')
f.close()
def checkSystemEnvironment():
"""Checks to ensure that all system application / environment variables needed to build a Windows distribution are installed
and properly configured. Returns False if the system environment is insufficient"""
return True
def getJreMajorVersion(aJreVerSpec):
"""Returns the minimum version of the JRE to utilize based on the passed in JreVerSpec. If aJreVerSpec is None then
the value specified in jreUtils.getDefaultJreVerStr() will be utilized. If that value is None then the value of
1.8.0 will be utilized."""
if aJreVerSpec == None:
aJreVerSpec = [jreUtils.getDefaultJreVerStr()]
minJreVerStr = aJreVerSpec[0]
if minJreVerStr == None:
minJreVerStr = '1.8.0'
try:
verArr = jreUtils.verStrToVerArr(minJreVerStr)
except:
return '1.8.0'
if len(verArr) <= 1: return '1.8.0'
if len(verArr) == 2: verArr.append(0)
return jreUtils.verArrToVerStr(verArr)
def writeln(f, tabL, aStr, tabStr='\t'):
tStr = ''
for i in range(tabL):
tStr += tabStr
f.write(tStr + aStr + '\n')