929dbc9a12cbea85b7e92426b50ef9c5ad48ce5a
[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     args = []
139     for a in [env['LINKFLAGS'],
140               '/OUT:' + str(target[0]),
141               env['_LIBDIRFLAGS'],
142               env['_LIBFLAGS'],
143               map(lambda x: str(x), source)]:
144         if SCons.Util.is_List(a):
145             args.extend(a)
146         else:
147             args.append(a)
148     argstring = string.join(args, " ")
149     if len(argstring) <= 2048:
150         return env['LINK'] + " " + argstring
151     else:
152         import tempfile
153         tmp = tempfile.mktemp()
154         open(tmp, 'w').write(argstring + "\n")
155         return [ env['LINK'] + " @" + tmp,
156                  "del " + tmp, ]
157
158 kw = {
159        'name'        : 'Program',
160        'prefix'      : '$PROGPREFIX',
161        'suffix'      : '$PROGSUFFIX',
162        'src_suffix'  : '$OBJSUFFIX',
163        'src_builder' : Object,
164        'scanner'     : SCons.Scanner.Prog.ProgScan()
165 }
166
167 if sys.platform == 'win32':
168     kw['generator'] = win32LinkGenerator
169 else:
170     kw['action'] = '$LINKCOM'
171
172 Program = apply(SCons.Builder.Builder, (), kw)
173
174 class LibAffixGenerator:
175     def __init__(self, static, shared):
176         self.static_affix = static
177         self.shared_affix = shared
178
179     def __call__(self, shared=0, win32=0):
180         if shared:
181             return self.shared_affix
182         return self.static_affix
183
184 def win32LibGenerator(target, source, env, shared=1):
185     listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
186
187     for tgt in target:
188         ext = os.path.splitext(str(tgt))[1]
189         if ext == env.subst("$LIBSUFFIX"):
190             # Put it on the command line as an import library.
191             listCmd.append("${WIN32IMPLIBPREFIX}%s" % tgt)
192         else:
193             listCmd.append("${WIN32DLLPREFIX}%s" % tgt)
194
195     listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
196     for src in source:
197         ext = os.path.splitext(str(src))[1]
198         if ext == env.subst("$WIN32DEFSUFFIX"):
199             # Treat this source as a .def file.
200             listCmd.append("${WIN32DEFPREFIX}%s" % src)
201         else:
202             # Just treat it as a generic source file.
203             listCmd.append(str(src))
204     return [ listCmd ]
205
206 def win32LibEmitter(target, source, env, shared=0):
207     if shared:
208         dll = None
209         for tgt in target:
210             ext = os.path.splitext(str(tgt))[1]
211             if ext == env.subst("$SHLIBSUFFIX"):
212                 dll = tgt
213                 break
214         if not dll:
215             raise UserError("A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX"))
216         
217         if env.has_key("WIN32_INSERT_DEF") and \
218            env["WIN32_INSERT_DEF"] and \
219            not '.def' in map(lambda x: os.path.split(str(x))[1],
220                              source):
221
222             # append a def file to the list of sources
223             source.append("%s%s" % (os.path.splitext(str(dll))[0],
224                                     env.subst("$WIN32DEFSUFFIX")))
225         if not env.subst("$LIBSUFFIX") in \
226            map(lambda x: os.path.split(str(x))[1], target):
227             # Append an import library to the list of targets.
228             target.append("%s%s%s" % (env.subst("$LIBPREFIX"),
229                                       os.path.splitext(str(dll))[0],
230                                       env.subst("$LIBSUFFIX")))
231     return (target, source)
232
233 PosixLibrary = SCons.Builder.Builder(name = 'Library',
234                                      generator = \
235                                      SharedCmdGenerator(shared="$SHLINKCOM",
236                                                         static="$ARCOM"),
237                                      prefix = \
238                                      LibAffixGenerator(static='$LIBPREFIX',
239                                                        shared='$SHLIBPREFIX'),
240                                      suffix = \
241                                      LibAffixGenerator(static='$LIBSUFFIX',
242                                                        shared='$SHLIBSUFFIX'),
243                                      src_suffix = '$OBJSUFFIX',
244                                      src_builder = Object)
245
246 Win32Library = SCons.Builder.Builder(name = 'Library',
247                                      generator = \
248                                      SharedCmdGenerator(shared=SCons.Action.CommandGeneratorAction(win32LibGenerator),
249                                                         static="$ARCOM"),
250                                      emitter = win32LibEmitter,
251                                      prefix = \
252                                      LibAffixGenerator(static='$LIBPREFIX',
253                                                        shared='$SHLIBPREFIX'),
254                                      suffix = \
255                                      LibAffixGenerator(static='$LIBSUFFIX',
256                                                        shared='$SHLIBSUFFIX'),
257                                      src_suffix = '$OBJSUFFIX',
258                                      src_builder = Object)
259
260 LaTeXAction = SCons.Action.Action('$LATEXCOM')
261
262 DVI = SCons.Builder.Builder(name = 'DVI',
263                             action = { '.tex'   : '$TEXCOM',
264                                        '.ltx'   : LaTeXAction,
265                                        '.latex' : LaTeXAction,
266                                      },
267                             # The suffix is not configurable via a
268                             # construction variable like $DVISUFFIX
269                             # because the output file name is
270                             # hard-coded within TeX.
271                             suffix = '.dvi')
272
273 PDF = SCons.Builder.Builder(name = 'PDF',
274                             action = '$PDFCOM',
275                             prefix = '$PDFPREFIX',
276                             suffix = '$PDFSUFFIX',
277                             src_suffix = '.dvi',
278                             src_builder = DVI)
279
280 PostScript = SCons.Builder.Builder(name = 'PostScript',
281                                    action = '$PSCOM',
282                                    prefix = '$PSPREFIX',
283                                    suffix = '$PSSUFFIX',
284                                    src_suffix = '.dvi',
285                                    src_builder = DVI)
286
287 CScan = SCons.Scanner.C.CScan()
288
289 def alias_builder(env, target, source):
290     pass
291
292 Alias = SCons.Builder.Builder(name = 'Alias',
293                               action = alias_builder,
294                               target_factory = SCons.Node.Alias.default_ans.Alias,
295                               source_factory = SCons.Node.FS.default_fs.Entry)
296
297 def get_devstudio_versions ():
298     """
299     Get list of devstudio versions from the Windows registry.  Return a
300     list of strings containing version numbers; an exception will be raised
301     if we were unable to access the registry (eg. couldn't import
302     a registry-access module) or the appropriate registry keys weren't
303     found.
304     """
305
306     if not SCons.Util.can_read_reg:
307         raise SCons.Errors.InternalError, "No Windows registry module was found"
308
309     K = 'Software\\Microsoft\\Devstudio'
310     L = []
311     for base in (SCons.Util.HKEY_CLASSES_ROOT,
312                  SCons.Util.HKEY_LOCAL_MACHINE,
313                  SCons.Util.HKEY_CURRENT_USER,
314                  SCons.Util.HKEY_USERS):
315         try:
316             k = SCons.Util.RegOpenKeyEx(base,K)
317             i = 0
318             while 1:
319                 try:
320                     p = SCons.Util.RegEnumKey(k,i)
321                     if p[0] in '123456789' and p not in L:
322                         L.append(p)
323                 except SCons.Util.RegError:
324                     break
325                 i = i + 1
326         except SCons.Util.RegError:
327             pass
328
329     if not L:
330         raise SCons.Errors.InternalError, "DevStudio was not found."
331
332     L.sort()
333     L.reverse()
334     return L
335
336 def get_msvc_path (path, version, platform='x86'):
337     """
338     Get a list of devstudio directories (include, lib or path).  Return
339     a string delimited by ';'. An exception will be raised if unable to
340     access the registry or appropriate registry keys not found.
341     """
342
343     if not SCons.Util.can_read_reg:
344         raise SCons.Errors.InternalError, "No Windows registry module was found"
345
346     if path=='lib':
347         path= 'Library'
348     path = string.upper(path + ' Dirs')
349     K = ('Software\\Microsoft\\Devstudio\\%s\\' +
350          'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
351         (version,platform)
352     for base in (SCons.Util.HKEY_CLASSES_ROOT,
353                  SCons.Util.HKEY_LOCAL_MACHINE,
354                  SCons.Util.HKEY_CURRENT_USER,
355                  SCons.Util.HKEY_USERS):
356         try:
357             k = SCons.Util.RegOpenKeyEx(base,K)
358             i = 0
359             while 1:
360                 try:
361                     (p,v,t) = SCons.Util.RegEnumValue(k,i)
362                     if string.upper(p) == path:
363                         return v
364                     i = i + 1
365                 except SCons.Util.RegError:
366                     break
367         except SCons.Util.RegError:
368             pass
369
370     # if we got here, then we didn't find the registry entries:
371     raise SCons.Errors.InternalError, "%s was not found in the registry."%path
372
373 def get_msdev_dir(version):
374     """Returns the root directory of the MSDev installation from the
375     registry if it can be found, otherwise we guess."""
376     if SCons.Util.can_read_reg:
377         K = ('Software\\Microsoft\\Devstudio\\%s\\' +
378              'Products\\Microsoft Visual C++') % \
379              version
380         for base in (SCons.Util.HKEY_LOCAL_MACHINE,
381                      SCons.Util.HKEY_CURRENT_USER):
382             try:
383                 k = SCons.Util.RegOpenKeyEx(base,K)
384                 val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
385                 return os.path.split(val)[0]
386             except SCons.Util.RegError:
387                 pass
388
389 def make_win32_env_from_paths(include, lib, path):
390     """
391     Build a dictionary of construction variables for a win32 platform.
392     include - include path
393     lib - library path
394     path - executable path
395     """
396     return {
397         'CC'         : 'cl',
398         'CCFLAGS'    : '/nologo',
399         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
400         'SHCC'      : '$CC',
401         'SHCCFLAGS' : '$CCFLAGS',
402         'SHCCCOM'    : '$SHCC $SHCCFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
403         'CFILESUFFIX' : '.c',
404         'CXX'        : '$CC',
405         'CXXFLAGS'   : '$CCFLAGS',
406         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
407         'SHCXX'      : '$CXX',
408         'SHCXXFLAGS' : '$CXXFLAGS',
409         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $CPPFLAGS $_INCFLAGS /c $SOURCES /Fo$TARGET',
410         'CXXFILESUFFIX' : '.cc',
411         'F77'        : 'g77',
412         'F77FLAGS'   : '',
413         'F77COM'     : '$F77 $F77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
414         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
415         'SHF77'      : '$F77',
416         'SHF77FLAGS' : '$F77FLAGS',
417         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
418         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
419         'LINK'       : 'link',
420         'LINKFLAGS'  : '/nologo',
421         # XXX - We'd like to do this as follows, but '$LINKCOM' in
422         # a Builder above gets expanded too soon to stick a function
423         # right in the environment like this.  Revisit this when this
424         # capability has been added (cf. bug report #537058).
425         #'LINKCOM'    : win32Link,
426         'SHLINK'     : '$LINK',
427         'SHLINKFLAGS': '$LINKFLAGS /dll',
428         'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS /OUT:$TARGET $_LIBDIRFLAGS $_LIBFLAGS $SOURCES',
429         'AR'         : 'lib',
430         'ARFLAGS'    : '/nologo',
431         'ARCOM'      : '$AR $ARFLAGS /OUT:$TARGET $SOURCES',
432         'SHLIBPREFIX': '',
433         'SHLIBSUFFIX': '.dll',
434         'LEX'        : 'lex',
435         'LEXFLAGS'   : '',
436         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
437         'YACC'       : 'yacc',
438         'YACCFLAGS'  : '',
439         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
440         'TEX'        : 'tex',
441         'TEXFLAGS'   : '',
442         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
443         'LATEX'      : 'latex',
444         'LATEXFLAGS' : '',
445         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
446         'DVIPDF'     : 'dvipdf',
447         'DVIPDFFLAGS' : '',
448         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
449         'PDFPREFIX'  : '',
450         'PDFSUFFIX'  : '.pdf',
451         'DVIPS'      : 'dvips',
452         'DVIPSFLAGS' : '',
453         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
454         'PSPREFIX'   : '',
455         'PSSUFFIX'   : '.ps',
456         'BUILDERS'   : [Alias, CFile, CXXFile, DVI, Win32Library, Object,
457                         PDF, PostScript, Program],
458         'SCANNERS'   : [CScan],
459         'OBJPREFIX'  : '',
460         'OBJSUFFIX'  : '.obj',
461         'PROGPREFIX' : '',
462         'PROGSUFFIX' : '.exe',
463         'LIBPREFIX'  : '',
464         'LIBPREFIXES': '$LIBPREFIX',
465         'LIBSUFFIX'  : '.lib',
466         'LIBSUFFIXES': '$LIBSUFFIX',
467         'LIBDIRPREFIX'          : '/LIBPATH:',
468         'LIBDIRSUFFIX'          : '',
469         'LIBLINKPREFIX'         : '',
470         'LIBLINKSUFFIX'         : '$LIBSUFFIX',
471         'INCPREFIX'             : '/I',
472         'INCSUFFIX'             : '',
473         'WIN32DEFPREFIX'        : '/def:',
474         'WIN32DEFSUFFIX'        : '.def',
475         'WIN32DLLPREFIX'        : '/out:',
476         'WIN32IMPLIBPREFIX'     : '/implib:',
477         'WIN32_INSERT_DEF'      : 0,
478         'ENV'        : {
479             'INCLUDE'  : include,
480             'LIB'      : lib,
481             'PATH'     : path,
482                 'PATHEXT' : '.COM;.EXE;.BAT;.CMD',
483             },
484         }
485
486 def make_win32_env(version):
487     """
488     Build a dictionary of construction variables for a win32 platform.
489     ver - the version string of DevStudio to use (e.g. "6.0")
490     """
491     return make_win32_env_from_paths(get_msvc_path("include", version),
492                                      get_msvc_path("lib", version),
493                                      get_msvc_path("path", version)
494                                      + ";" + os.environ['PATH'])
495
496
497 if os.name == 'posix':
498     Library = PosixLibrary
499     
500     arcom = '$AR $ARFLAGS $TARGET $SOURCES'
501     ranlib = 'ranlib'
502     if SCons.Util.WhereIs(ranlib):
503         arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
504
505     ConstructionEnvironment = {
506         'CC'         : 'cc',
507         'CCFLAGS'    : '',
508         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
509         'SHCC'       : '$CC',
510         'SHCCFLAGS'  : '$CCFLAGS -fPIC',
511         'SHCCCOM'    : '$SHCC $SHCCFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
512         'CFILESUFFIX' : '.c',
513         'CXX'        : 'c++',
514         'CXXFLAGS'   : '$CCFLAGS',
515         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
516         'CXXFILESUFFIX' : '.cc',
517         'SHCXX'      : '$CXX',
518         'SHCXXFLAGS' : '$CXXFLAGS -fPIC',
519         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
520         'F77'        : 'g77',
521         'F77FLAGS'   : '',
522         'F77COM'     : '$F77 $F77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
523         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
524         'SHF77FLAGS' : '$F77FLAGS -fPIC',
525         'SHF77COM'   : '$F77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
526         'SHF77PPCOM' : '$F77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
527         'SHF77'      : '$F77',
528         'SHF77FLAGS' : '$F77FLAGS -fPIC',
529         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
530         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_INCFLAGS -c -o $TARGET $SOURCES',
531         'LINK'       : '$CXX',
532         'LINKFLAGS'  : '',
533         'LINKCOM'    : '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
534         'SHLINK'     : '$LINK',
535         'SHLINKFLAGS': '$LINKFLAGS -shared',
536         'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
537         'AR'         : 'ar',
538         'ARFLAGS'    : 'r',
539         'RANLIB'     : ranlib,
540         'RANLIBFLAGS' : '',
541         'ARCOM'      : arcom,
542         'SHLIBPREFIX': '$LIBPREFIX',
543         'SHLIBSUFFIX': '.so',
544         'LEX'        : 'lex',
545         'LEXFLAGS'   : '',
546         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
547         'YACC'       : 'yacc',
548         'YACCFLAGS'  : '',
549         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
550         'TEX'        : 'tex',
551         'TEXFLAGS'   : '',
552         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
553         'LATEX'      : 'latex',
554         'LATEXFLAGS' : '',
555         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
556         'DVIPDF'     : 'dvipdf',
557         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
558         'PDFPREFIX'  : '',
559         'PDFSUFFIX'  : '.pdf',
560         'DVIPS'      : 'dvips',
561         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
562         'PSPREFIX'   : '',
563         'PSSUFFIX'   : '.ps',
564         'BUILDERS'   : [Alias, CFile, CXXFile, DVI, PosixLibrary, Object,
565                         PDF, PostScript, Program],
566         'SCANNERS'   : [CScan],
567         'OBJPREFIX'  : '',
568         'OBJSUFFIX'  : '.o',
569         'PROGPREFIX' : '',
570         'PROGSUFFIX' : (sys.platform == 'cygwin') and '.exe' or '',
571         'LIBPREFIX'  : 'lib',
572         'LIBPREFIXES': '$LIBPREFIX',
573         'LIBSUFFIX'  : '.a',
574         'LIBSUFFIXES': [ '$LIBSUFFIX', '$SHLIBSUFFIX' ],
575         'LIBDIRPREFIX'          : '-L',
576         'LIBDIRSUFFIX'          : '',
577         'LIBLINKPREFIX'         : '-l',
578         'LIBLINKSUFFIX'         : '',
579         'INCPREFIX'             : '-I',
580         'INCSUFFIX'             : '',
581         'ENV'        : { 'PATH' : '/usr/local/bin:/bin:/usr/bin' },
582     }
583
584 elif os.name == 'nt':
585     Library = Win32Library
586     
587     versions = None
588     try:
589         versions = get_devstudio_versions()
590         ConstructionEnvironment = make_win32_env(versions[0]) #use highest version
591     except (SCons.Util.RegError, SCons.Errors.InternalError):
592         # Could not get the configured directories from the registry.
593         # However, the configured directories only appear if the user
594         # changes them from the default.  Therefore, we'll see if
595         # we can get the path to the MSDev base installation from
596         # the registry and deduce the default directories.
597         MVSdir = None
598         if versions:
599             MVSdir = get_msdev_dir(versions[0])
600         if MVSdir:
601             MVSVCdir = r'%s\VC98' % MVSdir
602             MVSCommondir = r'%s\Common' % MVSdir
603             try:
604                 extra_path = os.pathsep + os.environ['PATH']
605             except KeyError:
606                 extra_path = ''
607             ConstructionEnvironment = make_win32_env_from_paths(
608                 r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir),
609                 r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir),
610                 (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path)
611         else:
612             # The DevStudio environment variables don't exist,
613             # so just use the variables from the source environment.
614             MVSdir = r'C:\Program Files\Microsoft Visual Studio'
615             MVSVCdir = r'%s\VC98' % MVSdir
616             MVSCommondir = r'%s\Common' % MVSdir
617             try:
618                 include_path = os.environ['INCLUDE']
619             except KeyError:
620                 include_path = ''
621             try:
622                 lib_path = os.environ['LIB']
623             except KeyError:
624                 lib_path = ''
625             try:
626                 exe_path = os.environ['PATH']
627             except KeyError:
628                 exe_path = ''
629             ConstructionEnvironment = make_win32_env_from_paths(
630                 include_path,
631                 lib_path,
632                 exe_path)
633