Attachment 'nsis-with-modifications-for-linux-and-includes.py'
Download 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 # NOTE (4 September 2007): The following import line was part of the original
28 # code on this wiki page before this date. It's not used anywhere below and
29 # therefore unnecessary. The SCons.Sig module is going away after 0.97.0d20070809,
30 # so the line should be removed from your copy of this module. There may be a
31 # do-nothing SCons.Sig module that generates a warning message checked in, so existing
32 # configurations won't break and can help point people to the line that needs removing.
33 #import SCons.Sig
34 import os.path
35 import glob
36 import platform
37
38 is_linux = (platform.system() == 'Linux')
39
40 def nsis_parse( sources, keyword, multiple, nsisdefines ):
41 """
42 A function that knows how to read a .nsi file and figure
43 out what files are referenced, or find the 'OutFile' line.
44
45
46 sources is a list of nsi files.
47 keyword is the command ('File' or 'OutFile') to look for
48 multiple is true if you want all the args as a list, false if you
49 just want the first one.
50 """
51 stuff = []
52 current_ignored = 0
53 for s in sources:
54 c = s.get_contents()
55 linenum = 0
56 for l in c.split('\n'):
57 linenum += 1
58 try:
59 semi = l.find(';')
60 if (semi != -1):
61 l = l[:semi]
62 hash = l.find('#')
63 if (hash != -1):
64 l = l[:hash]
65 # Look for the keyword
66 l = l.strip()
67 spl = l.split(None,1)
68 if len(spl) == 1 and current_ignored > 0 and spl[0].capitalize() == '!endif':
69 current_ignored -= 1
70 elif len(spl) > 1:
71 if current_ignored > 0 and spl[0].capitalize() in [ '!ifdef', '!ifmacrodef', '!ifndef' ]:
72 current_ignored += 1
73 elif current_ignored == 0 and spl[0].capitalize() == '!ifdef' and spl[1] not in nsisdefines:
74 current_ignored += 1
75 elif current_ignored == 0 and spl[0].capitalize() == '!ifndef' and spl[1] in nsisdefines:
76 current_ignored += 1
77 elif current_ignored == 0 and spl[0].capitalize() == keyword.capitalize():
78 arg = spl[1]
79 if keyword.capitalize() == 'File' and arg.lower().startswith('/oname') and len(spl) > 1:
80 arg = spl[2]
81 if arg.startswith('"') and arg.endswith('"'):
82 arg = arg[1:-1]
83 if multiple:
84 stuff += [ arg ]
85 else:
86 return arg
87 except:
88 print "in %(source)s, line %(linenum)d\n" % { 'source': s, 'linenum': linenum }
89 raise
90 return stuff
91
92
93 def nsis_path( filename, nsisdefines, rootdir ):
94 """
95 Do environment replacement, and prepend with the SCons root dir if
96 necessary
97 """
98 # We can't do variables defined by NSIS itself (like $INSTDIR),
99 # only user supplied ones (like ${FOO})
100 varPos = filename.find('${')
101 while varPos != -1:
102 endpos = filename.find('}',varPos)
103 assert endpos != -1
104 if not nsisdefines.has_key(filename[varPos+2:endpos]):
105 raise KeyError ("Could not find %s in NSISDEFINES" % filename[varPos+2:endpos])
106 val = nsisdefines[filename[varPos+2:endpos]]
107 if type(val) == list:
108 if varPos != 0 or endpos+1 != len(filename):
109 raise Exception("Can't use lists on variables that aren't complete filenames")
110 return val
111 filename = filename[0:varPos] + val + filename[endpos+1:]
112 varPos = filename.find('${')
113 return filename
114
115
116 def nsis_scanner( node, env, path, source_dir = None):
117 """
118 The scanner that looks through the source .nsi files and finds all lines
119 that are the 'File' command, fixes the directories etc, and returns them.
120 """
121 nodes = node.rfile()
122 if not node.exists():
123 return []
124 nodes = []
125 if source_dir is None:
126 try:
127 source_dir = env['NSISSRCDIR']
128 except:
129 source_dir = node.get_dir()
130 for include in nsis_parse([node],'file',1, env['NSISDEFINES']):
131 exp = nsis_path(include,env['NSISDEFINES'],source_dir)
132 if type(exp) != list:
133 exp = [exp]
134 for p in exp:
135 for filename in env.Glob( os.path.abspath(
136 os.path.join(str(source_dir),p))):
137 # Why absolute path? Cause it breaks mysteriously without it :(
138 nodes.append(filename)
139 for include in nsis_parse([node],'!include',1, env['NSISDEFINES']):
140 exp = nsis_path(include,env['NSISDEFINES'],source_dir)
141 if type(exp) != list:
142 exp = [exp]
143 for p in exp:
144 if p not in [ 'LogicLib.nsh', 'MUI2.nsh' ]:
145 # get ../bin/makensis and go up two directories
146 nsis_install_location = os.path.dirname(os.path.dirname(env['NSIS']))
147 filename = os.path.abspath(os.path.join(nsis_install_location, 'share', 'nsis', 'Include', p))
148 if not os.path.isfile(filename):
149 filename = os.path.abspath(os.path.join(str(source_dir),p))
150 # Why absolute path? Cause it breaks mysteriously without it :(
151 nodes.append(filename)
152 nodes += nsis_scanner(env.File(filename), env, path, source_dir = source_dir)
153 return nodes
154
155
156 def nsis_emitter( source, target, env ):
157 """
158 The emitter changes the target name to match what the command actually will
159 output, which is the argument to the OutFile command.
160 """
161 nsp = nsis_parse(source,'outfile',0, env['NSISDEFINES'])
162 if not nsp:
163 return (target,source)
164 x = (
165 nsis_path(nsp,env['NSISDEFINES'],''),
166 source)
167 return x
168
169 def quoteIfSpaced(text):
170 if ' ' in text:
171 return '"'+text+'"'
172 else:
173 return text
174
175 def toString(item,env):
176 if type(item) == list:
177 ret = ''
178 for i in item:
179 if ret:
180 ret += ' '
181 val = toString(i,env)
182 if ' ' in val:
183 val = "'"+val+"'"
184 ret += val
185 return ret
186 else:
187 # For convienence, handle #s here
188 if str(item).startswith('#'):
189 item = env.File(item).get_abspath()
190 return str(item)
191
192 def runNSIS(source,target,env,for_signature):
193 ret = env['NSIS']+" "
194 if env.has_key('NSISFLAGS'):
195 for flag in env['NSISFLAGS']:
196 ret += flag
197 ret += ' '
198 if env.has_key('NSISDEFINES'):
199 for d in env['NSISDEFINES']:
200 if is_linux:
201 ret += '-D'+d
202 else:
203 ret += '/D'+d
204 if env['NSISDEFINES'][d]:
205 ret +='='+quoteIfSpaced(toString(env['NSISDEFINES'][d],env))
206 ret += ' '
207 if is_linux:
208 ret += '-- '
209 for s in source:
210 ret += quoteIfSpaced(str(s))
211 return ret
212
213 def generate(env):
214 """
215 This function adds NSIS support to your environment.
216 """
217 env['BUILDERS']['Installer'] = SCons.Builder.Builder(generator=runNSIS,
218 src_suffix='.nsi',
219 emitter=nsis_emitter)
220 env.Append(SCANNERS = SCons.Scanner.Scanner( function = nsis_scanner,
221 skeys = ['.nsi','.nsh']))
222 if not env.has_key('NSISDEFINES'):
223 env['NSISDEFINES'] = {}
224 env['NSIS'] = find_nsis(env)
225
226 def find_nsis(env):
227 """
228 Try and figure out if NSIS is installed on this machine, and if so,
229 where.
230 """
231 if SCons.Util.can_read_reg:
232 # If we can read the registry, get the NSIS command from it
233 try:
234 k = SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
235 'SOFTWARE\\NSIS')
236 val, tok = SCons.Util.RegQueryValueEx(k,None)
237 ret = val + os.path.sep + 'makensis.exe'
238 if os.path.exists(ret):
239 return '"' + ret + '"'
240 else:
241 return None
242 except:
243 pass # Couldn't find the key, just act like we can't read the registry
244
245 # Hope it's on the path
246 return env.WhereIs('makensis' + env['PROGSUFFIX'])
247
248 def exists(env):
249 """
250 Is NSIS findable on this machine?
251 """
252 if find_nsis(env) != None:
253 return 1
254 return 0
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.- [get | view] (2013-03-30 18:18:25, 5.7 KB) [[attachment:nsis-changes-for-linux-and-includes.diff]]
- [get | view] (2013-03-30 18:18:25, 8.3 KB) [[attachment:nsis-with-modifications-for-linux-and-includes.py]]
You are not allowed to attach a file to this page.
