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

Annotation of /trunk/scons/nsis.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2556 - (hide 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 jpye 1408 # 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 jpye 2556 import os.path, glob, platform
25 jpye 1408
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 jpye 2556 if platform.architecture()[0] == "64bit":
178     regpath = 'SOFTWARE\\Wow6432Node\\NSIS'
179     else:
180     regpath = 'SOFTWARE\\NSIS'
181 jpye 1408 if SCons.Util.can_read_reg:
182     # If we can read the registry, get the NSIS command from it
183     try:
184 jpye 2556 k = SCons.Util.RegOpenKeyEx(
185     SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,regpath
186     )
187 jpye 1408 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 johnpye 913 return 0

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