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

Contents of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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