Fix win32LinkGenerator.
[scons.git] / src / engine / SCons / Defaults.py
1 """SCons.Defaults
2
3 Builders and other things for the local site.  Here's where we'll
4 duplicate the functionality of autoconf until we move it into the
5 installation procedure or use something like qmconf.
6
7 The code that reads the registry to find MSVC components was borrowed
8 from distutils.msvccompiler.
9
10 """
11
12 #
13 # Copyright (c) 2001, 2002 Steven Knight
14 #
15 # Permission is hereby granted, free of charge, to any person obtaining
16 # a copy of this software and associated documentation files (the
17 # "Software"), to deal in the Software without restriction, including
18 # without limitation the rights to use, copy, modify, merge, publish,
19 # distribute, sublicense, and/or sell copies of the Software, and to
20 # permit persons to whom the Software is furnished to do so, subject to
21 # the following conditions:
22 #
23 # The above copyright notice and this permission notice shall be included
24 # in all copies or substantial portions of the Software.
25 #
26 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
27 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
28 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #
34
35 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
36
37
38
39 import os
40 import stat
41 import string
42 import sys
43 import os.path
44
45 import SCons.Action
46 import SCons.Builder
47 import SCons.Errors
48 import SCons.Node.Alias
49 import SCons.Node.FS
50 import SCons.Scanner.C
51 import SCons.Scanner.Prog
52 import SCons.Util
53
54 class SharedCmdGenerator:
55     """A callable class that acts as a command generator.
56     It is designed to hold on to 2 actions, and return
57     one if the shared=1 keyword arg is supplied to the
58     Builder method, and the other if not.
59
60     Also, all target nodes will have the shared attribute
61     set to match the vaue of the shared keyword argument,
62     zero by default."""
63     def __init__(self, static, shared):
64         self.action_static = static
65         self.action_shared = shared
66         
67     def __call__(self, target, source, env, shared=0):
68         for src in source:
69             try:
70                 if src.attributes.shared != shared:
71                     raise UserError("Source file: %s must be built with shared=%s in order to be compatible with the selected target." % (src, str(shared)))
72             except AttributeError:
73                 pass
74         for t in target:
75             t.attributes.shared = shared
76         if shared:
77             return self.action_shared
78         else:
79             return self.action_static
80                          
81 CFile = SCons.Builder.Builder(name = 'CFile',
82                               action = { '.l'    : '$LEXCOM',
83                                          '.y'    : '$YACCCOM',
84                                        },
85                               suffix = '$CFILESUFFIX')
86
87 CXXFile = SCons.Builder.Builder(name = 'CXXFile',
88                                 action = { '.ll' : '$LEXCOM',
89                                            '.yy' : '$YACCCOM',
90                                          },
91                                 suffix = '$CXXFILESUFFIX')
92
93 CXXAction = SCons.Action.Action("$CXXCOM")
94 ShCXXAction = SCons.Action.Action("$SHCXXCOM")
95 F77Action = SCons.Action.Action("$F77COM")
96 ShF77Action = SCons.Action.Action("$SHF77COM")
97 F77PPAction = SCons.Action.Action("$F77PPCOM")
98 ShF77PPAction = SCons.Action.Action("$SHF77PPCOM")
99
100 shared_obj = SCons.Builder.DictCmdGenerator({ ".C"   : ShCXXAction,
101                                               ".cc"  : ShCXXAction,
102                                               ".cpp" : ShCXXAction,
103                                               ".cxx" : ShCXXAction,
104                                               ".c++" : ShCXXAction,
105                                               ".C++" : ShCXXAction,
106                                               ".c"   : "$SHCCCOM",
107                                               ".f"   : ShF77Action,
108                                               ".for" : ShF77Action,
109                                               ".FOR" : ShF77Action,
110                                               ".F"   : ShF77PPAction,
111                                               ".fpp" : ShF77PPAction,
112                                               ".FPP" : ShF77PPAction })
113
114 static_obj = SCons.Builder.DictCmdGenerator({ ".C"   : CXXAction,
115                                               ".cc"  : CXXAction,
116                                               ".cpp" : CXXAction,
117                                               ".cxx" : CXXAction,
118                                               ".c++" : CXXAction,
119                                               ".C++" : CXXAction,
120                                               ".c"   : "$CCCOM",
121                                               ".f"   : F77Action,
122                                               ".for" : F77Action,
123                                               ".F"   : F77PPAction,
124                                               ".FOR" : F77Action,
125                                               ".fpp" : F77PPAction,
126                                               ".FPP" : F77PPAction })
127                                                      
128 Object = SCons.Builder.Builder(name = 'Object',
129                                generator = \
130                                SharedCmdGenerator(static=SCons.Action.CommandGeneratorAction(static_obj),
131                                                   shared=SCons.Action.CommandGeneratorAction(shared_obj)),
132                                prefix = '$OBJPREFIX',
133                                suffix = '$OBJSUFFIX',
134                                src_suffix = static_obj.src_suffixes(),
135                                src_builder = [CFile, CXXFile])
136
137 def win32LinkGenerator(env, target, source, **kw):
138     cmd = env.subst_list([ '$LINK', '$LINKFLAGS', '/OUT:' + str(target[0]) ])[0]
139     cmd.extend(['$('] + env.subst_list('$_LIBDIRFLAGS')[0] + ['$)'])
140     cmd.extend(env.subst_list('$_LIBFLAGS')[0])
141     cmd.extend(map(lambda x: str(x), source))
142     cmdlen = reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)
143     if cmdlen <= 2048:
144         return [cmd]
145     else:
146         import tempfile
147         tmp = tempfile.mktemp()
148         args = filter(lambda x: x != '$(' and x != '$)', cmd[1:])
149         args = map(SCons.Util.quote_spaces, args)
150         open(tmp, 'w').write(string.join(args, " ") + "\n")
151         return [ [cmd[0], '@' + tmp],
152                  ['del', tmp] ]
153
154 kw = {
155        'name'        : 'Program',
156        'prefix'      : '$PROGPREFIX',
157        'suffix'      : '$PROGSUFFIX',
158        'src_suffix'  : '$OBJSUFFIX',
159        'src_builder' : Object,
160        'scanner'     : SCons.Scanner.Prog.ProgScan()
161 }
162
163 if sys.platform == 'win32':
164     kw['generator'] = win32LinkGenerator
165 else:
166     kw['action'] = '$LINKCOM'
167
168 Program = apply(SCons.Builder.Builder, (), kw)
169
170 class LibAffixGenerator:
171     def __init__(self, static, shared):
172         self.static_affix = static
173         self.shared_affix = shared
174
175     def __call__(self, shared=0, win32=0):
176         if shared:
177             return self.shared_affix
178         return self.static_affix
179
180 def win32LibGenerator(target, source, env, shared=1):
181     listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
182
183     for tgt in target:
184         ext = os.path.splitext(str(tgt))[1]
185         if ext == env.subst("$LIBSUFFIX"):
186             # Put it on the command line as an import library.
187             listCmd.append("${WIN32IMPLIBPREFIX}%s" % tgt)
188         else:
189             listCmd.append("${WIN32DLLPREFIX}%s" % tgt)
190
191     listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
192     for src in source:
193         ext = os.path.splitext(str(src))[1]
194         if ext == env.subst("$WIN32DEFSUFFIX"):
195             # Treat this source as a .def file.
196             listCmd.append("${WIN32DEFPREFIX}%s" % src)
197         else:
198             # Just treat it as a generic source file.
199             listCmd.append(str(src))
200     return [ listCmd ]
201
202 def win32LibEmitter(target, source, env, shared=0):
203     if shared:
204         dll = None
205         for tgt in target:
206             ext = os.path.splitext(str(tgt))[1]
207             if ext == env.subst("$SHLIBSUFFIX"):
208                 dll = tgt
209                 break
210         if not dll:
211             raise UserError("A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX"))
212         
213         if env.has_key("WIN32_INSERT_DEF") and \
214            env["WIN32_INSERT_DEF"] and \
215            not '.def' in map(lambda x: os.path.split(str(x))[1],
216                              source):
217
218             # append a def file to the list of sources
219             source.append("%s%s" % (os.path.splitext(str(dll))[0],
220                                     env.subst("$WIN32DEFSUFFIX")))
221         if not env.subst("$LIBSUFFIX") in \
222            map(lambda x: os.path.split(str(x))[1], target):
223             # Append an import library to the list of targets.
224             target.append("%s%s%s" % (env.subst("$LIBPREFIX"),
225                                       os.path.splitext(str(dll))[0],
226                                       env.subst("$LIBSUFFIX")))
227     return (target, source)
228
229 PosixLibrary = SCons.Builder.Builder(name = 'Library',
230                                      generator = \
231                                      SharedCmdGenerator(shared="$SHLINKCOM",
232                                                         static="$ARCOM"),
233                                      prefix = \
234                                      LibAffixGenerator(static='$LIBPREFIX',
235                                                        shared='$SHLIBPREFIX'),
236                                      suffix = \
237                                      LibAffixGenerator(static='$LIBSUFFIX',
238                                                        shared='$SHLIBSUFFIX'),
239                                      src_suffix = '$OBJSUFFIX',
240                                      src_builder = Object)
241
242 Win32Library = SCons.Builder.Builder(name = 'Library',
243                                      generator = \
244                                      SharedCmdGenerator(shared=SCons.Action.CommandGeneratorAction(win32LibGenerator),
245                                                         static="$ARCOM"),
246                                      emitter = win32LibEmitter,
247                                      prefix = \
248                                      LibAffixGenerator(static='$LIBPREFIX',
249                                                        shared='$SHLIBPREFIX'),
250                                      suffix = \
251                                      LibAffixGenerator(static='$LIBSUFFIX',
252                                                        shared='$SHLIBSUFFIX'),
253                                      src_suffix = '$OBJSUFFIX',
254                                      src_builder = Object)
255
256 LaTeXAction = SCons.Action.Action('$LATEXCOM')
257
258 DVI = SCons.Builder.Builder(name = 'DVI',
259                             action = { '.tex'   : '$TEXCOM',
260                                        '.ltx'   : LaTeXAction,
261                                        '.latex' : LaTeXAction,
262                                      },
263                             # The suffix is not configurable via a
264                             # construction variable like $DVISUFFIX
265                             # because the output file name is
266                             # hard-coded within TeX.
267                             suffix = '.dvi')
268
269 PDF = SCons.Builder.Builder(name = 'PDF',
270                             action = '$PDFCOM',
271                             prefix = '$PDFPREFIX',
272                             suffix = '$PDFSUFFIX',
273                             src_suffix = '.dvi',
274                             src_builder = DVI)
275
276 PostScript = SCons.Builder.Builder(name = 'PostScript',
277                                    action = '$PSCOM',
278                                    prefix = '$PSPREFIX',
279                                    suffix = '$PSSUFFIX',
280                                    src_suffix = '.dvi',
281                                    src_builder = DVI)
282
283 CScan = SCons.Scanner.C.CScan()
284
285 def alias_builder(env, target, source):
286     pass
287
288 Alias = SCons.Builder.Builder(name = 'Alias',
289                               action = alias_builder,
290                               target_factory = SCons.Node.Alias.default_ans.Alias,
291                               source_factory = SCons.Node.FS.default_fs.Entry)
292
293 def get_devstudio_versions ():
294     """
295     Get list of devstudio versions from the Windows registry.  Return a
296     list of strings containing version numbers; an exception will be raised
297     if we were unable to access the registry (eg. couldn't import
298     a registry-access module) or the appropriate registry keys weren't
299     found.
300     """
301
302     if not SCons.Util.can_read_reg:
303         raise SCons.Errors.InternalError, "No Windows registry module was found"
304
305     K = 'Software\\Microsoft\\Devstudio'
306     L = []
307     for base in (SCons.Util.HKEY_CLASSES_ROOT,
308                  SCons.Util.HKEY_LOCAL_MACHINE,
309                  SCons.Util.HKEY_CURRENT_USER,
310                  SCons.Util.HKEY_USERS):
311         try:
312             k = SCons.Util.RegOpenKeyEx(base,K)
313             i = 0
314             while 1:
315                 try:
316                     p = SCons.Util.RegEnumKey(k,i)
317                     if p[0] in '123456789' and p not in L:
318                         L.append(p)
319                 except SCons.Util.RegError:
320                     break
321                 i = i + 1
322         except SCons.Util.RegError:
323             pass
324
325     if not L:
326         raise SCons.Errors.InternalError, "DevStudio was not found."
327
328     L.sort()
329     L.reverse()
330     return L
331
332 def get_msvc_path (path, version, platform='x86'):
333     """
334     Get a list of devstudio directories (include, lib or path).  Return
335     a string delimited by ';'. An exception will be raised if unable to
336     access the registry or appropriate registry keys not found.
337     """
338
339     if not SCons.Util.can_read_reg:
340         raise SCons.Errors.InternalError, "No Windows registry module was found"
341
342     if path=='lib':
343         path= 'Library'
344     path = string.upper(path + ' Dirs')
345     K = ('Software\\Microsoft\\Devstudio\\%s\\' +
346          'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
347         (version,platform)
348     for base in (SCons.Util.HKEY_CLASSES_ROOT,
349                  SCons.Util.HKEY_LOCAL_MACHINE,
350                  SCons.Util.HKEY_CURRENT_USER,
351                  SCons.Util.HKEY_USERS):
352         try:
353             k = SCons.Util.RegOpenKeyEx(base,K)
354             i = 0
355             while 1:
356                 try:
357                     (p,v,t) = SCons.Util.RegEnumValue(k,i)
358                     if string.upper(p) == path:
359                         return v
360                     i = i + 1
361                 except SCons.Util.RegError:
362                     break
363         except SCons.Util.RegError:
364             pass
365
366     # if we got here, then we didn't find the registry entries:
367     raise SCons.Errors.InternalError, "%s was not found in the registry."%path
368
369 def get_msdev_dir(version):
370     """Returns the root directory of the MSDev installation from the
371     registry if it can be found, otherwise we guess."""
372     if SCons.Util.can_read_reg:
373         K = ('Software\\Microsoft\\Devstudio\\%s\\' +
374              'Products\\Microsoft Visual C++') % \
375              version
376         for base in (SCons.Util.HKEY_LOCAL_MACHINE,
377                      SCons.Util.HKEY_CURRENT_USER):
378             try:
379                 k = SCons.Util.RegOpenKeyEx(base,K)
380                 val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
381                 return os.path.split(val)[0]
382             except SCons.Util.RegError:
383                 pass
384
385 def make_win32_env_from_paths(include, lib, path):
386     """
387     Build a dictionary of construction variables for a win32 platform.
388     include - include path
389     lib - library path
390     path - executable path
391     """
392     return {
393         'CC'         : 'cl',
394         'CCFLAGS'    : '/nologo',
395         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
396         'SHCC'      : '$CC',
397         'SHCCFLAGS' : '$CCFLAGS',
398         'SHCCCOM'    : '$SHCC $SHCCFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
399         'CFILESUFFIX' : '.c',
400         'CXX'        : '$CC',
401         'CXXFLAGS'   : '$CCFLAGS',
402         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
403         'SHCXX'      : '$CXX',
404         'SHCXXFLAGS' : '$CXXFLAGS',
405         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
406         'CXXFILESUFFIX' : '.cc',
407         'F77'        : 'g77',
408         'F77FLAGS'   : '',
409         'F77COM'     : '$F77 $F77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
410         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
411         'SHF77'      : '$F77',
412         'SHF77FLAGS' : '$F77FLAGS',
413         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
414         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
415         'LINK'       : 'link',
416         'LINKFLAGS'  : '/nologo',
417         # XXX - We'd like to do this as follows, but '$LINKCOM' in
418         # a Builder above gets expanded too soon to stick a function
419         # right in the environment like this.  Revisit this when this
420         # capability has been added (cf. bug report #537058).
421         #'LINKCOM'    : win32Link,
422         'SHLINK'     : '$LINK',
423         'SHLINKFLAGS': '$LINKFLAGS /dll',
424         'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS /OUT:$TARGET $_LIBDIRFLAGS $_LIBFLAGS $SOURCES',
425         'AR'         : 'lib',
426         'ARFLAGS'    : '/nologo',
427         'ARCOM'      : '$AR $ARFLAGS /OUT:$TARGET $SOURCES',
428         'SHLIBPREFIX': '',
429         'SHLIBSUFFIX': '.dll',
430         'LEX'        : 'lex',
431         'LEXFLAGS'   : '',
432         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
433         'YACC'       : 'yacc',
434         'YACCFLAGS'  : '',
435         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
436         'TEX'        : 'tex',
437         'TEXFLAGS'   : '',
438         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
439         'LATEX'      : 'latex',
440         'LATEXFLAGS' : '',
441         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
442         'DVIPDF'     : 'dvipdf',
443         'DVIPDFFLAGS' : '',
444         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
445         'PDFPREFIX'  : '',
446         'PDFSUFFIX'  : '.pdf',
447         'DVIPS'      : 'dvips',
448         'DVIPSFLAGS' : '',
449         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
450         'PSPREFIX'   : '',
451         'PSSUFFIX'   : '.ps',
452         'BUILDERS'   : [Alias, CFile, CXXFile, DVI, Win32Library, Object,
453                         PDF, PostScript, Program],
454         'SCANNERS'   : [CScan],
455         'OBJPREFIX'  : '',
456         'OBJSUFFIX'  : '.obj',
457         'PROGPREFIX' : '',
458         'PROGSUFFIX' : '.exe',
459         'LIBPREFIX'  : '',
460         'LIBPREFIXES': '$LIBPREFIX',
461         'LIBSUFFIX'  : '.lib',
462         'LIBSUFFIXES': '$LIBSUFFIX',
463         'LIBDIRPREFIX'          : '/LIBPATH:',
464         'LIBDIRSUFFIX'          : '',
465         'LIBLINKPREFIX'         : '',
466         'LIBLINKSUFFIX'         : '$LIBSUFFIX',
467         'INCPREFIX'             : '/I',
468         'INCSUFFIX'             : '',
469         'WIN32DEFPREFIX'        : '/def:',
470         'WIN32DEFSUFFIX'        : '.def',
471         'WIN32DLLPREFIX'        : '/out:',
472         'WIN32IMPLIBPREFIX'     : '/implib:',
473         'WIN32_INSERT_DEF'      : 0,
474         'ENV'        : {
475             'INCLUDE'  : include,
476             'LIB'      : lib,
477             'PATH'     : path,
478                 'PATHEXT' : '.COM;.EXE;.BAT;.CMD',
479             },
480         }
481
482 def make_win32_env(version):
483     """
484     Build a dictionary of construction variables for a win32 platform.
485     ver - the version string of DevStudio to use (e.g. "6.0")
486     """
487     return make_win32_env_from_paths(get_msvc_path("include", version),
488                                      get_msvc_path("lib", version),
489                                      get_msvc_path("path", version)
490                                      + ";" + os.environ['PATH'])
491
492
493 if os.name == 'posix':
494     Library = PosixLibrary
495     
496     arcom = '$AR $ARFLAGS $TARGET $SOURCES'
497     ranlib = 'ranlib'
498     if SCons.Util.WhereIs(ranlib):
499         arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
500
501     ConstructionEnvironment = {
502         'CC'         : 'cc',
503         'CCFLAGS'    : '',
504         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
505         'SHCC'       : '$CC',
506         'SHCCFLAGS'  : '$CCFLAGS -fPIC',
507         'SHCCCOM'    : '$SHCC $SHCCFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
508         'CFILESUFFIX' : '.c',
509         'CXX'        : 'c++',
510         'CXXFLAGS'   : '$CCFLAGS',
511         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
512         'CXXFILESUFFIX' : '.cc',
513         'SHCXX'      : '$CXX',
514         'SHCXXFLAGS' : '$CXXFLAGS -fPIC',
515         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
516         'F77'        : 'g77',
517         'F77FLAGS'   : '',
518         'F77COM'     : '$F77 $F77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
519         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
520         'SHF77FLAGS' : '$F77FLAGS -fPIC',
521         'SHF77COM'   : '$F77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
522         'SHF77PPCOM' : '$F77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
523         'SHF77'      : '$F77',
524         'SHF77FLAGS' : '$F77FLAGS -fPIC',
525         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
526         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
527         'LINK'       : '$CXX',
528         'LINKFLAGS'  : '',
529         'LINKCOM'    : '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
530         'SHLINK'     : '$LINK',
531         'SHLINKFLAGS': '$LINKFLAGS -shared',
532         'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
533         'AR'         : 'ar',
534         'ARFLAGS'    : 'r',
535         'RANLIB'     : ranlib,
536         'RANLIBFLAGS' : '',
537         'ARCOM'      : arcom,
538         'SHLIBPREFIX': '$LIBPREFIX',
539         'SHLIBSUFFIX': '.so',
540         'LEX'        : 'lex',
541         'LEXFLAGS'   : '',
542         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
543         'YACC'       : 'yacc',
544         'YACCFLAGS'  : '',
545         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
546         'TEX'        : 'tex',
547         'TEXFLAGS'   : '',
548         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
549         'LATEX'      : 'latex',
550         'LATEXFLAGS' : '',
551         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
552         'DVIPDF'     : 'dvipdf',
553         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
554         'PDFPREFIX'  : '',
555         'PDFSUFFIX'  : '.pdf',
556         'DVIPS'      : 'dvips',
557         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
558         'PSPREFIX'   : '',
559         'PSSUFFIX'   : '.ps',
560         'BUILDERS'   : [Alias, CFile, CXXFile, DVI, PosixLibrary, Object,
561                         PDF, PostScript, Program],
562         'SCANNERS'   : [CScan],
563         'OBJPREFIX'  : '',
564         'OBJSUFFIX'  : '.o',
565         'PROGPREFIX' : '',
566         'PROGSUFFIX' : (sys.platform == 'cygwin') and '.exe' or '',
567         'LIBPREFIX'  : 'lib',
568         'LIBPREFIXES': '$LIBPREFIX',
569         'LIBSUFFIX'  : '.a',
570         'LIBSUFFIXES': [ '$LIBSUFFIX', '$SHLIBSUFFIX' ],
571         'LIBDIRPREFIX'          : '-L',
572         'LIBDIRSUFFIX'          : '',
573         'LIBLINKPREFIX'         : '-l',
574         'LIBLINKSUFFIX'         : '',
575         'INCPREFIX'             : '-I',
576         'INCSUFFIX'             : '',
577         'ENV'        : { 'PATH' : '/usr/local/bin:/bin:/usr/bin' },
578     }
579
580 elif os.name == 'nt':
581     Library = Win32Library
582     
583     versions = None
584     try:
585         versions = get_devstudio_versions()
586         ConstructionEnvironment = make_win32_env(versions[0]) #use highest version
587     except (SCons.Util.RegError, SCons.Errors.InternalError):
588         # Could not get the configured directories from the registry.
589         # However, the configured directories only appear if the user
590         # changes them from the default.  Therefore, we'll see if
591         # we can get the path to the MSDev base installation from
592         # the registry and deduce the default directories.
593         MVSdir = None
594         if versions:
595             MVSdir = get_msdev_dir(versions[0])
596         if MVSdir:
597             MVSVCdir = r'%s\VC98' % MVSdir
598             MVSCommondir = r'%s\Common' % MVSdir
599             try:
600                 extra_path = os.pathsep + os.environ['PATH']
601             except KeyError:
602                 extra_path = ''
603             ConstructionEnvironment = make_win32_env_from_paths(
604                 r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir),
605                 r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir),
606                 (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path)
607         else:
608             # The DevStudio environment variables don't exist,
609             # so just use the variables from the source environment.
610             MVSdir = r'C:\Program Files\Microsoft Visual Studio'
611             MVSVCdir = r'%s\VC98' % MVSdir
612             MVSCommondir = r'%s\Common' % MVSdir
613             try:
614                 include_path = os.environ['INCLUDE']
615             except KeyError:
616                 include_path = ''
617             try:
618                 lib_path = os.environ['LIB']
619             except KeyError:
620                 lib_path = ''
621             try:
622                 exe_path = os.environ['PATH']
623             except KeyError:
624                 exe_path = ''
625             ConstructionEnvironment = make_win32_env_from_paths(
626                 include_path,
627                 lib_path,
628                 exe_path)
629