sbsv2/raptor/util/install-windows/raptorinstallermaker.py
changeset 625 a1925fb7753a
parent 590 360bd6b35136
equal deleted inserted replaced
624:f70b728ea30c 625:a1925fb7753a
     1 #
       
     2 # Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     1 # Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 # All rights reserved.
     2 # All rights reserved.
     4 # This component and the accompanying materials are made available
     3 # This component and the accompanying materials are made available
     5 # under the terms of the License "Eclipse Public License v1.0"
     4 # under the terms of the License "Eclipse Public License v1.0"
     6 # which accompanies this distribution, and is available
     5 # which accompanies this distribution, and is available
    10 # Nokia Corporation - initial contribution.
     9 # Nokia Corporation - initial contribution.
    11 #
    10 #
    12 # Contributors:
    11 # Contributors:
    13 #
    12 #
    14 # Description: 
    13 # Description: 
    15 #
    14 # Raptor installer maker script - generates a Windows installer for Raptor using
    16 #! python
    15 # the NSIS package in the accompanying directory. Works on Windows and Linux.
    17 
    16 
    18 # Raptor installer maker!
    17 import optparse
    19 
       
    20 import os
    18 import os
    21 import os.path
    19 import os.path
       
    20 import re
       
    21 import shutil
       
    22 import stat
    22 import subprocess
    23 import subprocess
    23 import re
       
    24 import optparse
       
    25 import sys
    24 import sys
    26 import tempfile
    25 import tempfile
    27 import shutil
       
    28 import unzip
    26 import unzip
       
    27 import zipfile
    29 
    28 
    30 tempdir = ""
    29 tempdir = ""
    31 
    30 
    32 parser = optparse.OptionParser()
    31 def generateinstallerversion(sbshome = None):
    33 
       
    34 parser.add_option("-s", "--sbs-home", dest="sbshome", help="Path to use as SBS_HOME environment variable. If not present the script exits.")
       
    35 
       
    36 parser.add_option("-w", "--win32-support", dest="win32support", help="Path to Win32 support directory. If not present the script exits.")
       
    37 
       
    38 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.")
       
    39 
       
    40 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.")
       
    41 
       
    42 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.")
       
    43 
       
    44 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.")
       
    45 
       
    46 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="")
       
    47 
       
    48 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="")
       
    49 
       
    50 (options, args) = parser.parse_args()
       
    51 
       
    52 # Required directories inside the win32-support repository
       
    53 win32supportdirs = {"bv":"bv", "cygwin":"cygwin", "mingw":"mingw", "python":"python264"}
       
    54 
       
    55 if options.sbshome == None:
       
    56 	print "ERROR: no SBS_HOME passed in. Exiting..."
       
    57 	sys.exit(2)
       
    58 
       
    59 if options.win32support == None:
       
    60 	print "ERROR: no win32support directory specified. Unable to proceed. Exiting..."
       
    61 	sys.exit(2)
       
    62 else:
       
    63 	# Check for command line overrides to defaults
       
    64 	for directory in win32supportdirs:
       
    65 		print "TEST %s" % directory
       
    66 		value = getattr(options,directory)
       
    67 		print "value =  %s" % str(value)
       
    68 		if value != None: # Command line override
       
    69 			if value.lower().startswith("win32support"):
       
    70 				# Strip off "WIN32SUPPORT\" and join to Win32 support location
       
    71 				win32supportdirs[directory] = os.path.join(options.win32support, value[13:]) 
       
    72 			else:
       
    73 				# Relative to current directory
       
    74 				win32supportdirs[directory] = value
       
    75 
       
    76 		else: # Use default location
       
    77 			win32supportdirs[directory] = os.path.join(options.win32support, win32supportdirs[directory])
       
    78 	
       
    79 	print "\n\nwin32supportdirs = %s\n\n" % win32supportdirs
       
    80 
       
    81 	# Check that all the specified directories exist and exit if any of them is missing.
       
    82 	for directory in win32supportdirs:
       
    83 		dir = win32supportdirs[directory]
       
    84 		if os.path.isdir(dir):
       
    85 			print "Found directory %s" % dir
       
    86 		else:
       
    87 			print "ERROR: directory %s does not exist. Cannot build installer. Exiting..." % dir
       
    88 			sys.exit(2)
       
    89 
       
    90 def generateinstallerversionheader(sbshome = None):
       
    91 	shellenv = os.environ.copy()
    32 	shellenv = os.environ.copy()
    92 	shellenv["PYTHONPATH"] = os.path.join(sbshome, "python")
    33 	shellenv["PYTHONPATH"] = os.path.join(sbshome, "python")
    93 	
    34 	
    94 	raptorversioncommand = "python -c \"import raptor_version; print raptor_version.numericversion()\""
    35 	raptorversioncommand = "python -c \"import raptor_version; print raptor_version.numericversion()\""
    95 	
    36 	
   106 			raptorversion = res.group(1)
    47 			raptorversion = res.group(1)
   107 			print "Successfully determined Raptor version %s" % raptorversion
    48 			print "Successfully determined Raptor version %s" % raptorversion
   108 
    49 
   109 	versioncommand.wait() # Wait for process to end
    50 	versioncommand.wait() # Wait for process to end
   110 	
    51 	
   111 	raptorversion_nsis_header_string = "# Raptor version file\n\n!define RAPTOR_VERSION %s\n" % raptorversion
       
   112 	
       
   113 	fh = open("raptorversion.nsh", "w")
       
   114 	fh.write(raptorversion_nsis_header_string)
       
   115 	fh.close()
       
   116 	print "Wrote raptorversion.nsh"
       
   117 	return 0
       
   118 
       
   119 def generateinstallerversion(sbshome = None):
       
   120 	shellenv = os.environ.copy()
       
   121 	shellenv["PYTHONPATH"] = os.path.join(sbshome, "python")
       
   122 	
       
   123 	raptorversioncommand = "python -c \"import raptor_version; print raptor_version.numericversion()\""
       
   124 	
       
   125 	# Raptor version is obtained from raptor_version module's numericversion function.
       
   126 	sbs_version_matcher = re.compile(".*(\d+\.\d+\.\d+).*", re.I)
       
   127 	
       
   128 	# Create Raptor subprocess
       
   129 	versioncommand = subprocess.Popen(raptorversioncommand, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=shellenv)
       
   130 	raptorversion = ""
       
   131 	# Get all the lines matching the RE
       
   132 	for line in versioncommand.stdout.readlines():
       
   133 		res = sbs_version_matcher.match(line)
       
   134 		if res:
       
   135 			raptorversion = res.group(1)
       
   136 			print "Successfully determined Raptor version %s" % raptorversion
       
   137 
       
   138 	versioncommand.wait() # Wait for process to end
       
   139 	
       
   140 	return raptorversion
    52 	return raptorversion
   141 	
    53 	
   142 def unzipnsis(pathtozip):
    54 def unzipnsis(pathtozip):
   143     global tempdir
    55 	global tempdir
   144     tempdir = tempfile.mkdtemp()
    56 	tempdir = tempfile.mkdtemp()
   145     un = unzip.unzip()
    57 	un = unzip.unzip()
   146     print "Unzipping NSIS to %s..." % tempdir
    58 	print "Unzipping NSIS to %s..." % tempdir
   147     un.extract(pathtozip, tempdir)
    59 	un.extract(pathtozip, tempdir)
   148     print "Done."
    60 	print "Done."
   149     
    61 
   150     return os.path.join(tempdir, "NSIS", "makensis.exe")
    62 	# Ensure the correct executable is called	
   151     
    63 	dotexe=""
       
    64 	if "win" in sys.platform.lower():
       
    65 		dotexe=".exe"
       
    66 	
       
    67 	makensispath = os.path.join(tempdir, "NSIS", "makensis" + dotexe)
       
    68 	
       
    69 	if not "win" in sys.platform.lower():
       
    70 		os.chmod(makensispath, stat.S_IRWXU)
       
    71 
       
    72 	return makensispath
       
    73 	
   152 def runmakensis(nsiscommand):
    74 def runmakensis(nsiscommand):
   153 	# Create makensis subprocess
    75 	# Create makensis subprocess
   154 	print "Running NSIS command\n%s" % nsiscommand
    76 	print "Running NSIS command\n%s" % nsiscommand
   155 	makensis = subprocess.Popen(nsiscommand, shell=True)
    77 	makensis = subprocess.Popen(nsiscommand, shell=True)
   156 	makensis.wait() # Wait for process to end
    78 	makensis.wait() # Wait for process to end
   158 def cleanup():
    80 def cleanup():
   159 	""" Clean up tempdir """
    81 	""" Clean up tempdir """
   160 	global tempdir
    82 	global tempdir
   161 	print "Cleaning up temporary directory %s" % tempdir
    83 	print "Cleaning up temporary directory %s" % tempdir
   162 	shutil.rmtree(tempdir,True)
    84 	shutil.rmtree(tempdir,True)
       
    85 	print "Done."
       
    86 
       
    87 def __writeDirTreeToArchive(zip, dirlist, sbshome, win32supportdirs=False):
       
    88 	"""Auxilliary function to write all files in each directory trees of dirlist into the
       
    89 	open archive "zip" assuming valid sbshome; destination path is tweaked for win32supportdirs, 
       
    90 	so set this to true when writing files into $SBS_HOME/win32"""
       
    91 	for name in dirlist:
       
    92 		files = os.walk(os.path.join(sbshome, name))
       
    93 		for dirtuple in files:
       
    94 			filenames = dirtuple[2]
       
    95 			dirname = dirtuple[0]
       
    96 			for file in filenames:
       
    97 				# Filter out unwanted files
       
    98 				if not file.lower().endswith(".pyc") and \
       
    99 				not file.lower().endswith(".project") and \
       
   100 				not file.lower().endswith(".cproject") and \
       
   101 				not file.lower().endswith(".pydevproject"):
       
   102 					origin = os.path.join(dirname, file)
       
   103 					
       
   104 					# For the win32 support directories, the destination is different
       
   105 					if win32supportdirs:
       
   106 						destination = os.path.join("sbs", "win32", os.path.basename(name.rstrip(os.sep)), 
       
   107 												dirname.replace(name, "").strip(os.sep), file)
       
   108 					else:
       
   109 						destination = os.path.join("sbs", dirname.rstrip(os.sep).replace(sbshome, "").strip(os.sep), file)
       
   110 					
       
   111 					print "Compressing", origin, "\tto\t", destination 
       
   112 					zip.write(origin, destination)
       
   113 
       
   114 def writeZip(filename, sbshome, sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir):
       
   115 	"""Write a zip archive with file name "filename" assuming SBS_HOME is sbshome, and  
       
   116 	that sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir are the win32 support directories."""
       
   117 	
       
   118 	# *Files* in the top level SBS_HOME directory
       
   119 	sbshome_files = ["RELEASE-NOTES.html", "license.txt"]
       
   120 	
       
   121 	# Directories in SBS_HOME
       
   122 	sbshome_dirs = ["bin", "examples", "lib", "notes", "python", 
       
   123 				"schema", "style", os.sep.join(["win32", "bin"])]
       
   124 	
       
   125 	# Win32 support directories
       
   126 	win32_dirs = [sbsbvdir, sbscygwindir, sbsmingwdir, sbspythondir]
       
   127 	
   163 	try:
   128 	try:
   164 		os.remove("raptorversion.nsh")
   129 		# Open the zip archive for writing; if a file with the same
   165 		print "Successfully deleted raptorversion.nsh."
   130 		# name exists, it will be truncated to zero bytes before 
   166 	except:
   131 		# writing commences
   167 		print "ERROR: failed to remove raptorversion.nsh - remove manually if needed."
   132 		zip = zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED)
   168 	print "Done."
   133 		
   169 
   134 		# Write the files in the top-level of SBS_HOME into the archive
   170 makensispath = unzipnsis(".\\NSIS.zip")
   135 		for name in sbshome_files:
   171 # generateinstallerversionheader(options.sbshome)
   136 			origin = os.path.join(sbshome, name)
       
   137 			destination = os.path.join("sbs", name)
       
   138 			print "Compressing", origin, "\tto\t", destination 
       
   139 			zip.write(origin, destination)
       
   140 		
       
   141 		# Write all files in the the directories in the top-level of SBS_HOME into the archive
       
   142 		print "Reading the sbs directories..."
       
   143 		__writeDirTreeToArchive(zip, sbshome_dirs, sbshome, win32supportdirs=False)
       
   144 		print "Writing sbs directories to the archive is complete."
       
   145 		
       
   146 		# Write all files in the the win32 support directories in the top-level of SBS_HOME into the archive
       
   147 		print "Reading the win32 support directories"
       
   148 		__writeDirTreeToArchive(zip, win32_dirs, sbshome, win32supportdirs=True)
       
   149 		print "Writing win32 support directories to the archive is complete."
       
   150 		
       
   151 		zip.close()
       
   152 		print "Zipoutput: \"" + os.path.join(os.getcwd(), filename) + "\""
       
   153 		print "Zip file creation successful."
       
   154 	except Exception, e:
       
   155 		print "Error: failed to create zip file: %s" % str(e)
       
   156 		sys.exit(2)
       
   157 
       
   158 # Create CLI and parse it
       
   159 parser = optparse.OptionParser()
       
   160 
       
   161 parser.add_option("-s", "--sbs-home", dest="sbshome", help="Path to use as SBS_HOME environment variable. If not present the script exits.")
       
   162 
       
   163 parser.add_option("-w", "--win32-support", dest="win32support", help="Path to Win32 support directory. If not present the script exits.")
       
   164 
       
   165 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.")
       
   166 
       
   167 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.")
       
   168 
       
   169 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.")
       
   170 
       
   171 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.")
       
   172 
       
   173 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="")
       
   174 
       
   175 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="")
       
   176 
       
   177 parser.add_option("--noclean", dest="noclean", help="Do not clean up the temporary directory created during the run.", action="store_true" , default=False)
       
   178 
       
   179 parser.add_option("--noexe", dest="noexe", help="Do not create a Windows .exe installer of the Raptor installation.", action="store_true" , default=False)
       
   180 
       
   181 parser.add_option("--nozip", dest="nozip", help="Do not create a zip archive of the Raptor installation.", action="store_true" , default=False)
       
   182 
       
   183 (options, args) = parser.parse_args()
       
   184 
       
   185 # Required directories inside the win32-support directory (i.e. the win32-support repository).
       
   186 win32supportdirs = {"bv":"bv", "cygwin":"cygwin", "mingw":"mingw", "python":"python264"}
       
   187 
       
   188 if options.sbshome == None:
       
   189 	print "ERROR: no SBS_HOME passed in. Exiting..."
       
   190 	sys.exit(2)
       
   191 elif not os.path.isdir(options.sbshome):
       
   192 	print "ERROR: the specified SBS_HOME directory \"%s\" does not exist. Cannot build installer. Exiting..."
       
   193 	sys.exit(2)
       
   194 
       
   195 if options.win32support == None:
       
   196 	print "ERROR: no win32support directory specified. Unable to proceed. Exiting..."
       
   197 	sys.exit(2)
       
   198 else:
       
   199 	# Check for command line overrides to defaults
       
   200 	for directory in win32supportdirs:
       
   201 		print "Checking for location \"%s\"..." % directory
       
   202 		value = getattr(options,directory)
       
   203 		print "Directory is %s" % str(value)
       
   204 		if value != None: # Command line override
       
   205 			if value.lower().startswith("win32support"):
       
   206 				# Strip off "WIN32SUPPORT\" and join to Win32 support location
       
   207 				win32supportdirs[directory] = os.path.join(options.win32support, value[13:]) 
       
   208 			else:
       
   209 				# Relative to current directory
       
   210 				win32supportdirs[directory] = value
       
   211 
       
   212 		else: # Use default location
       
   213 			win32supportdirs[directory] = os.path.join(options.win32support, win32supportdirs[directory])
       
   214 		
       
   215 	print "\n\nIdentified win32supportdirs are = %s\n\n" % win32supportdirs
       
   216 
       
   217 	# Check that all the specified directories exist and exit if any of them is missing.
       
   218 	for directory in win32supportdirs:
       
   219 		dir = win32supportdirs[directory]
       
   220 		if os.path.isdir(dir):
       
   221 			print "Found directory %s" % dir
       
   222 		else:
       
   223 			print "ERROR: directory %s does not exist. Cannot build installer. Exiting..." % dir
       
   224 			sys.exit(2)
       
   225 
       
   226 
   172 raptorversion = options.versionprefix + generateinstallerversion(options.sbshome) + options.versionpostfix
   227 raptorversion = options.versionprefix + generateinstallerversion(options.sbshome) + options.versionpostfix
   173 nsiscommand = makensispath + " /DRAPTOR_LOCATION=%s /DBV_LOCATION=%s /DCYGWIN_LOCATION=%s /DMINGW_LOCATION=%s /DPYTHON_LOCATION=%s /DRAPTOR_VERSION=%s raptorinstallerscript.nsi" % (options.sbshome, 
   228 
   174 				win32supportdirs["bv"],
   229 print "Using Raptor version %s ..." % raptorversion
       
   230 
       
   231 if not options.noexe:
       
   232 	makensispath = unzipnsis("." + os.sep + "NSIS.zip")
       
   233 	if "win" in sys.platform.lower():
       
   234 		switch="/"
       
   235 	else:
       
   236 		switch="-"
       
   237 
       
   238 	nsiscommand = (makensispath + " " + 
       
   239 				switch + "DRAPTOR_LOCATION=%s "  + 
       
   240 				switch + "DBV_LOCATION=%s "  + 
       
   241 				switch + "DCYGWIN_LOCATION=%s "  + 
       
   242 				switch + "DMINGW_LOCATION=%s "  + 
       
   243 				switch + "DPYTHON_LOCATION=%s "  +
       
   244 				switch + "DRAPTOR_VERSION=%s " + 
       
   245 				"%s" ) % \
       
   246 			(	options.sbshome, 
       
   247 				win32supportdirs["bv"], 
   175 				win32supportdirs["cygwin"],
   248 				win32supportdirs["cygwin"],
   176 				win32supportdirs["mingw"],
   249 				win32supportdirs["mingw"],
   177 				win32supportdirs["python"],
   250 				win32supportdirs["python"],
   178 				raptorversion)
   251 				raptorversion,
   179 print "nsiscommand = %s" % nsiscommand
   252 				os.path.join(options.sbshome, "util", "install-windows", "raptorinstallerscript.nsi")
   180 runmakensis(nsiscommand)
   253 			)
   181 cleanup()
   254 	
   182 
   255 	# On Linux, we need to run makensis via Bash, so that is can find all its
       
   256 	# internal libraries and header files etc. Makensis fails unless it 
       
   257 	# is executed this way on Linux.
       
   258 	if "lin" in sys.platform.lower():
       
   259 		nsiscommand = "bash -c \"%s\"" % nsiscommand
       
   260 	
       
   261 	runmakensis(nsiscommand)
       
   262 else:
       
   263 	print "Not creating .exe as requested."
       
   264 
       
   265 # Only clean NSIS installation in the temporary directory if requested
       
   266 if not options.noclean:
       
   267 	cleanup()
       
   268 else:
       
   269 	print "Not cleaning makensis in %s" % makensispath
       
   270 
       
   271 # Only create zip archive if required
       
   272 if not options.nozip:
       
   273 	filename = "sbs-" + raptorversion + ".zip"
       
   274 	writeZip(filename, options.sbshome, win32supportdirs["bv"], win32supportdirs["cygwin"], win32supportdirs["mingw"], win32supportdirs["python"])
       
   275 else:
       
   276 	print "Not creating zip archive as requested."
       
   277 
       
   278 print "Finished."
       
   279