diff -r f70b728ea30c -r a1925fb7753a sbsv2/raptor/util/install-windows/raptorinstallermaker.py --- a/sbsv2/raptor/util/install-windows/raptorinstallermaker.py Wed Jul 28 13:20:46 2010 +0100 +++ b/sbsv2/raptor/util/install-windows/raptorinstallermaker.py Thu Aug 12 09:00:16 2010 +0100 @@ -1,4 +1,3 @@ -# # Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. # This component and the accompanying materials are made available @@ -12,110 +11,23 @@ # Contributors: # # Description: -# -#! python +# Raptor installer maker script - generates a Windows installer for Raptor using +# the NSIS package in the accompanying directory. Works on Windows and Linux. -# Raptor installer maker! - +import optparse import os import os.path +import re +import shutil +import stat import subprocess -import re -import optparse import sys import tempfile -import shutil import unzip +import zipfile tempdir = "" -parser = optparse.OptionParser() - -parser.add_option("-s", "--sbs-home", dest="sbshome", help="Path to use as SBS_HOME environment variable. If not present the script exits.") - -parser.add_option("-w", "--win32-support", dest="win32support", help="Path to Win32 support directory. If not present the script exits.") - -parser.add_option("-b", "--bv", dest="bv", help="Path to Binary variation CPP \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") - -parser.add_option("-c", "--cygwin", dest="cygwin", help="Path to Cygwin \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") - -parser.add_option("-m", "--mingw", dest="mingw", help="Path to MinGW \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") - -parser.add_option("-p", "--python", dest="python", help="Path to Python \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") - -parser.add_option("--prefix", dest="versionprefix", help="A string to use as a prefix to the Raptor version string. This will be present in the Raptor installer's file name, the installer's pages as well as the in output from sbs -v.", type="string", default="") - -parser.add_option("--postfix", dest="versionpostfix", help="A string to use as a postfix to the Raptor version string. This will be present in the Raptor installer's file name, the installer's pages as well as the in output from sbs -v.", type="string", default="") - -(options, args) = parser.parse_args() - -# Required directories inside the win32-support repository -win32supportdirs = {"bv":"bv", "cygwin":"cygwin", "mingw":"mingw", "python":"python264"} - -if options.sbshome == None: - print "ERROR: no SBS_HOME passed in. Exiting..." - sys.exit(2) - -if options.win32support == None: - print "ERROR: no win32support directory specified. Unable to proceed. Exiting..." - sys.exit(2) -else: - # Check for command line overrides to defaults - for directory in win32supportdirs: - print "TEST %s" % directory - value = getattr(options,directory) - print "value = %s" % str(value) - if value != None: # Command line override - if value.lower().startswith("win32support"): - # Strip off "WIN32SUPPORT\" and join to Win32 support location - win32supportdirs[directory] = os.path.join(options.win32support, value[13:]) - else: - # Relative to current directory - win32supportdirs[directory] = value - - else: # Use default location - win32supportdirs[directory] = os.path.join(options.win32support, win32supportdirs[directory]) - - print "\n\nwin32supportdirs = %s\n\n" % win32supportdirs - - # Check that all the specified directories exist and exit if any of them is missing. - for directory in win32supportdirs: - dir = win32supportdirs[directory] - if os.path.isdir(dir): - print "Found directory %s" % dir - else: - print "ERROR: directory %s does not exist. Cannot build installer. Exiting..." % dir - sys.exit(2) - -def generateinstallerversionheader(sbshome = None): - shellenv = os.environ.copy() - shellenv["PYTHONPATH"] = os.path.join(sbshome, "python") - - raptorversioncommand = "python -c \"import raptor_version; print raptor_version.numericversion()\"" - - # Raptor version is obtained from raptor_version module's numericversion function. - sbs_version_matcher = re.compile(".*(\d+\.\d+\.\d+).*", re.I) - - # Create Raptor subprocess - versioncommand = subprocess.Popen(raptorversioncommand, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=shellenv) - raptorversion = "" - # Get all the lines matching the RE - for line in versioncommand.stdout.readlines(): - res = sbs_version_matcher.match(line) - if res: - raptorversion = res.group(1) - print "Successfully determined Raptor version %s" % raptorversion - - versioncommand.wait() # Wait for process to end - - raptorversion_nsis_header_string = "# Raptor version file\n\n!define RAPTOR_VERSION %s\n" % raptorversion - - fh = open("raptorversion.nsh", "w") - fh.write(raptorversion_nsis_header_string) - fh.close() - print "Wrote raptorversion.nsh" - return 0 - def generateinstallerversion(sbshome = None): shellenv = os.environ.copy() shellenv["PYTHONPATH"] = os.path.join(sbshome, "python") @@ -140,15 +52,25 @@ return raptorversion def unzipnsis(pathtozip): - global tempdir - tempdir = tempfile.mkdtemp() - un = unzip.unzip() - print "Unzipping NSIS to %s..." % tempdir - un.extract(pathtozip, tempdir) - print "Done." - - return os.path.join(tempdir, "NSIS", "makensis.exe") - + global tempdir + tempdir = tempfile.mkdtemp() + un = unzip.unzip() + print "Unzipping NSIS to %s..." % tempdir + un.extract(pathtozip, tempdir) + print "Done." + + # Ensure the correct executable is called + dotexe="" + if "win" in sys.platform.lower(): + dotexe=".exe" + + makensispath = os.path.join(tempdir, "NSIS", "makensis" + dotexe) + + if not "win" in sys.platform.lower(): + os.chmod(makensispath, stat.S_IRWXU) + + return makensispath + def runmakensis(nsiscommand): # Create makensis subprocess print "Running NSIS command\n%s" % nsiscommand @@ -160,23 +82,198 @@ global tempdir print "Cleaning up temporary directory %s" % tempdir shutil.rmtree(tempdir,True) - try: - os.remove("raptorversion.nsh") - print "Successfully deleted raptorversion.nsh." - except: - print "ERROR: failed to remove raptorversion.nsh - remove manually if needed." print "Done." -makensispath = unzipnsis(".\\NSIS.zip") -# generateinstallerversionheader(options.sbshome) +def __writeDirTreeToArchive(zip, dirlist, sbshome, win32supportdirs=False): + """Auxilliary function to write all files in each directory trees of dirlist into the + open archive "zip" assuming valid sbshome; destination path is tweaked for win32supportdirs, + so set this to true when writing files into $SBS_HOME/win32""" + for name in dirlist: + files = os.walk(os.path.join(sbshome, name)) + for dirtuple in files: + filenames = dirtuple[2] + dirname = dirtuple[0] + for file in filenames: + # Filter out unwanted files + if not file.lower().endswith(".pyc") and \ + not file.lower().endswith(".project") and \ + not file.lower().endswith(".cproject") and \ + not file.lower().endswith(".pydevproject"): + origin = os.path.join(dirname, file) + + # For the win32 support directories, the destination is different + if win32supportdirs: + destination = os.path.join("sbs", "win32", os.path.basename(name.rstrip(os.sep)), + dirname.replace(name, "").strip(os.sep), file) + else: + destination = os.path.join("sbs", dirname.rstrip(os.sep).replace(sbshome, "").strip(os.sep), file) + + print "Compressing", origin, "\tto\t", destination + zip.write(origin, destination) + +def writeZip(filename, sbshome, sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir): + """Write a zip archive with file name "filename" assuming SBS_HOME is sbshome, and + that sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir are the win32 support directories.""" + + # *Files* in the top level SBS_HOME directory + sbshome_files = ["RELEASE-NOTES.html", "license.txt"] + + # Directories in SBS_HOME + sbshome_dirs = ["bin", "examples", "lib", "notes", "python", + "schema", "style", os.sep.join(["win32", "bin"])] + + # Win32 support directories + win32_dirs = [sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir] + + try: + # Open the zip archive for writing; if a file with the same + # name exists, it will be truncated to zero bytes before + # writing commences + zip = zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED) + + # Write the files in the top-level of SBS_HOME into the archive + for name in sbshome_files: + origin = os.path.join(sbshome, name) + destination = os.path.join("sbs", name) + print "Compressing", origin, "\tto\t", destination + zip.write(origin, destination) + + # Write all files in the the directories in the top-level of SBS_HOME into the archive + print "Reading the sbs directories..." + __writeDirTreeToArchive(zip, sbshome_dirs, sbshome, win32supportdirs=False) + print "Writing sbs directories to the archive is complete." + + # Write all files in the the win32 support directories in the top-level of SBS_HOME into the archive + print "Reading the win32 support directories" + __writeDirTreeToArchive(zip, win32_dirs, sbshome, win32supportdirs=True) + print "Writing win32 support directories to the archive is complete." + + zip.close() + print "Zipoutput: \"" + os.path.join(os.getcwd(), filename) + "\"" + print "Zip file creation successful." + except Exception, e: + print "Error: failed to create zip file: %s" % str(e) + sys.exit(2) + +# Create CLI and parse it +parser = optparse.OptionParser() + +parser.add_option("-s", "--sbs-home", dest="sbshome", help="Path to use as SBS_HOME environment variable. If not present the script exits.") + +parser.add_option("-w", "--win32-support", dest="win32support", help="Path to Win32 support directory. If not present the script exits.") + +parser.add_option("-b", "--bv", dest="bv", help="Path to Binary variation CPP \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") + +parser.add_option("-c", "--cygwin", dest="cygwin", help="Path to Cygwin \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") + +parser.add_option("-m", "--mingw", dest="mingw", help="Path to MinGW \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") + +parser.add_option("-p", "--python", dest="python", help="Path to Python \"root\" directory. Can be a full/relatitve path; prefix with \"WIN32SUPPORT\\\" to be relative to the Win32 support directory. Omitting this value will assume a default to a path inside the Win32 support directory.") + +parser.add_option("--prefix", dest="versionprefix", help="A string to use as a prefix to the Raptor version string. This will be present in the Raptor installer's file name, the installer's pages as well as the in output from sbs -v.", type="string", default="") + +parser.add_option("--postfix", dest="versionpostfix", help="A string to use as a postfix to the Raptor version string. This will be present in the Raptor installer's file name, the installer's pages as well as the in output from sbs -v.", type="string", default="") + +parser.add_option("--noclean", dest="noclean", help="Do not clean up the temporary directory created during the run.", action="store_true" , default=False) + +parser.add_option("--noexe", dest="noexe", help="Do not create a Windows .exe installer of the Raptor installation.", action="store_true" , default=False) + +parser.add_option("--nozip", dest="nozip", help="Do not create a zip archive of the Raptor installation.", action="store_true" , default=False) + +(options, args) = parser.parse_args() + +# Required directories inside the win32-support directory (i.e. the win32-support repository). +win32supportdirs = {"bv":"bv", "cygwin":"cygwin", "mingw":"mingw", "python":"python264"} + +if options.sbshome == None: + print "ERROR: no SBS_HOME passed in. Exiting..." + sys.exit(2) +elif not os.path.isdir(options.sbshome): + print "ERROR: the specified SBS_HOME directory \"%s\" does not exist. Cannot build installer. Exiting..." + sys.exit(2) + +if options.win32support == None: + print "ERROR: no win32support directory specified. Unable to proceed. Exiting..." + sys.exit(2) +else: + # Check for command line overrides to defaults + for directory in win32supportdirs: + print "Checking for location \"%s\"..." % directory + value = getattr(options,directory) + print "Directory is %s" % str(value) + if value != None: # Command line override + if value.lower().startswith("win32support"): + # Strip off "WIN32SUPPORT\" and join to Win32 support location + win32supportdirs[directory] = os.path.join(options.win32support, value[13:]) + else: + # Relative to current directory + win32supportdirs[directory] = value + + else: # Use default location + win32supportdirs[directory] = os.path.join(options.win32support, win32supportdirs[directory]) + + print "\n\nIdentified win32supportdirs are = %s\n\n" % win32supportdirs + + # Check that all the specified directories exist and exit if any of them is missing. + for directory in win32supportdirs: + dir = win32supportdirs[directory] + if os.path.isdir(dir): + print "Found directory %s" % dir + else: + print "ERROR: directory %s does not exist. Cannot build installer. Exiting..." % dir + sys.exit(2) + + raptorversion = options.versionprefix + generateinstallerversion(options.sbshome) + options.versionpostfix -nsiscommand = makensispath + " /DRAPTOR_LOCATION=%s /DBV_LOCATION=%s /DCYGWIN_LOCATION=%s /DMINGW_LOCATION=%s /DPYTHON_LOCATION=%s /DRAPTOR_VERSION=%s raptorinstallerscript.nsi" % (options.sbshome, - win32supportdirs["bv"], + +print "Using Raptor version %s ..." % raptorversion + +if not options.noexe: + makensispath = unzipnsis("." + os.sep + "NSIS.zip") + if "win" in sys.platform.lower(): + switch="/" + else: + switch="-" + + nsiscommand = (makensispath + " " + + switch + "DRAPTOR_LOCATION=%s " + + switch + "DBV_LOCATION=%s " + + switch + "DCYGWIN_LOCATION=%s " + + switch + "DMINGW_LOCATION=%s " + + switch + "DPYTHON_LOCATION=%s " + + switch + "DRAPTOR_VERSION=%s " + + "%s" ) % \ + ( options.sbshome, + win32supportdirs["bv"], win32supportdirs["cygwin"], win32supportdirs["mingw"], win32supportdirs["python"], - raptorversion) -print "nsiscommand = %s" % nsiscommand -runmakensis(nsiscommand) -cleanup() + raptorversion, + os.path.join(options.sbshome, "util", "install-windows", "raptorinstallerscript.nsi") + ) + + # On Linux, we need to run makensis via Bash, so that is can find all its + # internal libraries and header files etc. Makensis fails unless it + # is executed this way on Linux. + if "lin" in sys.platform.lower(): + nsiscommand = "bash -c \"%s\"" % nsiscommand + + runmakensis(nsiscommand) +else: + print "Not creating .exe as requested." +# Only clean NSIS installation in the temporary directory if requested +if not options.noclean: + cleanup() +else: + print "Not cleaning makensis in %s" % makensispath + +# Only create zip archive if required +if not options.nozip: + filename = "sbs-" + raptorversion + ".zip" + writeZip(filename, options.sbshome, win32supportdirs["bv"], win32supportdirs["cygwin"], win32supportdirs["mingw"], win32supportdirs["python"]) +else: + print "Not creating zip archive as requested." + +print "Finished." +