3 Tool-specific initialization for the Microsoft linker.
5 Based on SCons.Tool.mslink, without the MSVS detection.
10 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
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:
20 # The above copyright notice and this permission notice shall be included
21 # in all copies or substantial portions of the Software.
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.
37 import SCons
.Platform
.win32
39 import SCons
.Tool
.msvc
42 def pdbGenerator(env
, target
, source
, for_signature
):
44 return ['/PDB:%s' % target
[0].attributes
.pdb
, '/DEBUG']
45 except (AttributeError, IndexError):
48 def _dllTargets(target
, source
, env
, for_signature
, paramtp
):
50 dll
= env
.FindIxes(target
, '%sPREFIX' % paramtp
, '%sSUFFIX' % paramtp
)
51 if dll
: listCmd
.append("/out:%s"%dll
.get_string(for_signature
))
53 implib
= env
.FindIxes(target
, 'LIBPREFIX', 'LIBSUFFIX')
54 if implib
: listCmd
.append("/implib:%s"%implib
.get_string(for_signature
))
58 def _dllSources(target
, source
, env
, for_signature
, paramtp
):
61 deffile
= env
.FindIxes(source
, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")
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
))
70 # Just treat it as a generic source file.
74 def windowsShlinkTargets(target
, source
, env
, for_signature
):
75 return _dllTargets(target
, source
, env
, for_signature
, 'SHLIB')
77 def windowsShlinkSources(target
, source
, env
, for_signature
):
78 return _dllSources(target
, source
, env
, for_signature
, 'SHLIB')
80 def _windowsLdmodTargets(target
, source
, env
, for_signature
):
81 """Get targets for loadable modules."""
82 return _dllTargets(target
, source
, env
, for_signature
, 'LDMODULE')
84 def _windowsLdmodSources(target
, source
, env
, for_signature
):
85 """Get sources for loadable modules."""
86 return _dllSources(target
, source
, env
, for_signature
, 'LDMODULE')
88 def _dllEmitter(target
, source
, env
, paramtp
):
89 """Common implementation of dll emitter."""
90 SCons
.Tool
.msvc
.validate_vars(env
)
95 dll
= env
.FindIxes(target
, '%sPREFIX' % paramtp
, '%sSUFFIX' % paramtp
)
96 no_import_lib
= env
.get('no_import_lib', 0)
99 raise SCons
.Errors
.UserError
, 'A shared library should have exactly one target with the suffix: %s' % env
.subst('$%sSUFFIX' % paramtp
)
101 insert_def
= env
.subst("$WINDOWS_INSERT_DEF")
102 if not insert_def
in ['', '0', 0] and \
103 not env
.FindIxes(source
, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"):
105 # append a def file to the list of sources
108 '%sPREFIX' % paramtp
, '%sSUFFIX' % paramtp
,
109 "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"))
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
116 if not no_import_lib
and \
117 not env
.FindIxes(target
, "LIBPREFIX", "LIBSUFFIX"):
118 # Append an import library to the list of targets.
121 '%sPREFIX' % paramtp
, '%sSUFFIX' % paramtp
,
122 "LIBPREFIX", "LIBSUFFIX"))
123 # and .exp file is created if there are exports from a DLL
126 '%sPREFIX' % paramtp
, '%sSUFFIX' % paramtp
,
127 "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX"))
129 return (target
+extratargets
, source
+extrasources
)
131 def windowsLibEmitter(target
, source
, env
):
132 return _dllEmitter(target
, source
, env
, 'SHLIB')
134 def ldmodEmitter(target
, source
, env
):
135 """Emitter for loadable modules.
137 Loadable modules are identical to shared libraries on Windows, but building
138 them is subject to different parameters (LDMODULE*).
140 return _dllEmitter(target
, source
, env
, 'LDMODULE')
142 def prog_emitter(target
, source
, env
):
143 SCons
.Tool
.msvc
.validate_vars(env
)
147 exe
= env
.FindIxes(target
, "PROGPREFIX", "PROGSUFFIX")
149 raise SCons
.Errors
.UserError
, "An executable should have exactly one target with the suffix: %s" % env
.subst("$PROGSUFFIX")
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
156 return (target
+extratargets
,source
)
158 def RegServerFunc(target
, source
, env
):
159 if env
.has_key('register') and env
['register']:
160 ret
= regServerAction([target
[0]], [source
[0]], env
)
162 raise SCons
.Errors
.UserError
, "Unable to register %s" % target
[0]
164 print "Registered %s sucessfully" % target
[0]
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
176 """Add Builders and construction variables for ar to an Environment."""
177 SCons
.Tool
.createSharedLibBuilder(env
)
178 SCons
.Tool
.createProgBuilder(env
)
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
])
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'
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}'
203 env
['WIN32EXPPREFIX'] = ''
204 env
['WIN32EXPSUFFIX'] = '.exp'
205 env
['WINDOWSEXPPREFIX'] = '${WIN32EXPPREFIX}'
206 env
['WINDOWSEXPSUFFIX'] = '${WIN32EXPSUFFIX}'
208 env
['WINDOWSSHLIBMANIFESTPREFIX'] = ''
209 env
['WINDOWSSHLIBMANIFESTSUFFIX'] = '${SHLIBSUFFIX}.manifest'
210 env
['WINDOWSPROGMANIFESTPREFIX'] = ''
211 env
['WINDOWSPROGMANIFESTSUFFIX'] = '${PROGSUFFIX}.manifest'
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}'
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
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')
244 # indent-tabs-mode:nil
246 # vim: set expandtab tabstop=4 shiftwidth=4: