/[ascend]/trunk/scons/nsis.py
ViewVC logotype

Diff of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1407 by johnpye, Sat Oct 28 03:55:19 2006 UTC revision 1408 by jpye, Mon Apr 23 02:32:34 2007 UTC
# Line 1  Line 1 
1  # NSIS Support for SCons  # NSIS Support for SCons
2  # Written by Mike Elkins, January 2004  # Written by Mike Elkins, January 2004
3  # Provided 'as-is', it works for me!  # Provided 'as-is', it works for me!
4    
5    
6  """  """
7  This tool provides SCons support for the Nullsoft Scriptable Install System  This tool provides SCons support for the Nullsoft Scriptable Install System
8  a windows installer builder available at http://nsis.sourceforge.net/home  a windows installer builder available at http://nsis.sourceforge.net/home
9    
10    
11  To use it you must copy this file into the scons/SCons/Tools directory or use  To use it you must copy this file into the scons/SCons/Tools directory or use
12  the tooldir arg in the Tool function and put a line like 'env.Tool("NSIS")'  the tooldir arg in the Tool function and put a line like 'env.Tool("NSIS")'
13  into your file. Then you can do 'env.Installer("foobar")' which will read foobar.nsi and  into your file. Then you can do 'env.Installer("foobar")' which will read foobar.nsi and
14  create dependencies on all the files you put into your installer, so that if  create dependencies on all the files you put into your installer, so that if
15  anything changes your installer will be rebuilt.  It also makes the target  anything changes your installer will be rebuilt.  It also makes the target
16  equal to the filename you specified in foobar.nsi.  Wildcards are handled correctly.  equal to the filename you specified in foobar.nsi.  Wildcards are handled correctly.
17    
18  In addition, if you set NSISDEFINES to a dictionary, those variables will be passed  In addition, if you set NSISDEFINES to a dictionary, those variables will be passed
19  to NSIS.  to NSIS.
20  """  """
21    
22    
23    
24  import SCons.Builder  import SCons.Builder
25  import SCons.Util  import SCons.Util
26  import SCons.Scanner  import SCons.Scanner
27  import SCons.Sig  import SCons.Sig
28  import os.path  import os.path
29  import glob  import glob
30    
31    
32  def nsis_parse( sources, keyword, multiple ):  def nsis_parse( sources, keyword, multiple ):
33    """    """
34    A function that knows how to read a .nsi file and figure    A function that knows how to read a .nsi file and figure
35    out what files are referenced, or find the 'OutFile' line.    out what files are referenced, or find the 'OutFile' line.
36    
37    
38    sources is a list of nsi files.    sources is a list of nsi files.
39    keyword is the command ('File' or 'OutFile') to look for    keyword is the command ('File' or 'OutFile') to look for
40    multiple is true if you want all the args as a list, false if you    multiple is true if you want all the args as a list, false if you
41    just want the first one.    just want the first one.
42    """    """
43    stuff = []    stuff = []
44    for s in sources:    for s in sources:
45      c = s.get_contents()      c = s.get_contents()
46      for l in c.split('\n'):      for l in c.split('\n'):
47        semi = l.find(';')        semi = l.find(';')
48        if (semi != -1):        if (semi != -1):
49          l = l[:semi]          l = l[:semi]
50        hash = l.find('#')        hash = l.find('#')
51        if (hash != -1):        if (hash != -1):
52          l = l[:hash]          l = l[:hash]
53        # Look for the keyword        # Look for the keyword
54        l = l.strip()        l = l.strip()
55        spl = l.split(None,1)        spl = l.split(None,1)
56        if len(spl) > 1:        if len(spl) > 1:
57          if spl[0].capitalize() == keyword.capitalize():          if spl[0].capitalize() == keyword.capitalize():
58            arg = spl[1]            arg = spl[1]
59            if arg.startswith('"') and arg.endswith('"'):            if arg.startswith('"') and arg.endswith('"'):
60              arg = arg[1:-1]              arg = arg[1:-1]
61            if multiple:            if multiple:
62              stuff += [ arg ]              stuff += [ arg ]
63            else:            else:
64              return arg              return arg
65    return stuff    return stuff
66    
67    
68  def nsis_path( filename, nsisdefines, rootdir ):  def nsis_path( filename, nsisdefines, rootdir ):
69    """    """
70    Do environment replacement, and prepend with the SCons root dir if    Do environment replacement, and prepend with the SCons root dir if
71    necessary    necessary
72    """    """
73    # We can't do variables defined by NSIS itself (like $INSTDIR),    # We can't do variables defined by NSIS itself (like $INSTDIR),
74    # only user supplied ones (like ${FOO})    # only user supplied ones (like ${FOO})
75    varPos = filename.find('${')    varPos = filename.find('${')
76    while varPos != -1:    while varPos != -1:
77      endpos = filename.find('}',varPos)      endpos = filename.find('}',varPos)
78      assert endpos != -1      assert endpos != -1
79      if not nsisdefines.has_key(filename[varPos+2:endpos]):      if not nsisdefines.has_key(filename[varPos+2:endpos]):
80        raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])        raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])
81      val = nsisdefines[filename[varPos+2:endpos]]      val = nsisdefines[filename[varPos+2:endpos]]
82      if type(val) == list:      if type(val) == list:
83        if varPos != 0 or endpos+1 != len(filename):        if varPos != 0 or endpos+1 != len(filename):
84          raise Exception("Can't use lists on variables that aren't complete filenames")          raise Exception("Can't use lists on variables that aren't complete filenames")
85        return val        return val
86      filename = filename[0:varPos] + val + filename[endpos+1:]      filename = filename[0:varPos] + val + filename[endpos+1:]
87      varPos = filename.find('${')      varPos = filename.find('${')
88    return filename    return filename
89    
90    
91  def nsis_scanner( node, env, path ):  def nsis_scanner( node, env, path ):
92    """    """
93    The scanner that looks through the source .nsi files and finds all lines    The scanner that looks through the source .nsi files and finds all lines
94    that are the 'File' command, fixes the directories etc, and returns them.    that are the 'File' command, fixes the directories etc, and returns them.
95    """    """
96    nodes = node.rfile()    nodes = node.rfile()
97    if not node.exists():    if not node.exists():
98      return []      return []
99    nodes = []    nodes = []
100    source_dir = node.get_dir()    source_dir = node.get_dir()
101    for include in nsis_parse([node],'file',1):    for include in nsis_parse([node],'file',1):
102      exp = nsis_path(include,env['NSISDEFINES'],source_dir)      exp = nsis_path(include,env['NSISDEFINES'],source_dir)
103      if type(exp) != list:      if type(exp) != list:
104        exp = [exp]        exp = [exp]
105      for p in exp:      for p in exp:
106        for filename in glob.glob( os.path.abspath(        for filename in glob.glob( os.path.abspath(
107          os.path.join(str(source_dir),p))):          os.path.join(str(source_dir),p))):
108            # Why absolute path?  Cause it breaks mysteriously without it :(            # Why absolute path?  Cause it breaks mysteriously without it :(
109            nodes.append(filename)            nodes.append(filename)
110    return nodes    return nodes
111    
112    
113  def nsis_emitter( source, target, env ):  def nsis_emitter( source, target, env ):
114    """    """
115    The emitter changes the target name to match what the command actually will    The emitter changes the target name to match what the command actually will
116    output, which is the argument to the OutFile command.    output, which is the argument to the OutFile command.
117    """    """
118    nsp = nsis_parse(source,'outfile',0)    nsp = nsis_parse(source,'outfile',0)
119    if not nsp:    if not nsp:
120      return (target,source)      return (target,source)
121    x  = (    x  = (
122      nsis_path(nsp,env['NSISDEFINES'],''),      nsis_path(nsp,env['NSISDEFINES'],''),
123      source)      source)
124    return x    return x
125    
126  def quoteIfSpaced(text):  def quoteIfSpaced(text):
127    if ' ' in text:    if ' ' in text:
128      return '"'+text+'"'      return '"'+text+'"'
129    else:    else:
130      return text      return text
131    
132  def toString(item,env):  def toString(item,env):
133    if type(item) == list:    if type(item) == list:
134      ret = ''      ret = ''
135      for i in item:      for i in item:
136        if ret:        if ret:
137          ret += ' '          ret += ' '
138        val = toString(i,env)        val = toString(i,env)
139        if ' ' in val:        if ' ' in val:
140          val = "'"+val+"'"          val = "'"+val+"'"
141        ret += val        ret += val
142      return ret      return ret
143    else:    else:
144      # For convienence, handle #s here      # For convienence, handle #s here
145      if str(item).startswith('#'):      if str(item).startswith('#'):
146        item = env.File(item).get_abspath()        item = env.File(item).get_abspath()
147      return str(item)      return str(item)
148    
149  def runNSIS(source,target,env,for_signature):  def runNSIS(source,target,env,for_signature):
150    ret = env['NSIS']+" "    ret = env['NSIS']+" "
151    if env.has_key('NSISFLAGS'):    if env.has_key('NSISFLAGS'):
152      for flag in env['NSISFLAGS']:      for flag in env['NSISFLAGS']:
153        ret += flag        ret += flag
154        ret += ' '        ret += ' '
155    if env.has_key('NSISDEFINES'):    if env.has_key('NSISDEFINES'):
156      for d in env['NSISDEFINES']:      for d in env['NSISDEFINES']:
157        ret += '/D'+d        ret += '/D'+d
158        if env['NSISDEFINES'][d]:        if env['NSISDEFINES'][d]:
159          ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))          ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))
160        ret += ' '        ret += ' '
161    for s in source:    for s in source:
162      ret += quoteIfSpaced(str(s))      ret += quoteIfSpaced(str(s))
163    return ret    return ret
164    
165  def generate(env):  def generate(env):
166    """    """
167    This function adds NSIS support to your environment.    This function adds NSIS support to your environment.
168    """    """
169    env['BUILDERS']['Installer'] = SCons.Builder.Builder(generator=runNSIS,    env['BUILDERS']['Installer'] = SCons.Builder.Builder(generator=runNSIS,
170                                   src_suffix='.nsi',                                   src_suffix='.nsi',
171                                   emitter=nsis_emitter)                                   emitter=nsis_emitter)
172    env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,    env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,
173               skeys = ['.nsi']))               skeys = ['.nsi']))
174    if not env.has_key('NSISDEFINES'):    if not env.has_key('NSISDEFINES'):
175      env['NSISDEFINES'] = {}      env['NSISDEFINES'] = {}
176    env['NSIS'] = find_nsis(env)    env['NSIS'] = find_nsis(env)
177    
178  def find_nsis(env):  def find_nsis(env):
179    """    """
180    Try and figure out if NSIS is installed on this machine, and if so,    Try and figure out if NSIS is installed on this machine, and if so,
181    where.    where.
182    """    """
183    if SCons.Util.can_read_reg:    if SCons.Util.can_read_reg:
184      # If we can read the registry, get the NSIS command from it      # If we can read the registry, get the NSIS command from it
185      try:      try:
186        k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,        k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
187                                    'SOFTWARE\\NSIS')                                    'SOFTWARE\\NSIS')
188        val, tok = SCons.Util.RegQueryValueEx(k,None)        val, tok = SCons.Util.RegQueryValueEx(k,None)
189        ret = val + os.path.sep + 'makensis.exe'        ret = val + os.path.sep + 'makensis.exe'
190        if os.path.exists(ret):        if os.path.exists(ret):
191          return '"' + ret + '"'          return '"' + ret + '"'
192        else:        else:
193          return None          return None
194      except:      except:
195        pass # Couldn't find the key, just act like we can't read the registry        pass # Couldn't find the key, just act like we can't read the registry
196    # Hope it's on the path    # Hope it's on the path
197    return env.WhereIs('makensis.exe')    return env.WhereIs('makensis.exe')
198    
199  def exists(env):  def exists(env):
200    """    """
201    Is NSIS findable on this machine?    Is NSIS findable on this machine?
202    """    """
203    if find_nsis(env) != None:    if find_nsis(env) != None:
204      return 1      return 1
205    return 0    return 0

Legend:
Removed from v.1407  
changed lines
  Added in v.1408

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22