Merge branch '7.8'
[mesa.git] / scons / mslink_sa.py
1 """mslink_sa
2
3 Tool-specific initialization for the Microsoft linker.
4
5 Based on SCons.Tool.mslink, without the MSVS detection.
6
7 """
8
9 #
10 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
11 #
12 # Permission is hereby granted, free of charge, to any person obtaining
13 # a copy of this software and associated documentation files (the
14 # "Software"), to deal in the Software without restriction, including
15 # without limitation the rights to use, copy, modify, merge, publish,
16 # distribute, sublicense, and/or sell copies of the Software, and to
17 # permit persons to whom the Software is furnished to do so, subject to
18 # the following conditions:
19 #
20 # The above copyright notice and this permission notice shall be included
21 # in all copies or substantial portions of the Software.
22 #
23 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
24 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
25 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #
31
32 import os.path
33
34 import SCons.Action
35 import SCons.Defaults
36 import SCons.Errors
37 import SCons.Platform.win32
38 import SCons.Tool
39 import SCons.Tool.msvc
40 import SCons.Util
41
42 def pdbGenerator(env, target, source, for_signature):
43 try:
44 return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG']
45 except (AttributeError, IndexError):
46 return None
47
48 def _dllTargets(target, source, env, for_signature, paramtp):
49 listCmd = []
50 dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp)
51 if dll: listCmd.append("/out:%s"%dll.get_string(for_signature))
52
53 implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
54 if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature))
55
56 return listCmd
57
58 def _dllSources(target, source, env, for_signature, paramtp):
59 listCmd = []
60
61 deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")
62 for src in source:
63 # Check explicitly for a non-None deffile so that the __cmp__
64 # method of the base SCons.Util.Proxy class used for some Node
65 # proxies doesn't try to use a non-existent __dict__ attribute.
66 if deffile and src == deffile:
67 # Treat this source as a .def file.
68 listCmd.append("/def:%s" % src.get_string(for_signature))
69 else:
70 # Just treat it as a generic source file.
71 listCmd.append(src)
72 return listCmd
73
74 def windowsShlinkTargets(target, source, env, for_signature):
75 return _dllTargets(target, source, env, for_signature, 'SHLIB')
76
77 def windowsShlinkSources(target, source, env, for_signature):
78 return _dllSources(target, source, env, for_signature, 'SHLIB')
79
80 def _windowsLdmodTargets(target, source, env, for_signature):
81 """Get targets for loadable modules."""
82 return _dllTargets(target, source, env, for_signature, 'LDMODULE')
83
84 def _windowsLdmodSources(target, source, env, for_signature):
85 """Get sources for loadable modules."""
86 return _dllSources(target, source, env, for_signature, 'LDMODULE')
87
88 def _dllEmitter(target, source, env, paramtp):
89 """Common implementation of dll emitter."""
90 SCons.Tool.msvc.validate_vars(env)
91
92 extratargets = []
93 extrasources = []
94
95 dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp)
96 no_import_lib = env.get('no_import_lib', 0)
97
98 if not dll:
99 raise SCons.Errors.UserError, 'A shared library should have exactly one target with the suffix: %s' % env.subst('$%sSUFFIX' % paramtp)
100
101 insert_def = env.subst("$WINDOWS_INSERT_DEF")
102 if not insert_def in ['', '0', 0] and \
103 not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"):
104
105 # append a def file to the list of sources
106 extrasources.append(
107 env.ReplaceIxes(dll,
108 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
109 "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"))
110
111 if env.has_key('PDB') and env['PDB']:
112 pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
113 extratargets.append(pdb)
114 target[0].attributes.pdb = pdb
115
116 if not no_import_lib and \
117 not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
118 # Append an import library to the list of targets.
119 extratargets.append(
120 env.ReplaceIxes(dll,
121 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
122 "LIBPREFIX", "LIBSUFFIX"))
123 # and .exp file is created if there are exports from a DLL
124 extratargets.append(
125 env.ReplaceIxes(dll,
126 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp,
127 "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX"))
128
129 return (target+extratargets, source+extrasources)
130
131 def windowsLibEmitter(target, source, env):
132 return _dllEmitter(target, source, env, 'SHLIB')
133
134 def ldmodEmitter(target, source, env):
135 """Emitter for loadable modules.
136
137 Loadable modules are identical to shared libraries on Windows, but building
138 them is subject to different parameters (LDMODULE*).
139 """
140 return _dllEmitter(target, source, env, 'LDMODULE')
141
142 def prog_emitter(target, source, env):
143 SCons.Tool.msvc.validate_vars(env)
144
145 extratargets = []
146
147 exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX")
148 if not exe:
149 raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX")
150
151 if env.has_key('PDB') and env['PDB']:
152 pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
153 extratargets.append(pdb)
154 target[0].attributes.pdb = pdb
155
156 return (target+extratargets,source)
157
158 def RegServerFunc(target, source, env):
159 if env.has_key('register') and env['register']:
160 ret = regServerAction([target[0]], [source[0]], env)
161 if ret:
162 raise SCons.Errors.UserError, "Unable to register %s" % target[0]
163 else:
164 print "Registered %s sucessfully" % target[0]
165 return ret
166 return 0
167
168 regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR")
169 regServerCheck = SCons.Action.Action(RegServerFunc, None)
170 shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK_TARGETS $_LIBDIRFLAGS $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}')
171 compositeShLinkAction = shlibLinkAction + regServerCheck
172 ldmodLinkAction = SCons.Action.Action('${TEMPFILE("$LDMODULE $LDMODULEFLAGS $_LDMODULE_TARGETS $_LIBDIRFLAGS $_LIBFLAGS $_PDB $_LDMODULE_SOURCES")}')
173 compositeLdmodAction = ldmodLinkAction + regServerCheck
174
175 def generate(env):
176 """Add Builders and construction variables for ar to an Environment."""
177 SCons.Tool.createSharedLibBuilder(env)
178 SCons.Tool.createProgBuilder(env)
179
180 env['SHLINK'] = '$LINK'
181 env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
182 env['_SHLINK_TARGETS'] = windowsShlinkTargets
183 env['_SHLINK_SOURCES'] = windowsShlinkSources
184 env['SHLINKCOM'] = compositeShLinkAction
185 env.Append(SHLIBEMITTER = [windowsLibEmitter])
186 env['LINK'] = 'link'
187 env['LINKFLAGS'] = SCons.Util.CLVar('/nologo')
188 env['_PDB'] = pdbGenerator
189 env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $_LIBDIRFLAGS $_LIBFLAGS $_PDB $SOURCES.windows")}'
190 env.Append(PROGEMITTER = [prog_emitter])
191 env['LIBDIRPREFIX']='/LIBPATH:'
192 env['LIBDIRSUFFIX']=''
193 env['LIBLINKPREFIX']=''
194 env['LIBLINKSUFFIX']='$LIBSUFFIX'
195
196 env['WIN32DEFPREFIX'] = ''
197 env['WIN32DEFSUFFIX'] = '.def'
198 env['WIN32_INSERT_DEF'] = 0
199 env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}'
200 env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}'
201 env['WINDOWS_INSERT_DEF'] = '${WIN32_INSERT_DEF}'
202
203 env['WIN32EXPPREFIX'] = ''
204 env['WIN32EXPSUFFIX'] = '.exp'
205 env['WINDOWSEXPPREFIX'] = '${WIN32EXPPREFIX}'
206 env['WINDOWSEXPSUFFIX'] = '${WIN32EXPSUFFIX}'
207
208 env['WINDOWSSHLIBMANIFESTPREFIX'] = ''
209 env['WINDOWSSHLIBMANIFESTSUFFIX'] = '${SHLIBSUFFIX}.manifest'
210 env['WINDOWSPROGMANIFESTPREFIX'] = ''
211 env['WINDOWSPROGMANIFESTSUFFIX'] = '${PROGSUFFIX}.manifest'
212
213 env['REGSVRACTION'] = regServerCheck
214 env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32')
215 env['REGSVRFLAGS'] = '/s '
216 env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}'
217
218 # Loadable modules are on Windows the same as shared libraries, but they
219 # are subject to different build parameters (LDMODULE* variables).
220 # Therefore LDMODULE* variables correspond as much as possible to
221 # SHLINK*/SHLIB* ones.
222 SCons.Tool.createLoadableModuleBuilder(env)
223 env['LDMODULE'] = '$SHLINK'
224 env['LDMODULEPREFIX'] = '$SHLIBPREFIX'
225 env['LDMODULESUFFIX'] = '$SHLIBSUFFIX'
226 env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
227 env['_LDMODULE_TARGETS'] = _windowsLdmodTargets
228 env['_LDMODULE_SOURCES'] = _windowsLdmodSources
229 env['LDMODULEEMITTER'] = [ldmodEmitter]
230 env['LDMODULECOM'] = compositeLdmodAction
231
232 def exists(env):
233 platform = env.get('PLATFORM', '')
234 if platform in ('win32', 'cygwin'):
235 # Only explicitly search for a 'link' executable on Windows
236 # systems. Some other systems (e.g. Ubuntu Linux) have an
237 # executable named 'link' and we don't want that to make SCons
238 # think Visual Studio is installed.
239 return env.Detect('link')
240 return None
241
242 # Local Variables:
243 # tab-width:4
244 # indent-tabs-mode:nil
245 # End:
246 # vim: set expandtab tabstop=4 shiftwidth=4: