Merge commit 'origin/master' into gallium-0.2
[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 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 windowsShlinkTargets(target, source, env, for_signature):
49 listCmd = []
50 dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
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 windowsShlinkSources(target, source, env, for_signature):
59 listCmd = []
60
61 deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")
62 for src in source:
63 if src == deffile:
64 # Treat this source as a .def file.
65 listCmd.append("/def:%s" % src.get_string(for_signature))
66 else:
67 # Just treat it as a generic source file.
68 listCmd.append(src)
69 return listCmd
70
71 def windowsLibEmitter(target, source, env):
72 SCons.Tool.msvc.validate_vars(env)
73
74 extratargets = []
75 extrasources = []
76
77 dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX")
78 no_import_lib = env.get('no_import_lib', 0)
79
80 if not dll:
81 raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
82
83 insert_def = env.subst("$WINDOWS_INSERT_DEF")
84 if not insert_def in ['', '0', 0] and \
85 not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"):
86
87 # append a def file to the list of sources
88 extrasources.append(
89 env.ReplaceIxes(dll,
90 "SHLIBPREFIX", "SHLIBSUFFIX",
91 "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"))
92
93 if env.has_key('PDB') and env['PDB']:
94 pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
95 extratargets.append(pdb)
96 target[0].attributes.pdb = pdb
97
98 if not no_import_lib and \
99 not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
100 # Append an import library to the list of targets.
101 extratargets.append(
102 env.ReplaceIxes(dll,
103 "SHLIBPREFIX", "SHLIBSUFFIX",
104 "LIBPREFIX", "LIBSUFFIX"))
105 # and .exp file is created if there are exports from a DLL
106 extratargets.append(
107 env.ReplaceIxes(dll,
108 "SHLIBPREFIX", "SHLIBSUFFIX",
109 "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX"))
110
111 return (target+extratargets, source+extrasources)
112
113 def prog_emitter(target, source, env):
114 SCons.Tool.msvc.validate_vars(env)
115
116 extratargets = []
117
118 exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX")
119 if not exe:
120 raise SCons.Errors.UserError, "An executable should have exactly one target with the suffix: %s" % env.subst("$PROGSUFFIX")
121
122 if env.has_key('PDB') and env['PDB']:
123 pdb = env.arg2nodes('$PDB', target=target, source=source)[0]
124 extratargets.append(pdb)
125 target[0].attributes.pdb = pdb
126
127 return (target+extratargets,source)
128
129 def RegServerFunc(target, source, env):
130 if env.has_key('register') and env['register']:
131 ret = regServerAction([target[0]], [source[0]], env)
132 if ret:
133 raise SCons.Errors.UserError, "Unable to register %s" % target[0]
134 else:
135 print "Registered %s sucessfully" % target[0]
136 return ret
137 return 0
138
139 regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR")
140 regServerCheck = SCons.Action.Action(RegServerFunc, None)
141 shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}')
142 compositeLinkAction = shlibLinkAction + regServerCheck
143
144 def generate(env):
145 """Add Builders and construction variables for ar to an Environment."""
146 SCons.Tool.createSharedLibBuilder(env)
147 SCons.Tool.createProgBuilder(env)
148
149 env['SHLINK'] = '$LINK'
150 env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
151 env['_SHLINK_TARGETS'] = windowsShlinkTargets
152 env['_SHLINK_SOURCES'] = windowsShlinkSources
153 env['SHLINKCOM'] = compositeLinkAction
154 env.Append(SHLIBEMITTER = [windowsLibEmitter])
155 env['LINK'] = 'link'
156 env['LINKFLAGS'] = SCons.Util.CLVar('/nologo')
157 env['_PDB'] = pdbGenerator
158 env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $SOURCES.windows")}'
159 env.Append(PROGEMITTER = [prog_emitter])
160 env['LIBDIRPREFIX']='/LIBPATH:'
161 env['LIBDIRSUFFIX']=''
162 env['LIBLINKPREFIX']=''
163 env['LIBLINKSUFFIX']='$LIBSUFFIX'
164
165 env['WIN32DEFPREFIX'] = ''
166 env['WIN32DEFSUFFIX'] = '.def'
167 env['WIN32_INSERT_DEF'] = 0
168 env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}'
169 env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}'
170 env['WINDOWS_INSERT_DEF'] = '${WIN32_INSERT_DEF}'
171
172 env['WIN32EXPPREFIX'] = ''
173 env['WIN32EXPSUFFIX'] = '.exp'
174 env['WINDOWSEXPPREFIX'] = '${WIN32EXPPREFIX}'
175 env['WINDOWSEXPSUFFIX'] = '${WIN32EXPSUFFIX}'
176
177 env['WINDOWSSHLIBMANIFESTPREFIX'] = ''
178 env['WINDOWSSHLIBMANIFESTSUFFIX'] = '${SHLIBSUFFIX}.manifest'
179 env['WINDOWSPROGMANIFESTPREFIX'] = ''
180 env['WINDOWSPROGMANIFESTSUFFIX'] = '${PROGSUFFIX}.manifest'
181
182 env['REGSVRACTION'] = regServerCheck
183 env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32')
184 env['REGSVRFLAGS'] = '/s '
185 env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}'
186
187 # For most platforms, a loadable module is the same as a shared
188 # library. Platforms which are different can override these, but
189 # setting them the same means that LoadableModule works everywhere.
190 SCons.Tool.createLoadableModuleBuilder(env)
191 env['LDMODULE'] = '$SHLINK'
192 env['LDMODULEPREFIX'] = '$SHLIBPREFIX'
193 env['LDMODULESUFFIX'] = '$SHLIBSUFFIX'
194 env['LDMODULEFLAGS'] = '$SHLINKFLAGS'
195 # We can't use '$SHLINKCOM' here because that will stringify the
196 # action list on expansion, and will then try to execute expanded
197 # strings, with the upshot that it would try to execute RegServerFunc
198 # as a command.
199 env['LDMODULECOM'] = compositeLinkAction
200
201 def exists(env):
202 platform = env.get('PLATFORM', '')
203 if platform in ('win32', 'cygwin'):
204 # Only explicitly search for a 'link' executable on Windows
205 # systems. Some other systems (e.g. Ubuntu Linux) have an
206 # executable named 'link' and we don't want that to make SCons
207 # think Visual Studio is installed.
208 return env.Detect('link')
209 return None
210
211 # vim:set ts=4 sw=4 et: