]> git.cworth.org Git - apitrace/blob - scons/scons/mslink_sa.py
53331def1aaa123b8cf1960b5c1ccc16baf9c8c3
[apitrace] / scons / 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: