e7a49b8656722ec5c67cbdf5f2222b7b64707d51
[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.Platform
51 import SCons.Scanner.C
52 import SCons.Scanner.Fortran
53 import SCons.Scanner.Prog
54 import SCons.Util
55
56 def yaccEmitter(target, source, env, **kw):
57     # Yacc can be configured to emit a .h file as well
58     # as a .c file, if -d is specified on the command line.
59     if len(source) and \
60        os.path.splitext(SCons.Util.to_String(source[0]))[1] in \
61        [ '.y', '.yy'] and \
62        '-d' in string.split(env.subst("$YACCFLAGS")):
63         target.append(os.path.splitext(SCons.Util.to_String(target[0]))[0] + \
64                       '.h')
65     return (target, source)
66
67 CFile = SCons.Builder.Builder(action = { '.l'    : '$LEXCOM',
68                                          '.y'    : '$YACCCOM',
69                                        },
70                               emitter = yaccEmitter,
71                               suffix = '$CFILESUFFIX')
72
73 CXXFile = SCons.Builder.Builder(action = { '.ll' : '$LEXCOM',
74                                            '.yy' : '$YACCCOM',
75                                          },
76                                 emitter = yaccEmitter,
77                                 suffix = '$CXXFILESUFFIX')
78
79 class SharedFlagChecker:
80     """This is a callable class that is used as
81     a build action for all objects, libraries, and programs.
82     Its job is to run before the "real" action that builds the
83     file, to make sure we aren't trying to link shared objects
84     into a static library/program, or static objects into a
85     shared library."""
86
87     def __init__(self, shared):
88         self.shared = shared
89
90     def __call__(self, source, target, env, **kw):
91         if kw.has_key('shared'):
92             raise SCons.Errors.UserError, "The shared= parameter to Library() or Object() no longer works.\nUse SharedObject() or SharedLibrary() instead."
93         for tgt in target:
94             tgt.attributes.shared = self.shared
95
96         for src in source:
97             if hasattr(src.attributes, 'shared'):
98                 if self.shared and not src.attributes.shared:
99                     raise SCons.Errors.UserError, "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])
100                 elif not self.shared and src.attributes.shared:
101                     raise SCons.Errors.UserError, "Source file: %s is shared and is not compatible with static target: %s" % (src, target[0])
102
103 SharedCheck = SharedFlagChecker(1)
104 StaticCheck = SharedFlagChecker(0)
105
106 CAction = SCons.Action.Action([ StaticCheck, "$CCCOM" ])
107 ShCAction = SCons.Action.Action([ SharedCheck, "$SHCCCOM" ])
108 CXXAction = SCons.Action.Action([ StaticCheck, "$CXXCOM" ])
109 ShCXXAction = SCons.Action.Action([ SharedCheck, "$SHCXXCOM" ])
110 F77Action = SCons.Action.Action([ StaticCheck, "$F77COM" ])
111 ShF77Action = SCons.Action.Action([ SharedCheck, "$SHF77COM" ])
112 F77PPAction = SCons.Action.Action([ StaticCheck, "$F77PPCOM" ])
113 ShF77PPAction = SCons.Action.Action([ SharedCheck, "$SHF77PPCOM" ])
114
115 if os.path.normcase('.c') == os.path.normcase('.C'):
116     # We're on a case-insensitive system, so .[CF] (upper case)
117     # files should be treated like .[cf] (lower case) files.
118     C_static = CAction
119     C_shared = ShCAction
120     F_static = F77Action
121     F_shared = ShF77Action
122 else:
123     # We're on a case-sensitive system, so .C (upper case) files
124     # are C++, and .F (upper case) files get run through the C
125     # preprocessor.
126     C_static = CXXAction
127     C_shared = ShCXXAction
128     F_static = F77PPAction
129     F_shared = ShF77PPAction
130
131 StaticObject = SCons.Builder.Builder(action = { ".C"   : C_static,
132                                                 ".cc"  : CXXAction,
133                                                 ".cpp" : CXXAction,
134                                                 ".cxx" : CXXAction,
135                                                 ".c++" : CXXAction,
136                                                 ".C++" : CXXAction,
137                                                 ".c"   : CAction,
138                                                 ".f"   : F77Action,
139                                                 ".for" : F77Action,
140                                                 ".F"   : F_static,
141                                                 ".FOR" : F77Action,
142                                                 ".fpp" : F77PPAction,
143                                                 ".FPP" : F77PPAction },
144                                      prefix = '$OBJPREFIX',
145                                      suffix = '$OBJSUFFIX',
146                                      src_builder = [CFile, CXXFile])
147
148 SharedObject = SCons.Builder.Builder(action = { ".C"   : C_shared,
149                                                 ".cc"  : ShCXXAction,
150                                                 ".cpp" : ShCXXAction,
151                                                 ".cxx" : ShCXXAction,
152                                                 ".c++" : ShCXXAction,
153                                                 ".C++" : ShCXXAction,
154                                                 ".c"   : ShCAction,
155                                                 ".f"   : ShF77Action,
156                                                 ".for" : ShF77Action,
157                                                 ".FOR" : ShF77Action,
158                                                 ".F"   : F_shared,
159                                                 ".fpp" : ShF77PPAction,
160                                                 ".FPP" : ShF77PPAction },
161                                      prefix = '$OBJPREFIX',
162                                      suffix = '$OBJSUFFIX',
163                                      src_builder = [CFile, CXXFile])
164
165 def win32TempFileMunge(env, cmd_list, for_signature): 
166     """Given a list of command line arguments, see if it is too
167     long to pass to the win32 command line interpreter.  If so,
168     create a temp file, then pass "@tempfile" as the sole argument
169     to the supplied command (which is the first element of cmd_list).
170     Otherwise, just return [cmd_list]."""
171     cmd = env.subst_list(cmd_list)[0]
172     if for_signature or \
173        (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= 2048:
174         return [cmd_list]
175     else:
176         import tempfile
177         # We do a normpath because mktemp() has what appears to be
178         # a bug in Win32 that will use a forward slash as a path
179         # delimiter.  Win32's link mistakes that for a command line
180         # switch and barfs.
181         tmp = os.path.normpath(tempfile.mktemp())
182         args = map(SCons.Util.quote_spaces, cmd[1:])
183         open(tmp, 'w').write(string.join(args, " ") + "\n")
184         return [ [cmd[0], '@' + tmp],
185                  ['del', tmp] ]
186     
187 def win32LinkGenerator(env, target, source, for_signature, **kw):
188     args = [ '$LINK', '$LINKFLAGS', '/OUT:%s' % target[0],
189              '$(', '$_LIBDIRFLAGS', '$)', '$_LIBFLAGS' ]
190     args.extend(map(SCons.Util.to_String, source))
191     return win32TempFileMunge(env, args, for_signature)
192
193 ProgScan = SCons.Scanner.Prog.ProgScan()
194
195 Program = SCons.Builder.Builder(action=[ StaticCheck, '$LINKCOM' ],
196                                 prefix='$PROGPREFIX',
197                                 suffix='$PROGSUFFIX',
198                                 src_suffix='$OBJSUFFIX',
199                                 src_builder=StaticObject,
200                                 scanner = ProgScan)
201
202 def win32LibGenerator(target, source, env, for_signature, no_import_lib=0):
203     listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
204
205     for tgt in target:
206         ext = os.path.splitext(str(tgt))[1]
207         if ext == env.subst("$LIBSUFFIX"):
208             # Put it on the command line as an import library.
209             if no_import_lib:
210                 raise SCons.Errors.UserError, "%s: You cannot specify a .lib file as a target of a shared library build if no_import_library is nonzero." % tgt
211             listCmd.append("${WIN32IMPLIBPREFIX}%s" % tgt)
212         else:
213             listCmd.append("${WIN32DLLPREFIX}%s" % tgt)
214
215     listCmd.extend([ '$_LIBDIRFLAGS', '$_LIBFLAGS' ])
216     for src in source:
217         ext = os.path.splitext(str(src))[1]
218         if ext == env.subst("$WIN32DEFSUFFIX"):
219             # Treat this source as a .def file.
220             listCmd.append("${WIN32DEFPREFIX}%s" % src)
221         else:
222             # Just treat it as a generic source file.
223             listCmd.append(str(src))
224     return win32TempFileMunge(env, listCmd, for_signature)
225
226 def win32LibEmitter(target, source, env, no_import_lib=0):
227     dll = None
228     for tgt in target:
229         ext = os.path.splitext(str(tgt))[1]
230         if ext == env.subst("$SHLIBSUFFIX"):
231             dll = tgt
232             break
233     if not dll:
234         raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
235         
236     if env.has_key("WIN32_INSERT_DEF") and \
237        env["WIN32_INSERT_DEF"] and \
238        not '.def' in map(lambda x: os.path.split(str(x))[1],
239                          source):
240
241         # append a def file to the list of sources
242         source.append("%s%s" % (os.path.splitext(str(dll))[0],
243                                 env.subst("$WIN32DEFSUFFIX")))
244     if not no_import_lib and \
245        not env.subst("$LIBSUFFIX") in \
246        map(lambda x: os.path.split(str(x))[1], target):
247         # Append an import library to the list of targets.
248         target.append("%s%s%s" % (env.subst("$LIBPREFIX"),
249                                   os.path.splitext(str(dll))[0],
250                                   env.subst("$LIBSUFFIX")))
251     return (target, source)
252
253 StaticLibrary = SCons.Builder.Builder(action=[ StaticCheck, "$ARCOM" ],
254                                       prefix = '$LIBPREFIX',
255                                       suffix = '$LIBSUFFIX',
256                                       src_suffix = '$OBJSUFFIX',
257                                       src_builder = StaticObject)
258
259 SharedLibrary = SCons.Builder.Builder(action=[ SharedCheck, "$SHLINKCOM" ],
260                                       emitter="$LIBEMITTER",
261                                       prefix = '$SHLIBPREFIX',
262                                       suffix = '$SHLIBSUFFIX',
263                                       scanner = ProgScan,
264                                       src_suffix = '$OBJSUFFIX',
265                                       src_builder = SharedObject)
266
267 LaTeXAction = SCons.Action.Action('$LATEXCOM')
268
269 DVI = SCons.Builder.Builder(action = { '.tex'   : '$TEXCOM',
270                                        '.ltx'   : LaTeXAction,
271                                        '.latex' : LaTeXAction,
272                                      },
273                             # The suffix is not configurable via a
274                             # construction variable like $DVISUFFIX
275                             # because the output file name is
276                             # hard-coded within TeX.
277                             suffix = '.dvi')
278
279 PDFLaTeXAction = SCons.Action.Action('$PDFLATEXCOM')
280
281 PDF = SCons.Builder.Builder(action = { '.dvi'   : '$PDFCOM',
282                                        '.tex'   : '$PDFTEXCOM',
283                                        '.ltx'   : PDFLaTeXAction,
284                                        '.latex' : PDFLaTeXAction,
285                                      },
286                             prefix = '$PDFPREFIX',
287                             suffix = '$PDFSUFFIX')
288
289 PostScript = SCons.Builder.Builder(action = '$PSCOM',
290                                    prefix = '$PSPREFIX',
291                                    suffix = '$PSSUFFIX',
292                                    src_suffix = '.dvi',
293                                    src_builder = DVI)
294
295 CScan = SCons.Scanner.C.CScan()
296
297 FortranScan = SCons.Scanner.Fortran.FortranScan()
298
299 def alias_builder(env, target, source):
300     pass
301
302 Alias = SCons.Builder.Builder(action = alias_builder,
303                               target_factory = SCons.Node.Alias.default_ans.Alias,
304                               source_factory = SCons.Node.FS.default_fs.Entry,
305                               multi = 1)
306
307 def get_devstudio_versions ():
308     """
309     Get list of devstudio versions from the Windows registry.  Return a
310     list of strings containing version numbers; an exception will be raised
311     if we were unable to access the registry (eg. couldn't import
312     a registry-access module) or the appropriate registry keys weren't
313     found.
314     """
315
316     if not SCons.Util.can_read_reg:
317         raise SCons.Errors.InternalError, "No Windows registry module was found"
318
319     K = 'Software\\Microsoft\\Devstudio'
320     L = []
321     for base in (SCons.Util.HKEY_CLASSES_ROOT,
322                  SCons.Util.HKEY_LOCAL_MACHINE,
323                  SCons.Util.HKEY_CURRENT_USER,
324                  SCons.Util.HKEY_USERS):
325         try:
326             k = SCons.Util.RegOpenKeyEx(base,K)
327             i = 0
328             while 1:
329                 try:
330                     p = SCons.Util.RegEnumKey(k,i)
331                     if p[0] in '123456789' and p not in L:
332                         L.append(p)
333                 except SCons.Util.RegError:
334                     break
335                 i = i + 1
336         except SCons.Util.RegError:
337             pass
338
339     if not L:
340         raise SCons.Errors.InternalError, "DevStudio was not found."
341
342     L.sort()
343     L.reverse()
344     return L
345
346 def get_msvc_path (path, version, platform='x86'):
347     """
348     Get a list of devstudio directories (include, lib or path).  Return
349     a string delimited by ';'. An exception will be raised if unable to
350     access the registry or appropriate registry keys not found.
351     """
352
353     if not SCons.Util.can_read_reg:
354         raise SCons.Errors.InternalError, "No Windows registry module was found"
355
356     if path=='lib':
357         path= 'Library'
358     path = string.upper(path + ' Dirs')
359     K = ('Software\\Microsoft\\Devstudio\\%s\\' +
360          'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
361         (version,platform)
362     for base in (SCons.Util.HKEY_CLASSES_ROOT,
363                  SCons.Util.HKEY_LOCAL_MACHINE,
364                  SCons.Util.HKEY_CURRENT_USER,
365                  SCons.Util.HKEY_USERS):
366         try:
367             k = SCons.Util.RegOpenKeyEx(base,K)
368             i = 0
369             while 1:
370                 try:
371                     (p,v,t) = SCons.Util.RegEnumValue(k,i)
372                     if string.upper(p) == path:
373                         return v
374                     i = i + 1
375                 except SCons.Util.RegError:
376                     break
377         except SCons.Util.RegError:
378             pass
379
380     # if we got here, then we didn't find the registry entries:
381     raise SCons.Errors.InternalError, "%s was not found in the registry."%path
382
383 def get_msdev_dir(version):
384     """Returns the root directory of the MSDev installation from the
385     registry if it can be found, otherwise we guess."""
386     if SCons.Util.can_read_reg:
387         K = ('Software\\Microsoft\\Devstudio\\%s\\' +
388              'Products\\Microsoft Visual C++') % \
389              version
390         for base in (SCons.Util.HKEY_LOCAL_MACHINE,
391                      SCons.Util.HKEY_CURRENT_USER):
392             try:
393                 k = SCons.Util.RegOpenKeyEx(base,K)
394                 val, tok = SCons.Util.RegQueryValueEx(k, 'ProductDir')
395                 return os.path.split(val)[0]
396             except SCons.Util.RegError:
397                 pass
398
399 def make_win32_env_from_paths(include, lib, path):
400     """
401     Build a dictionary of construction variables for a win32 platform.
402     include - include path
403     lib - library path
404     path - executable path
405     """
406     return {
407         'CC'         : 'cl',
408         'CCFLAGS'    : '/nologo',
409         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
410         'SHCC'      : '$CC',
411         'SHCCFLAGS' : '$CCFLAGS',
412         'SHCCCOM'    : '$SHCC $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
413         'CFILESUFFIX' : '.c',
414         'CXX'        : '$CC',
415         'CXXFLAGS'   : '$CCFLAGS',
416         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
417         'SHCXX'      : '$CXX',
418         'SHCXXFLAGS' : '$CXXFLAGS',
419         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $CPPFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET',
420         'CXXFILESUFFIX' : '.cc',
421         'F77'        : 'g77',
422         'F77FLAGS'   : '',
423         'F77COM'     : '$F77 $F77FLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
424         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
425         'SHF77'      : '$F77',
426         'SHF77FLAGS' : '$F77FLAGS',
427         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
428         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS /c $SOURCES /Fo$TARGET',
429         'LINK'       : 'link',
430         'LINKFLAGS'  : '/nologo',
431         'LINKCOM'    : SCons.Action.CommandGenerator(win32LinkGenerator),
432         'SHLINK'     : '$LINK',
433         'SHLINKFLAGS': '$LINKFLAGS /dll',
434         'SHLINKCOM'  : SCons.Action.CommandGenerator(win32LibGenerator),
435         'AR'         : 'lib',
436         'ARFLAGS'    : '/nologo',
437         'ARCOM'      : '$AR $ARFLAGS /OUT:$TARGET $SOURCES',
438         'LEX'        : 'lex',
439         'LEXFLAGS'   : '',
440         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
441         'YACC'       : 'yacc',
442         'YACCFLAGS'  : '',
443         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
444         'TEX'        : 'tex',
445         'TEXFLAGS'   : '',
446         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
447         'LATEX'      : 'latex',
448         'LATEXFLAGS' : '',
449         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
450         'DVIPDF'     : 'dvipdf',
451         'DVIPDFFLAGS' : '',
452         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
453         'PDFPREFIX'  : '',
454         'PDFSUFFIX'  : '.pdf',
455         'PDFTEX'     : 'pdftex',
456         'PDFTEXFLAGS' : '',
457         'PDFTEXCOM'  : '$PDFTEX $PDFTEXFLAGS $SOURCES $TARGET',
458         'PDFLATEX'   : 'pdflatex',
459         'PDFLATEXFLAGS' : '',
460         'PDFLATEXCOM' : '$PDFLATEX $PDFLATEXFLAGS $SOURCES $TARGET',
461         'DVIPS'      : 'dvips',
462         'DVIPSFLAGS' : '',
463         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
464         'PSPREFIX'   : '',
465         'PSSUFFIX'   : '.ps',
466         'BUILDERS'   : { 'Alias'          : Alias,
467                          'CFile'          : CFile,
468                          'CXXFile'        : CXXFile,
469                          'DVI'            : DVI,
470                          'Library'        : StaticLibrary,
471                          'StaticLibrary'  : StaticLibrary,
472                          'SharedLibrary'  : SharedLibrary,
473                          'Object'         : StaticObject,
474                          'StaticObject'   : StaticObject,
475                          'SharedObject'   : SharedObject,
476                          'PDF'            : PDF,
477                          'PostScript'     : PostScript,
478                          'Program'        : Program },
479         'SCANNERS'   : [CScan, FortranScan],
480         'LIBDIRPREFIX'          : '/LIBPATH:',
481         'LIBDIRSUFFIX'          : '',
482         'LIBLINKPREFIX'         : '',
483         'LIBLINKSUFFIX'         : '$LIBSUFFIX',
484         'LIBEMITTER'            : win32LibEmitter,
485         'INCPREFIX'             : '/I',
486         'INCSUFFIX'             : '',
487         'WIN32DEFPREFIX'        : '/def:',
488         'WIN32DEFSUFFIX'        : '.def',
489         'WIN32DLLPREFIX'        : '/out:',
490         'WIN32IMPLIBPREFIX'     : '/implib:',
491         'WIN32_INSERT_DEF'      : 0,
492         'ENV'        : {
493             'INCLUDE'  : include,
494             'LIB'      : lib,
495             'PATH'     : path,
496             },
497         }
498
499 def make_win32_env(version):
500     """
501     Build a dictionary of construction variables for a win32 platform.
502     ver - the version string of DevStudio to use (e.g. "6.0")
503     """
504     return make_win32_env_from_paths(get_msvc_path("include", version),
505                                      get_msvc_path("lib", version),
506                                      get_msvc_path("path", version)
507                                      + ";" + os.environ['PATH'])
508
509
510 if os.name == 'posix':
511     arcom = '$AR $ARFLAGS $TARGET $SOURCES'
512     ranlib = 'ranlib'
513     if SCons.Util.WhereIs(ranlib):
514         arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
515
516     ConstructionEnvironment = {
517         'CC'         : 'cc',
518         'CCFLAGS'    : '',
519         'CCCOM'      : '$CC $CCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
520         'SHCC'       : '$CC',
521         'SHCCFLAGS'  : '$CCFLAGS -fPIC',
522         'SHCCCOM'    : '$SHCC $SHCCFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
523         'CFILESUFFIX' : '.c',
524         'CXX'        : 'c++',
525         'CXXFLAGS'   : '$CCFLAGS',
526         'CXXCOM'     : '$CXX $CXXFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
527         'CXXFILESUFFIX' : '.cc',
528         'SHCXX'      : '$CXX',
529         'SHCXXFLAGS' : '$CXXFLAGS -fPIC',
530         'SHCXXCOM'   : '$SHCXX $SHCXXFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES',
531         'F77'        : 'g77',
532         'F77FLAGS'   : '',
533         'F77COM'     : '$F77 $F77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
534         'F77PPCOM'   : '$F77 $F77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
535         'SHF77FLAGS' : '$F77FLAGS -fPIC',
536         'SHF77COM'   : '$F77 $SHF77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
537         'SHF77PPCOM' : '$F77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
538         'SHF77'      : '$F77',
539         'SHF77FLAGS' : '$F77FLAGS -fPIC',
540         'SHF77COM'   : '$SHF77 $SHF77FLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
541         'SHF77PPCOM' : '$SHF77 $SHF77FLAGS $CPPFLAGS $_F77INCFLAGS -c -o $TARGET $SOURCES',
542         'LINK'       : '$CXX',
543         'LINKFLAGS'  : '',
544         'LINKCOM'    : '$LINK $LINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
545         'SHLINK'     : '$LINK',
546         'SHLINKFLAGS': '$LINKFLAGS -shared',
547         'SHLINKCOM'  : '$SHLINK $SHLINKFLAGS -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS',
548         'AR'         : 'ar',
549         'ARFLAGS'    : 'r',
550         'RANLIB'     : ranlib,
551         'RANLIBFLAGS' : '',
552         'ARCOM'      : arcom,
553         'LEX'        : 'lex',
554         'LEXFLAGS'   : '',
555         'LEXCOM'     : '$LEX $LEXFLAGS -t $SOURCES > $TARGET',
556         'YACC'       : 'yacc',
557         'YACCFLAGS'  : '',
558         'YACCCOM'    : '$YACC $YACCFLAGS -o $TARGET $SOURCES',
559         'TEX'        : 'tex',
560         'TEXFLAGS'   : '',
561         'TEXCOM'     : '$TEX $TEXFLAGS $SOURCES',
562         'LATEX'      : 'latex',
563         'LATEXFLAGS' : '',
564         'LATEXCOM'   : '$LATEX $LATEXFLAGS $SOURCES',
565         'DVIPDF'     : 'dvipdf',
566         'PDFCOM'     : '$DVIPDF $DVIPDFFLAGS $SOURCES $TARGET',
567         'PDFPREFIX'  : '',
568         'PDFSUFFIX'  : '.pdf',
569         'PDFTEX'     : 'pdftex',
570         'PDFTEXFLAGS' : '',
571         'PDFTEXCOM'  : '$PDFTEX $PDFTEXFLAGS $SOURCES $TARGET',
572         'PDFLATEX'   : 'pdflatex',
573         'PDFLATEXFLAGS' : '',
574         'PDFLATEXCOM' : '$PDFLATEX $PDFLATEXFLAGS $SOURCES $TARGET',
575         'DVIPS'      : 'dvips',
576         'PSCOM'      : '$DVIPS $DVIPSFLAGS -o $TARGET $SOURCES',
577         'PSPREFIX'   : '',
578         'PSSUFFIX'   : '.ps',
579         'BUILDERS'   : { 'Alias'          : Alias,
580                          'CFile'          : CFile,
581                          'CXXFile'        : CXXFile,
582                          'DVI'            : DVI,
583                          'Library'        : StaticLibrary,
584                          'StaticLibrary'  : StaticLibrary,
585                          'SharedLibrary'  : SharedLibrary,
586                          'Object'         : StaticObject,
587                          'StaticObject'   : StaticObject,
588                          'SharedObject'   : SharedObject,
589                          'PDF'            : PDF,
590                          'PostScript'     : PostScript,
591                          'Program'        : Program },
592         'SCANNERS'   : [CScan, FortranScan],
593         'LIBDIRPREFIX'          : '-L',
594         'LIBDIRSUFFIX'          : '',
595         'LIBLINKPREFIX'         : '-l',
596         'LIBLINKSUFFIX'         : '',
597         'INCPREFIX'             : '-I',
598         'INCSUFFIX'             : '',
599     }
600
601 elif os.name == 'nt':
602     versions = None
603     try:
604         versions = get_devstudio_versions()
605         ConstructionEnvironment = make_win32_env(versions[0]) #use highest version
606     except (SCons.Util.RegError, SCons.Errors.InternalError):
607         # Could not get the configured directories from the registry.
608         # However, the configured directories only appear if the user
609         # changes them from the default.  Therefore, we'll see if
610         # we can get the path to the MSDev base installation from
611         # the registry and deduce the default directories.
612         MVSdir = None
613         if versions:
614             MVSdir = get_msdev_dir(versions[0])
615         if MVSdir:
616             MVSVCdir = r'%s\VC98' % MVSdir
617             MVSCommondir = r'%s\Common' % MVSdir
618             try:
619                 extra_path = os.pathsep + os.environ['PATH']
620             except KeyError:
621                 extra_path = ''
622             ConstructionEnvironment = make_win32_env_from_paths(
623                 r'%s\atl\include;%s\mfc\include;%s\include' % (MVSVCdir, MVSVCdir, MVSVCdir),
624                 r'%s\mfc\lib;%s\lib' % (MVSVCdir, MVSVCdir),
625                 (r'%s\MSDev98\Bin;%s\Bin' % (MVSCommondir, MVSVCdir)) + extra_path)
626         else:
627             # The DevStudio environment variables don't exist,
628             # so just use the variables from the source environment.
629             MVSdir = r'C:\Program Files\Microsoft Visual Studio'
630             MVSVCdir = r'%s\VC98' % MVSdir
631             MVSCommondir = r'%s\Common' % MVSdir
632             try:
633                 include_path = os.environ['INCLUDE']
634             except KeyError:
635                 include_path = ''
636             try:
637                 lib_path = os.environ['LIB']
638             except KeyError:
639                 lib_path = ''
640             try:
641                 exe_path = os.environ['PATH']
642             except KeyError:
643                 exe_path = ''
644             ConstructionEnvironment = make_win32_env_from_paths(
645                 include_path,
646                 lib_path,
647                 exe_path)