OLD | NEW |
1 """SCons.Tool.mslink | 1 """SCons.Tool.mslink |
2 | 2 |
3 Tool-specific initialization for the Microsoft linker. | 3 Tool-specific initialization for the Microsoft linker. |
4 | 4 |
5 There normally shouldn't be any need to import this module directly. | 5 There normally shouldn't be any need to import this module directly. |
6 It will usually be imported through the generic SCons.Tool.Tool() | 6 It will usually be imported through the generic SCons.Tool.Tool() |
7 selection method. | 7 selection method. |
8 | 8 |
9 """ | 9 """ |
10 | 10 |
11 # | 11 # |
12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat
ion | 12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F
oundation |
13 # | 13 # |
14 # Permission is hereby granted, free of charge, to any person obtaining | 14 # Permission is hereby granted, free of charge, to any person obtaining |
15 # a copy of this software and associated documentation files (the | 15 # a copy of this software and associated documentation files (the |
16 # "Software"), to deal in the Software without restriction, including | 16 # "Software"), to deal in the Software without restriction, including |
17 # without limitation the rights to use, copy, modify, merge, publish, | 17 # without limitation the rights to use, copy, modify, merge, publish, |
18 # distribute, sublicense, and/or sell copies of the Software, and to | 18 # distribute, sublicense, and/or sell copies of the Software, and to |
19 # permit persons to whom the Software is furnished to do so, subject to | 19 # permit persons to whom the Software is furnished to do so, subject to |
20 # the following conditions: | 20 # the following conditions: |
21 # | 21 # |
22 # The above copyright notice and this permission notice shall be included | 22 # The above copyright notice and this permission notice shall be included |
23 # in all copies or substantial portions of the Software. | 23 # in all copies or substantial portions of the Software. |
24 # | 24 # |
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | 25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | 26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
32 # | 32 # |
33 | 33 |
34 __revision__ = "src/engine/SCons/Tool/mslink.py 3842 2008/12/20 22:59:52 scons" | 34 __revision__ = "src/engine/SCons/Tool/mslink.py 3897 2009/01/13 06:45:54 scons" |
35 | 35 |
36 import os.path | 36 import os.path |
37 | 37 |
38 import SCons.Action | 38 import SCons.Action |
39 import SCons.Defaults | 39 import SCons.Defaults |
40 import SCons.Errors | 40 import SCons.Errors |
41 import SCons.Platform.win32 | 41 import SCons.Platform.win32 |
42 import SCons.Tool | 42 import SCons.Tool |
43 import SCons.Tool.msvc | 43 import SCons.Tool.msvc |
44 import SCons.Tool.msvs | 44 import SCons.Tool.msvs |
45 import SCons.Util | 45 import SCons.Util |
46 | 46 |
47 def pdbGenerator(env, target, source, for_signature): | 47 def pdbGenerator(env, target, source, for_signature): |
48 try: | 48 try: |
49 return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG'] | 49 return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG'] |
50 except (AttributeError, IndexError): | 50 except (AttributeError, IndexError): |
51 return None | 51 return None |
52 | 52 |
53 def windowsShlinkTargets(target, source, env, for_signature): | 53 def _dllTargets(target, source, env, for_signature, paramtp): |
54 listCmd = [] | 54 listCmd = [] |
55 dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') | 55 dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp) |
56 if dll: listCmd.append("/out:%s"%dll.get_string(for_signature)) | 56 if dll: listCmd.append("/out:%s"%dll.get_string(for_signature)) |
57 | 57 |
58 implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX') | 58 implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX') |
59 if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature)) | 59 if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature)) |
60 | 60 |
61 return listCmd | 61 return listCmd |
62 | 62 |
63 def windowsShlinkSources(target, source, env, for_signature): | 63 def _dllSources(target, source, env, for_signature, paramtp): |
64 listCmd = [] | 64 listCmd = [] |
65 | 65 |
66 deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX") | 66 deffile = env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX") |
67 for src in source: | 67 for src in source: |
68 if src == deffile: | 68 # Check explicitly for a non-None deffile so that the __cmp__ |
| 69 # method of the base SCons.Util.Proxy class used for some Node |
| 70 # proxies doesn't try to use a non-existent __dict__ attribute. |
| 71 if deffile and src == deffile: |
69 # Treat this source as a .def file. | 72 # Treat this source as a .def file. |
70 listCmd.append("/def:%s" % src.get_string(for_signature)) | 73 listCmd.append("/def:%s" % src.get_string(for_signature)) |
71 else: | 74 else: |
72 # Just treat it as a generic source file. | 75 # Just treat it as a generic source file. |
73 listCmd.append(src) | 76 listCmd.append(src) |
74 return listCmd | 77 return listCmd |
75 | 78 |
76 def windowsLibEmitter(target, source, env): | 79 def windowsShlinkTargets(target, source, env, for_signature): |
| 80 return _dllTargets(target, source, env, for_signature, 'SHLIB') |
| 81 |
| 82 def windowsShlinkSources(target, source, env, for_signature): |
| 83 return _dllSources(target, source, env, for_signature, 'SHLIB') |
| 84 |
| 85 def _windowsLdmodTargets(target, source, env, for_signature): |
| 86 """Get targets for loadable modules.""" |
| 87 return _dllTargets(target, source, env, for_signature, 'LDMODULE') |
| 88 |
| 89 def _windowsLdmodSources(target, source, env, for_signature): |
| 90 """Get sources for loadable modules.""" |
| 91 return _dllSources(target, source, env, for_signature, 'LDMODULE') |
| 92 |
| 93 def _dllEmitter(target, source, env, paramtp): |
| 94 """Common implementation of dll emitter.""" |
77 SCons.Tool.msvc.validate_vars(env) | 95 SCons.Tool.msvc.validate_vars(env) |
78 | 96 |
79 extratargets = [] | 97 extratargets = [] |
80 extrasources = [] | 98 extrasources = [] |
81 | 99 |
82 dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX") | 100 dll = env.FindIxes(target, '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp) |
83 no_import_lib = env.get('no_import_lib', 0) | 101 no_import_lib = env.get('no_import_lib', 0) |
84 | 102 |
85 if not dll: | 103 if not dll: |
86 raise SCons.Errors.UserError, "A shared library should have exactly one
target with the suffix: %s" % env.subst("$SHLIBSUFFIX") | 104 raise SCons.Errors.UserError, 'A shared library should have exactly one
target with the suffix: %s' % env.subst('$%sSUFFIX' % paramtp) |
87 | 105 |
88 insert_def = env.subst("$WINDOWS_INSERT_DEF") | 106 insert_def = env.subst("$WINDOWS_INSERT_DEF") |
89 if not insert_def in ['', '0', 0] and \ | 107 if not insert_def in ['', '0', 0] and \ |
90 not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"): | 108 not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"): |
91 | 109 |
92 # append a def file to the list of sources | 110 # append a def file to the list of sources |
93 extrasources.append( | 111 extrasources.append( |
94 env.ReplaceIxes(dll, | 112 env.ReplaceIxes(dll, |
95 "SHLIBPREFIX", "SHLIBSUFFIX", | 113 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp, |
96 "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")) | 114 "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX")) |
97 | 115 |
98 version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSIO
N', '6.0')) | 116 version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSIO
N', '6.0')) |
99 if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0): | 117 if version_num >= 8.0 and env.get('WINDOWS_INSERT_MANIFEST', 0): |
100 # MSVC 8 automatically generates .manifest files that must be installed | 118 # MSVC 8 automatically generates .manifest files that must be installed |
101 extratargets.append( | 119 extratargets.append( |
102 env.ReplaceIxes(dll, | 120 env.ReplaceIxes(dll, |
103 "SHLIBPREFIX", "SHLIBSUFFIX", | 121 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp, |
104 "WINDOWSSHLIBMANIFESTPREFIX", "WINDOWSSHLIBMANIFESTS
UFFIX")) | 122 "WINDOWSSHLIBMANIFESTPREFIX", "WINDOWSSHLIBMANIFESTS
UFFIX")) |
105 | 123 |
106 if env.has_key('PDB') and env['PDB']: | 124 if env.has_key('PDB') and env['PDB']: |
107 pdb = env.arg2nodes('$PDB', target=target, source=source)[0] | 125 pdb = env.arg2nodes('$PDB', target=target, source=source)[0] |
108 extratargets.append(pdb) | 126 extratargets.append(pdb) |
109 target[0].attributes.pdb = pdb | 127 target[0].attributes.pdb = pdb |
110 | 128 |
111 if not no_import_lib and \ | 129 if not no_import_lib and \ |
112 not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"): | 130 not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"): |
113 # Append an import library to the list of targets. | 131 # Append an import library to the list of targets. |
114 extratargets.append( | 132 extratargets.append( |
115 env.ReplaceIxes(dll, | 133 env.ReplaceIxes(dll, |
116 "SHLIBPREFIX", "SHLIBSUFFIX", | 134 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp, |
117 "LIBPREFIX", "LIBSUFFIX")) | 135 "LIBPREFIX", "LIBSUFFIX")) |
118 # and .exp file is created if there are exports from a DLL | 136 # and .exp file is created if there are exports from a DLL |
119 extratargets.append( | 137 extratargets.append( |
120 env.ReplaceIxes(dll, | 138 env.ReplaceIxes(dll, |
121 "SHLIBPREFIX", "SHLIBSUFFIX", | 139 '%sPREFIX' % paramtp, '%sSUFFIX' % paramtp, |
122 "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX")) | 140 "WINDOWSEXPPREFIX", "WINDOWSEXPSUFFIX")) |
123 | 141 |
124 return (target+extratargets, source+extrasources) | 142 return (target+extratargets, source+extrasources) |
125 | 143 |
| 144 def windowsLibEmitter(target, source, env): |
| 145 return _dllEmitter(target, source, env, 'SHLIB') |
| 146 |
| 147 def ldmodEmitter(target, source, env): |
| 148 """Emitter for loadable modules. |
| 149 |
| 150 Loadable modules are identical to shared libraries on Windows, but building |
| 151 them is subject to different parameters (LDMODULE*). |
| 152 """ |
| 153 return _dllEmitter(target, source, env, 'LDMODULE') |
| 154 |
126 def prog_emitter(target, source, env): | 155 def prog_emitter(target, source, env): |
127 SCons.Tool.msvc.validate_vars(env) | 156 SCons.Tool.msvc.validate_vars(env) |
128 | 157 |
129 extratargets = [] | 158 extratargets = [] |
130 | 159 |
131 exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX") | 160 exe = env.FindIxes(target, "PROGPREFIX", "PROGSUFFIX") |
132 if not exe: | 161 if not exe: |
133 raise SCons.Errors.UserError, "An executable should have exactly one tar
get with the suffix: %s" % env.subst("$PROGSUFFIX") | 162 raise SCons.Errors.UserError, "An executable should have exactly one tar
get with the suffix: %s" % env.subst("$PROGSUFFIX") |
134 | 163 |
135 version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSIO
N', '6.0')) | 164 version_num, suite = SCons.Tool.msvs.msvs_parse_version(env.get('MSVS_VERSIO
N', '6.0')) |
(...skipping 17 matching lines...) Expand all Loading... |
153 if ret: | 182 if ret: |
154 raise SCons.Errors.UserError, "Unable to register %s" % target[0] | 183 raise SCons.Errors.UserError, "Unable to register %s" % target[0] |
155 else: | 184 else: |
156 print "Registered %s sucessfully" % target[0] | 185 print "Registered %s sucessfully" % target[0] |
157 return ret | 186 return ret |
158 return 0 | 187 return 0 |
159 | 188 |
160 regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR") | 189 regServerAction = SCons.Action.Action("$REGSVRCOM", "$REGSVRCOMSTR") |
161 regServerCheck = SCons.Action.Action(RegServerFunc, None) | 190 regServerCheck = SCons.Action.Action(RegServerFunc, None) |
162 shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK
_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}') | 191 shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK
_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}') |
163 compositeLinkAction = shlibLinkAction + regServerCheck | 192 compositeShLinkAction = shlibLinkAction + regServerCheck |
| 193 ldmodLinkAction = SCons.Action.Action('${TEMPFILE("$LDMODULE $LDMODULEFLAGS $_LD
MODULE_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_LDMODULE_SOURCES")}') |
| 194 compositeLdmodAction = ldmodLinkAction + regServerCheck |
164 | 195 |
165 def generate(env): | 196 def generate(env): |
166 """Add Builders and construction variables for ar to an Environment.""" | 197 """Add Builders and construction variables for ar to an Environment.""" |
167 SCons.Tool.createSharedLibBuilder(env) | 198 SCons.Tool.createSharedLibBuilder(env) |
168 SCons.Tool.createProgBuilder(env) | 199 SCons.Tool.createProgBuilder(env) |
169 | 200 |
170 env['SHLINK'] = '$LINK' | 201 env['SHLINK'] = '$LINK' |
171 env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll') | 202 env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll') |
172 env['_SHLINK_TARGETS'] = windowsShlinkTargets | 203 env['_SHLINK_TARGETS'] = windowsShlinkTargets |
173 env['_SHLINK_SOURCES'] = windowsShlinkSources | 204 env['_SHLINK_SOURCES'] = windowsShlinkSources |
174 env['SHLINKCOM'] = compositeLinkAction | 205 env['SHLINKCOM'] = compositeShLinkAction |
175 env.Append(SHLIBEMITTER = [windowsLibEmitter]) | 206 env.Append(SHLIBEMITTER = [windowsLibEmitter]) |
176 env['LINK'] = 'link' | 207 env['LINK'] = 'link' |
177 env['LINKFLAGS'] = SCons.Util.CLVar('/nologo') | 208 env['LINKFLAGS'] = SCons.Util.CLVar('/nologo') |
178 env['_PDB'] = pdbGenerator | 209 env['_PDB'] = pdbGenerator |
179 env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $( $_LIB
DIRFLAGS $) $_LIBFLAGS $_PDB $SOURCES.windows")}' | 210 env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $( $_LIB
DIRFLAGS $) $_LIBFLAGS $_PDB $SOURCES.windows")}' |
180 env.Append(PROGEMITTER = [prog_emitter]) | 211 env.Append(PROGEMITTER = [prog_emitter]) |
181 env['LIBDIRPREFIX']='/LIBPATH:' | 212 env['LIBDIRPREFIX']='/LIBPATH:' |
182 env['LIBDIRSUFFIX']='' | 213 env['LIBDIRSUFFIX']='' |
183 env['LIBLINKPREFIX']='' | 214 env['LIBLINKPREFIX']='' |
184 env['LIBLINKSUFFIX']='$LIBSUFFIX' | 215 env['LIBLINKSUFFIX']='$LIBSUFFIX' |
(...skipping 29 matching lines...) Expand all Loading... |
214 include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(en
v,version) | 245 include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(en
v,version) |
215 | 246 |
216 # since other tools can set these, we just make sure that the | 247 # since other tools can set these, we just make sure that the |
217 # relevant stuff from MSVS is in there somewhere. | 248 # relevant stuff from MSVS is in there somewhere. |
218 env.PrependENVPath('INCLUDE', include_path) | 249 env.PrependENVPath('INCLUDE', include_path) |
219 env.PrependENVPath('LIB', lib_path) | 250 env.PrependENVPath('LIB', lib_path) |
220 env.PrependENVPath('PATH', exe_path) | 251 env.PrependENVPath('PATH', exe_path) |
221 except (SCons.Util.RegError, SCons.Errors.InternalError): | 252 except (SCons.Util.RegError, SCons.Errors.InternalError): |
222 pass | 253 pass |
223 | 254 |
224 # For most platforms, a loadable module is the same as a shared | 255 # Loadable modules are on Windows the same as shared libraries, but they |
225 # library. Platforms which are different can override these, but | 256 # are subject to different build parameters (LDMODULE* variables). |
226 # setting them the same means that LoadableModule works everywhere. | 257 # Therefore LDMODULE* variables correspond as much as possible to |
| 258 # SHLINK*/SHLIB* ones. |
227 SCons.Tool.createLoadableModuleBuilder(env) | 259 SCons.Tool.createLoadableModuleBuilder(env) |
228 env['LDMODULE'] = '$SHLINK' | 260 env['LDMODULE'] = '$SHLINK' |
229 env['LDMODULEPREFIX'] = '$SHLIBPREFIX' | 261 env['LDMODULEPREFIX'] = '$SHLIBPREFIX' |
230 env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' | 262 env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' |
231 env['LDMODULEFLAGS'] = '$SHLINKFLAGS' | 263 env['LDMODULEFLAGS'] = '$SHLINKFLAGS' |
232 # We can't use '$SHLINKCOM' here because that will stringify the | 264 env['_LDMODULE_TARGETS'] = _windowsLdmodTargets |
233 # action list on expansion, and will then try to execute expanded | 265 env['_LDMODULE_SOURCES'] = _windowsLdmodSources |
234 # strings, with the upshot that it would try to execute RegServerFunc | 266 env['LDMODULEEMITTER'] = [ldmodEmitter] |
235 # as a command. | 267 env['LDMODULECOM'] = compositeLdmodAction |
236 env['LDMODULECOM'] = compositeLinkAction | |
237 | 268 |
238 def exists(env): | 269 def exists(env): |
239 platform = env.get('PLATFORM', '') | 270 platform = env.get('PLATFORM', '') |
240 if SCons.Tool.msvs.is_msvs_installed(): | 271 if SCons.Tool.msvs.is_msvs_installed(): |
241 # there's at least one version of MSVS installed. | 272 # there's at least one version of MSVS installed. |
242 return 1 | 273 return 1 |
243 elif platform in ('win32', 'cygwin'): | 274 elif platform in ('win32', 'cygwin'): |
244 # Only explicitly search for a 'link' executable on Windows | 275 # Only explicitly search for a 'link' executable on Windows |
245 # systems. Some other systems (e.g. Ubuntu Linux) have an | 276 # systems. Some other systems (e.g. Ubuntu Linux) have an |
246 # executable named 'link' and we don't want that to make SCons | 277 # executable named 'link' and we don't want that to make SCons |
247 # think Visual Studio is installed. | 278 # think Visual Studio is installed. |
248 return env.Detect('link') | 279 return env.Detect('link') |
249 return None | 280 return None |
OLD | NEW |