Files
DistMaker/tools/buildRelease
Norberto Lopez 1dc7490047 Changes associated with version 0.71:
[1] Added support to build compressed DMG files.
2024-12-18 18:30:36 -05:00

282 lines
9.4 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import glob
import os
import shutil
import signal
import subprocess
import sys
import traceback
# Define the (baseline) version
baseVersion = "0.71"
# Define relevant base names
appBaseName = 'DistMaker'
libBaseName = 'distMaker'
# Define the libraries DistMaker depends on
libList = ['glum-2.0.0.jar', 'guava-18.0.jar']
#libList += ['commons-compress-1.15.jar']
# Define the paths to various executables
antPath = '/spare/apache/apache-ant-1.10.8'
antExe = os.path.join(antPath, 'bin/ant')
jdkPath = '/spare/jdk-17'
jarExe = os.path.join(jdkPath, 'bin/jar')
javaExe = os.path.join(jdkPath, 'bin/java')
def checkForInstalledApps():
"""Checks for installed applications needed to build a release of the
DistMaker library / package.
"""
# Ensure required applications are installed
errList = []
for aPath in [antExe, jarExe, javaExe]:
if os.path.exists(aPath) == False:
errList.append('System executable is missing: ' + aPath)
if len(errList) > 0:
print('There are configuration errors with the environment or system.')
# print('System Path:' + str(sys.path))
print('Please correct the following:')
for aError in errList:
print('\t' + aError)
sys.exit(0)
def buildLibraryJar(aVersion):
"""Method that builds the library jars. Upon sucessful execution
jar files (binary + source) will be generated.
"""
# Note it is assumed that this is run from the path /proj/glum/
# Compile the java files
# Run the Ant script to build the class files
os.environ["JAVA_HOME"] = jdkPath
exeCmd = [antExe, '-f', 'tools/build.xml', 'compile']
retCode = subprocess.call(exeCmd)
if retCode != 0:
print('Failed while trying to run ant script. Exiting...\n')
sys.exit(0)
print('Finished executing Ant script.\n')
# Generate the manifest file
manifestFN = 'release/Manifest.txt'
# buildManifestFile(manifestFN)
# Build the (bin) jar file
jarBinFN = 'release/' + libBaseName + '-' + aVersion + '.jar'
# exeCmd = [jarExe, 'cfm', jarBinFN, manifestFN, '-C', 'bin/classes', '.']
exeCmd = [jarExe, 'cfM', jarBinFN, '-C', 'bin/classes', '.']
retCode = subprocess.call(exeCmd)
if retCode != 0:
print('Failed to build jar file: ' + jarBinFN)
exit(-1)
# Build the (src) jar file
jarSrcFN = 'release/' + libBaseName + '-' + aVersion + '-src.jar'
exeCmd = ['zip', '-D9q', '../' + jarSrcFN, '-r', '.']
retCode = subprocess.call(exeCmd, cwd='./src')
if retCode != 0:
print('Failed to build jar file: ' + jarSrcFN)
exit(-1)
# Remove the manifest file
# os.remove(manifestFN)
def buildRelease(aExtraTag, aDoNotClean=False):
"""Method that builds a release of DistMaker. Upon sucessful execution
the following will be created:
- distMaker-<version>.jar
- distMaker-<version>-src.jar
- DistMaker-<version>.tar.gz
"""
# Define the version to build
version = baseVersion
if aExtraTag != None:
if aExtraTag.startswith('.') or aExtraTag.startswith('-'):
version = baseVersion + aExtraTag
else:
version = baseVersion + '-' + aExtraTag
# Retrieve the install path
installPath = getInstallRoot()
installPath = os.path.dirname(installPath)
# Define the paths of interest
jarBinPathFN = os.path.join(installPath, 'release', libBaseName + '-' + version + '.jar')
jarSrcPathFN = os.path.join(installPath, 'release', libBaseName + '-' + version + '-src.jar')
workPath = os.path.join(installPath, 'release', appBaseName + '-' + version)
destFileGZ = os.path.join(installPath, 'release', appBaseName + '-' + version + '.tar.gz')
# Let the user know of the version we are building
print('Building ' + appBaseName + ' release ' + version + '...\n')
# Bail if there is a prior build
failMsgL = []
if os.path.exists(jarBinPathFN) == True:
failMsgL += ['Library binary file already exists: ' + jarBinPathFN]
if os.path.exists(jarSrcPathFN) == True:
failMsgL += ['Library source file already exists: ' + jarSrcPathFN]
if os.path.exists(workPath) == True:
failMsgL += ['Release folder already exists: ' + workPath]
if os.path.exists(destFileGZ) == True:
failMsgL += ['Release package already exists: ' + destFileGZ]
if len(failMsgL) > 0:
errPrintln('Aborting ' + appBaseName + ' release build. Reasons:')
for aFailMsg in failMsgL:
errPrintln(' - ' + aFailMsg)
errPrintln('')
exit(-1)
# Build the library jars
buildLibraryJar(version)
# Confirm that we have built the class files properly by retrieving the
# version from the built application jar and comparing it to our version.
tmpVersion = getLibraryBinVersion(jarBinPathFN)
if tmpVersion != version:
print('Failure: Embedded release: {} Expected: {}\n\tAborting...'.format(tmpVersion, version))
exit(-1)
# Laydown the structure, and let the user know of the version we are building
os.mkdir(workPath)
# Copy the regular documents
dstPath = os.path.join(workPath, 'doc')
os.mkdir(dstPath)
for aFile in ['QuickStartGuide.pdf', 'ReadMe.txt']:
srcPath = os.path.join(installPath, 'doc', aFile)
shutil.copy2(srcPath, dstPath)
# Copy the legal documents
dstPath = os.path.join(workPath, 'doc/legal')
os.mkdir(dstPath)
for aFile in glob.glob('doc/legal/*txt'):
srcPath = os.path.join(installPath, aFile)
shutil.copy2(srcPath, dstPath)
# Copy the libraries
dstPath = os.path.join(workPath, 'lib')
os.mkdir(dstPath)
for aLib in libList:
srcPath = os.path.join(installPath, 'lib', aLib)
shutil.copy2(srcPath, dstPath)
# Copy the (newly) built DistMaker (binary) library
shutil.copy2(jarBinPathFN, dstPath)
# Copy the scripts
dstPath = os.path.join(workPath, 'script')
os.mkdir(dstPath)
for aScript in ['appleUtils.py', 'linuxUtils.py', 'windowsUtils.py', 'buildDist.py', 'deployAppDist.py', 'deployJreDist.py', 'jreUtils.py', 'logUtils.py', 'miscUtils.py']:
srcPath = os.path.join(installPath, 'script', aScript)
shutil.copy2(srcPath, dstPath)
# Setup the template tree
dstPath = os.path.join(workPath, 'template')
os.makedirs(dstPath + '/apple')
os.makedirs(dstPath + '/background')
os.makedirs(dstPath + '/launch4j')
for aFile in ['appLauncher.jar', 'JreCatalog.txt', 'apple/.DS_Store.template', 'apple/JavaAppLauncher', 'background/background.png', 'launch4j/launch4j-3.14-linux-x64.tgz', 'launch4j/launch4j-3.14-linux.tgz', 'launch4j/launch4j-3.14-macosx-x86.tgz']:
srcPath = os.path.join(installPath, 'template', aFile)
shutil.copy2(srcPath, dstPath + '/' + aFile)
# Form the archive
exeCmd = ['tar', '-czf', destFileGZ, '-C', os.path.dirname(workPath), os.path.basename(workPath)]
retCode = subprocess.call(exeCmd)
if retCode != 0:
print('Failed to build tar.gz file: ' + destFileGZ)
exit(-1)
# Remove the workPath
if aDoNotClean == False:
shutil.rmtree(workPath)
print(appBaseName + ' release ' + version + ' built. Assets:')
for aFilePath in [jarBinPathFN, jarSrcPathFN, destFileGZ]:
print(' - ' + aFilePath)
print('')
def errPrintln(aMessage=''):
"""Print the specified string with a trailing newline to stderr. Each tab
character will be replaced with: 3 spaces"""
aMessage = aMessage.replace('\t', ' ')
sys.stderr.write(aMessage + '\n')
def getLibraryBinVersion(aJarBinPath):
"""Method that will return the version of the specified binary jar file.
The binary jar file will be queried (package distmaker.DistApp) and the
output will be parsed. Any failures will result in the abrupt exit of this
script."""
try:
cpStr = aJarBinPath
cpStr += ':lib/' + ':lib/'.join(libList)
exeCmd = [javaExe, '-cp', cpStr, 'distMaker.DistApp', '--version']
output = subprocess.check_output(exeCmd).decode('utf-8')
version = output.split()[1].strip()
return version
except Exception as aExp:
traceback.print_exc()
exit(-1)
def getInstallRoot():
"""Returns the root path where the running script is installed."""
argv = sys.argv;
installRoot = os.path.dirname(argv[0])
# print('appInstallRoot: ' + appInstallRoot)
return installRoot
def handleSignal(signal, frame):
"""Signal handler, typically used to capture ctrl-c."""
print('User aborted processing!')
sys.exit(0)
if __name__ == "__main__":
# Logic to capture Ctrl-C and bail
signal.signal(signal.SIGINT, handleSignal)
# Require python version 3.6 or later
targVer = (3, 6)
if sys.version_info < targVer:
print('The installed version of python is too old. Please upgrade.')
print(' Current version: ' + '.'.join(str(i) for i in sys.version_info))
print(' Require version: ' + '.'.join(str(i) for i in targVer))
sys.exit(-1)
tmpDescr = 'Utility to build a ' + appBaseName + ' release\n'
parser = argparse.ArgumentParser(prefix_chars='-', description=tmpDescr, add_help=False, fromfile_prefix_chars='@')
parser.add_argument('--help', '-h', help='Show this help message and exit.', action='help')
parser.add_argument('--doNotClean', default=False, action='store_true', help='Do NOT remove temporary work folder created while generating release.')
parser.add_argument('--doFullBuild', default=False, action='store_true', help='Force a full build of the main jar file. (Unsupported action)')
parser.add_argument('--extraTag', default=None, action='store', help='Specify an extra tag for to the version.')
# Intercept any request for a help message and bail
argv = sys.argv;
if '-h' in argv or '-help' in argv or '--help' in argv:
parser.print_help()
exit()
# Parse the args
parser.formatter_class.max_help_position = 50
args = parser.parse_args()
# TODO: Finish this functionality
if args.doFullBuild == True:
print("Unsupported action: [--doFullBuild]. Skipping...")
# Ensure required applications are installed
checkForInstalledApps()
buildRelease(args.extraTag, args.doNotClean)