From 084666bef3d944c8174578d4aa75c9b1643ddeff Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 3 Jan 2012 23:07:58 +0000 Subject: [PATCH] First steps toward developing a Windows installer --- SConstruct | 9 ++++- platform/windows/cantera.wxs | 67 ++++++++++++++++++++++++++++++++++ platform/windows/wxsgen.py | 69 ++++++++++++++++++++++++++++++++++++ site_scons/buildutils.py | 10 ++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 platform/windows/cantera.wxs create mode 100644 platform/windows/wxsgen.py diff --git a/SConstruct b/SConstruct index 83bbdc16b..24ab547b0 100644 --- a/SConstruct +++ b/SConstruct @@ -13,6 +13,8 @@ Basic usage: 'scons test-clean' - Delete files created while running the regression tests. + + 'scons msi' - Build a Windows installer (.msi) for Cantera """ from buildutils import * @@ -646,10 +648,15 @@ env['ct_tutdir'] = pjoin(env['prefix'], 'tutorials') env['ct_mandir'] = pjoin(env['prefix'], 'man1') env['ct_matlab_dir'] = pjoin(env['prefix'], 'matlab', 'toolbox') +# Always set the stage directory before building an MSI installer +if 'msi' in COMMAND_LINE_TARGETS: + env['stage_dir'] = 'stage' + env['prefix'] = '.' + # Directories where things will be staged for package creation. These # variables should always be used by the Install(...) targets if env['stage_dir']: - instRoot = pjoin(os.getcwd(), env['stage_dir'], env['prefix'].strip('/')) + instRoot = pjoin(os.getcwd(), env['stage_dir'], stripDrive(env['prefix']).strip('/\\')) env['python_prefix'] = instRoot else: instRoot = env['prefix'] diff --git a/platform/windows/cantera.wxs b/platform/windows/cantera.wxs new file mode 100644 index 000000000..b4a32e5e4 --- /dev/null +++ b/platform/windows/cantera.wxs @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/windows/wxsgen.py b/platform/windows/wxsgen.py new file mode 100644 index 000000000..0ffec79df --- /dev/null +++ b/platform/windows/wxsgen.py @@ -0,0 +1,69 @@ +try: + # Prefer LXML for its pretty printer, but xml.etree works fine. + import lxml.etree as et + have_lxml = True +except ImportError: + import xml.etree.ElementTree as et + have_lxml = False + +wix = et.Element("Wix", {'xmlns': 'http://schemas.microsoft.com/wix/2006/wi'}) + +def Directory(parent, Id, Name): + return et.SubElement(parent, 'Directory', + dict(Id=Id, Name=Name)) + +def FileComponent(parent, componentId, fileId, Guid, Name, Source, DiskId='1', KeyPath='yes'): + c = et.SubElement(parent, "Component", + dict(Id=componentId, Guid=Guid)) + f = et.SubElement(c, "File", + dict(Id=fileId, + Name=Name, + Source=Source, + DiskId=DiskId, + KeyPath=KeyPath)) + return c,f + +product = et.SubElement(wix, "Product", + dict(Name='Cantera 2.0', + Id='1B36CAF0-279D-11E1-8979-001FBC085391', + UpgradeCode='2340BEE1-279D-11E1-A4AA-001FBC085391', + Language='1033', + Codepage='1252', + Version='2.0.0', + Manufacturer='Cantera Developers')) + +package = et.SubElement(product, "Package", + dict(Id='*', + Keywords='Installer', + Description="Cantera 2.0 Installer", + InstallerVersion='100', + Languages='1033', + Compressed='yes', + SummaryCodepage='1252')) + +# Required boilerplate refering to nonexistent installation media +media = et.SubElement(product, "Media", + dict(Id='1', + Cabinet='cantera.cab', + EmbedCab='yes', + DiskPrompt='CD-ROM #1')) +diskprompt = et.SubElement(product, "Property", + dict(Id='DiskPrompt', + Value="Cantera Installation Disk")) + +targetdir = Directory(product, 'TARGETDIR', 'SourceDir') +pfiles = Directory(targetdir, 'ProgramFilesFolder', 'PFiles') +instdir = Directory(pfiles, 'INSTALLDIR', 'Cantera') +bindir = Directory(instdir, 'bin', 'bin') + +ck2cti = FileComponent(bindir, 'MainExecutable', 'ck2ctiEXE', + '0ABCA730-279D-11E1-984E-001FBC085391', + 'ck2cti.exe', '../../stage/bin/ck2cti.exe') + +complete = et.SubElement(product, 'Feature', dict(Id='Complete', Level='1')) +mainExec = et.SubElement(complete, 'ComponentRef', dict(Id='MainExecutable')) + +if have_lxml: + print et.tostring(wix, pretty_print=True) +else: + print et.tostring(wix) diff --git a/site_scons/buildutils.py b/site_scons/buildutils.py index b143ee0f5..37fcf2658 100644 --- a/site_scons/buildutils.py +++ b/site_scons/buildutils.py @@ -291,6 +291,16 @@ def psplit(s): return path +def stripDrive(s): + """ + Remove a Windows drive letter specification from a path. + """ + if len(s) > 1 and s[1] == ':': + return s[2:] + else: + return s + + def which(program): """ Replicates the functionality of the 'which' shell command """ def is_exe(fpath):