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

Annotation of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 578 - (hide annotations) (download) (as text)
Tue May 9 04:59:03 2006 UTC (16 years, 3 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 johnpye 578 # 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