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

Contents of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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