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

Contents of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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