]> git.lyx.org Git - features.git/blob - development/scons/scons_utils.py
Scons: initial msvc support, and separate fast_start and load_option options.
[features.git] / development / scons / scons_utils.py
1 # vi:filetype=python:expandtab:tabstop=2:shiftwidth=2
2 #
3 # file scons_utils.py
4
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10 #
11 # This file defines all the utility functions for the
12 # scons-based build system of lyx
13
14
15 import os, sys, re, shutil, glob
16 from SCons.Util import WhereIs
17
18 config_h = os.path.join('src', 'config.h')
19 config_content = ''
20
21 def writeToFile(filename, lines, append = False):
22   " utility function: write or append lines to filename "
23   if append:
24     file = open(filename, 'a')
25   else:
26     file = open(filename, 'w')
27   file.write(lines)
28   file.close()
29
30
31 def printEnvironment(env, keys=[]):
32   ''' used to check profile settings '''
33   dict = env.Dictionary()
34   if len(keys) == 0:
35     keys = dict.keys()
36   keys.sort()
37   for key in keys:
38     try:
39       # try to expand, but this is not always possible
40       print key, '=', env.subst('$'+key)
41     except:   
42       print '<<UNEXPANDED>>:', key, '=', dict[key]
43
44
45 def env_subst(target, source, env):
46   ''' subst variables in source by those in env, and output to target
47     source and target are scons File() objects
48
49     %key% (not key itself) is an indication of substitution
50   '''
51   assert len(target) == 1
52   assert len(source) == 1
53   target_file = file(str(target[0]), "w")
54   source_file = file(str(source[0]), "r")
55   
56   contents = source_file.read()
57   for k, v in env.items():
58     try:
59       val = env.subst('$'+k)
60       # temporary fix for the \Resource backslash problem
61       val = val.replace('\\', '/')
62       # multi-line replacement
63       val = val.replace('\n',r'\\n\\\n')
64       contents = re.sub('@'+k+'@', val, contents)
65       contents = re.sub('%'+k+'%', val, contents)
66     except:
67       pass
68   target_file.write(contents + "\n")
69   target_file.close()
70   #st = os.stat(str(source[0]))
71   #os.chmod(str(target[0]), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
72
73
74 #
75 # autoconf tests
76 #
77
78 def checkPkgConfig(conf, version):
79   ''' Return false if pkg_config does not exist, or is too old '''
80   conf.Message('Checking for pkg-config...')
81   ret = conf.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
82   conf.Result(ret)
83   return ret
84
85
86 def checkPackage(conf, pkg):
87   ''' check if pkg is under the control of conf '''
88   conf.Message('Checking for package %s...' % pkg)
89   ret = conf.TryAction("pkg-config --print-errors --exists %s" % pkg)[0]
90   conf.Result(ret)
91   return ret
92
93
94 def startConfigH():
95   ''' Write the first part of config.h '''
96   global config_content
97   config_content = '''/* src/config.h.  Generated by scon.  */
98
99 /* -*- C++ -*- */
100 /*
101  * \file config.h
102  * This file is part of LyX, the document processor.
103  * Licence details can be found in the file COPYING.
104  *
105  * This is the compilation configuration file for LyX.
106  * It was generated by scon.
107  * You might want to change some of the defaults if something goes wrong
108  * during the compilation.
109  */
110
111 #ifndef _CONFIG_H
112 #define _CONFIG_H
113 '''
114
115
116 def addToConfig(lines, newline=2):
117   ''' utility function: shortcut for appending lines to outfile
118     add newline at the end of lines.
119   '''
120   global config_content
121   if lines.strip() != '':
122     config_content += lines + '\n'*newline
123
124
125 def endConfigH(top_src_dir):
126   ''' Write the last part of config.h '''
127   global config_content
128   writeToFile(os.path.join(top_src_dir, config_h), config_content + 
129 '''/************************************************************
130  ** You should not need to change anything beyond this point */
131
132 #ifndef HAVE_STRERROR
133 #if defined(__cplusplus)
134 extern "C"
135 #endif
136 char * strerror(int n);
137 #endif
138
139 #ifdef HAVE_MKSTEMP
140 #ifndef HAVE_DECL_MKSTEMP
141 #if defined(__cplusplus)
142 extern "C"
143 #endif
144 int mkstemp(char*);
145 #endif
146 #endif
147
148 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
149 #  define USE_BOOST_FORMAT 1
150 #else
151 #  define USE_BOOST_FORMAT 0
152 #endif
153
154 #define BOOST_USER_CONFIG <config.h>
155
156 #if !defined(ENABLE_ASSERTIONS)
157 #  define BOOST_DISABLE_ASSERTS 1
158 #endif
159 #define BOOST_ENABLE_ASSERT_HANDLER 1
160
161 #define BOOST_DISABLE_THREADS 1
162 #define BOOST_NO_WREGEX 1
163 #define BOOST_NO_WSTRING 1
164
165 #ifdef __CYGWIN__
166 #  define BOOST_POSIX 1
167 #endif
168
169 #if defined(HAVE_NEWAPIS_H)
170 #  define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
171 #endif
172
173 #endif
174 ''')
175
176
177 #MKDIR_TAKES_ONE_ARG
178 def checkMkdirOneArg(conf):
179   check_mkdir_one_arg_source = """
180 #include <sys/stat.h>
181 int main()
182 {
183   mkdir("somedir");
184 }
185 """
186   conf.Message('Checking for the number of args for mkdir... ')
187   ret = conf.TryLink(check_mkdir_one_arg_source, '.c') or \
188     conf.TryLink('#include <unistd.h>' + check_mkdir_one_arg_source, '.c') or \
189     conf.TryLink('#include <direct.h>' + check_mkdir_one_arg_source, '.c')
190   if ret:
191     conf.Result('one')
192   else:
193     conf.Result('two')
194   return ret
195
196
197 # CXX_GLOBAL_CSTD
198 def checkCXXGlobalCstd(conf):
199   ''' Check the use of std::tolower or tolower '''
200   check_global_cstd_source = '''
201 #include <cctype>
202 using std::tolower;
203 int main()
204 {
205   return 0;
206 }
207 '''
208   conf.Message('Check for the use of global cstd... ')
209   ret = conf.TryLink(check_global_cstd_source, '.c')
210   conf.Result(ret)
211   return ret
212
213
214 # SELECT_TYPE_ARG1
215 # SELECT_TYPE_ARG234
216 # SELECT_TYPE_ARG5
217 def checkSelectArgType(conf):
218   ''' Adapted from autoconf '''
219   conf.Message('Checking for arg types for select... ')
220   for arg234 in ['fd_set *', 'int *', 'void *']:
221     for arg1 in ['int', 'size_t', 'unsigned long', 'unsigned']:
222       for arg5 in ['struct timeval *', 'const struct timeval *']:
223         check_select_source = '''
224 #if HAVE_SYS_SELECT_H
225 # include <sys/select.h>
226 #endif
227 #if HAVE_SYS_SOCKET_H
228 # include <sys/socket.h>
229 #endif
230 extern int select (%s, %s, %s, %s, %s);
231 int main()
232 {
233   return(0);
234 }
235 ''' % (arg1, arg234, arg234, arg234, arg5)
236         ret = conf.TryLink(check_select_source, '.c')
237         if ret:
238           conf.Result(ret)
239           return (arg1, arg234, arg5)
240   conf.Result('no (use default)')
241   return ('int', 'int *', 'struct timeval *')
242
243
244 def checkBoostLibraries(conf, lib, pathes):
245   ''' look for boost libraries '''
246   conf.Message('Checking for boost library %s... ' % lib)
247   for path in pathes:
248     # direct form: e.g. libboost_iostreams.a
249     if os.path.isfile(os.path.join(path, 'lib%s.a' % lib)):
250       conf.Result('yes')
251       return (path, lib)
252     # check things like libboost_iostreams-gcc.a
253     files = glob.glob(os.path.join(path, 'lib%s-*.a' % lib))
254     # if there are more than one, choose the first one
255     # FIXME: choose the best one.
256     if len(files) >= 1:
257       # get xxx-gcc from /usr/local/lib/libboost_xxx-gcc.a
258       conf.Result('yes')
259       return (path, files[0].split(os.sep)[-1][3:-2])
260   conf.Result('n')
261   return ('','')
262
263
264 def checkCommand(conf, cmd):
265   ''' check the existence of a command
266     return full path to the command, or none
267   '''
268   conf.Message('Checking for command %s...' % cmd)
269   res = WhereIs(cmd)
270   conf.Result(res is not None)
271   return res
272
273
274 def installCygwinLDScript(path):
275   ''' Install i386pe.x-no-rdata '''
276   ld_script = os.path.join(path, 'i386pe.x-no-rdata')
277   script = open(ld_script, 'w')
278   script.write('''/* specific linker script avoiding .rdata sections, for normal executables 
279 for a reference see 
280 http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
281 http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
282 */
283 OUTPUT_FORMAT(pei-i386)
284 SEARCH_DIR("/usr/i686-pc-cygwin/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");
285 ENTRY(_mainCRTStartup)
286 SECTIONS
287 {
288   .text  __image_base__ + __section_alignment__  :
289   {
290      *(.init)
291     *(.text)
292     *(SORT(.text$*))
293     *(.glue_7t)
294     *(.glue_7)
295      ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
296                         LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0);
297      ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
298                         LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0);
299      *(.fini)
300     /* ??? Why is .gcc_exc here?  */
301      *(.gcc_exc)
302     PROVIDE (etext = .);
303     *(.gcc_except_table)
304   }
305   /* The Cygwin32 library uses a section to avoid copying certain data
306      on fork.  This used to be named ".data".  The linker used
307      to include this between __data_start__ and __data_end__, but that
308      breaks building the cygwin32 dll.  Instead, we name the section
309      ".data_cygwin_nocopy" and explictly include it after __data_end__. */
310   .data BLOCK(__section_alignment__) :
311   {
312     __data_start__ = . ;
313     *(.data)
314     *(.data2)
315     *(SORT(.data$*))
316     *(.rdata)
317     *(SORT(.rdata$*))
318     *(.eh_frame)
319     ___RUNTIME_PSEUDO_RELOC_LIST__ = .;
320     __RUNTIME_PSEUDO_RELOC_LIST__ = .;
321     *(.rdata_runtime_pseudo_reloc)
322     ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
323     __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
324     __data_end__ = . ;
325     *(.data_cygwin_nocopy)
326   }
327   .rdata BLOCK(__section_alignment__) :
328   {
329   }
330   .pdata BLOCK(__section_alignment__) :
331   {
332     *(.pdata)
333   }
334   .bss BLOCK(__section_alignment__) :
335   {
336     __bss_start__ = . ;
337     *(.bss)
338     *(COMMON)
339     __bss_end__ = . ;
340   }
341   .edata BLOCK(__section_alignment__) :
342   {
343     *(.edata)
344   }
345   /DISCARD/ :
346   {
347     *(.debug$S)
348     *(.debug$T)
349     *(.debug$F)
350     *(.drectve)
351   }
352   .idata BLOCK(__section_alignment__) :
353   {
354     /* This cannot currently be handled with grouped sections.
355         See pe.em:sort_sections.  */
356     SORT(*)(.idata$2)
357     SORT(*)(.idata$3)
358     /* These zeroes mark the end of the import list.  */
359     LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
360     SORT(*)(.idata$4)
361     SORT(*)(.idata$5)
362     SORT(*)(.idata$6)
363     SORT(*)(.idata$7)
364   }
365   .CRT BLOCK(__section_alignment__) :
366   {
367     ___crt_xc_start__ = . ;
368     *(SORT(.CRT$XC*))  /* C initialization */
369     ___crt_xc_end__ = . ;
370     ___crt_xi_start__ = . ;
371     *(SORT(.CRT$XI*))  /* C++ initialization */
372     ___crt_xi_end__ = . ;
373     ___crt_xl_start__ = . ;
374     *(SORT(.CRT$XL*))  /* TLS callbacks */
375     /* ___crt_xl_end__ is defined in the TLS Directory support code */
376     ___crt_xp_start__ = . ;
377     *(SORT(.CRT$XP*))  /* Pre-termination */
378     ___crt_xp_end__ = . ;
379     ___crt_xt_start__ = . ;
380     *(SORT(.CRT$XT*))  /* Termination */
381     ___crt_xt_end__ = . ;
382   }
383   .tls BLOCK(__section_alignment__) :
384   {
385     ___tls_start__ = . ;
386     *(.tls)
387     *(.tls$)
388     *(SORT(.tls$*))
389     ___tls_end__ = . ;
390   }
391   .endjunk BLOCK(__section_alignment__) :
392   {
393     /* end is deprecated, don't use it */
394     PROVIDE (end = .);
395     PROVIDE ( _end = .);
396      __end__ = .;
397   }
398   .rsrc BLOCK(__section_alignment__) :
399   {
400     *(.rsrc)
401     *(SORT(.rsrc$*))
402   }
403   .reloc BLOCK(__section_alignment__) :
404   {
405     *(.reloc)
406   }
407   .stab BLOCK(__section_alignment__) (NOLOAD) :
408   {
409     *(.stab)
410   }
411   .stabstr BLOCK(__section_alignment__) (NOLOAD) :
412   {
413     *(.stabstr)
414   }
415   /* DWARF debug sections.
416      Symbols in the DWARF debugging sections are relative to the beginning
417      of the section.  Unlike other targets that fake this by putting the
418      section VMA at 0, the PE format will not allow it.  */
419   /* DWARF 1.1 and DWARF 2.  */
420   .debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
421   {
422     *(.debug_aranges)
423   }
424   .debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
425   {
426     *(.debug_pubnames)
427   }
428   /* DWARF 2.  */
429   .debug_info BLOCK(__section_alignment__) (NOLOAD) :
430   {
431     *(.debug_info) *(.gnu.linkonce.wi.*)
432   }
433   .debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
434   {
435     *(.debug_abbrev)
436   }
437   .debug_line BLOCK(__section_alignment__) (NOLOAD) :
438   {
439     *(.debug_line)
440   }
441   .debug_frame BLOCK(__section_alignment__) (NOLOAD) :
442   {
443     *(.debug_frame)
444   }
445   .debug_str BLOCK(__section_alignment__) (NOLOAD) :
446   {
447     *(.debug_str)
448   }
449   .debug_loc BLOCK(__section_alignment__) (NOLOAD) :
450   {
451     *(.debug_loc)
452   }
453   .debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
454   {
455     *(.debug_macinfo)
456   }
457   /* SGI/MIPS DWARF 2 extensions.  */
458   .debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
459   {
460     *(.debug_weaknames)
461   }
462   .debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
463   {
464     *(.debug_funcnames)
465   }
466   .debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
467   {
468     *(.debug_typenames)
469   }
470   .debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
471   {
472     *(.debug_varnames)
473   }
474   /* DWARF 3.  */
475   .debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
476   {
477     *(.debug_ranges)
478   }
479 }
480 ''')
481   script.close()
482   return(ld_script)
483
484
485 try:
486   # these will be used under win32
487   import win32file
488   import win32event
489   import win32process
490   import win32security
491 except:
492   # does not matter if it fails on other systems
493   pass
494
495
496 class loggedSpawn:
497   def __init__(self, env, logfile, longarg, info):
498     # save the spawn system
499     self.env = env
500     self.logfile = logfile
501     # clear the logfile (it may not exist)
502     if logfile != '':
503       # this will overwrite existing content.
504       writeToFile(logfile, info, append=False)
505     # 
506     self.longarg = longarg
507     # get hold of the old spawn? (necessary?)
508     self._spawn = env['SPAWN']
509
510   # define new SPAWN
511   def spawn(self, sh, escape, cmd, args, spawnenv):
512     # get command line
513     newargs = ' '.join(map(escape, args[1:]))
514     cmdline = cmd + " " + newargs
515     #
516     # if log is not empty, write to it
517     if self.logfile != '':
518       # this tend to be slow (?) but ensure correct output
519       # Note that cmdline may be long so I do not escape it
520       try:
521         # since this is not an essential operation, proceed if things go wrong here.
522         writeToFile(self.logfile, cmd + " " + ' '.join(args[1:]) + '\n', append=True)
523       except:
524         print "Warning: can not write to log file ", self.logfile
525     #
526     # if the command is not too long, use the old
527     if not self.longarg or len(cmdline) < 8000:
528       exit_code = self._spawn(sh, escape, cmd, args, spawnenv)
529     else:  
530       sAttrs = win32security.SECURITY_ATTRIBUTES()
531       StartupInfo = win32process.STARTUPINFO()
532       for var in spawnenv:
533         spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
534       # check for any special operating system commands
535       if cmd == 'del':
536         for arg in args[1:]:
537           win32file.DeleteFile(arg)
538         exit_code = 0
539       else:
540         # otherwise execute the command.
541         hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
542         win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
543         exit_code = win32process.GetExitCodeProcess(hProcess)
544         win32file.CloseHandle(hProcess);
545         win32file.CloseHandle(hThread);
546     return exit_code
547
548
549 def setLoggedSpawn(env, logfile = '', longarg=False, info=''):
550   ''' This function modify env and allow logging of
551     commands to a logfile. If the argument is too long
552     a win32 spawn will be used instead of the system one
553   '''
554   #
555   # create a new spwn object
556   ls = loggedSpawn(env, logfile, longarg, info)
557   # replace the old SPAWN by the new function
558   env['SPAWN'] = ls.spawn
559
560
561 ## def DistSources(env, node):
562 ##     env.DistFiles(_get_sources(env, node))
563 ## 
564 ## def DistFiles(env, files):
565 ##     assert isinstance(files, (list, tuple))
566 ##     DISTFILES = [env.File(fname) for fname in files]
567 ##     env.AppendUnique(DISTFILES=DISTFILES)
568 ## 
569 ## 
570 ## def make_distdir(target=None, source=None, env=None):
571 ##     distdir = env.subst('$DISTDIR')
572 ##     Execute(Delete(distdir))
573 ##     Execute(Mkdir(distdir))
574 ##     for fnode in env["DISTFILES"]:
575 ##         dirname, fname = os.path.split(str(fnode))
576 ##         if dirname:
577 ##             distdirname = os.path.join(distdir, dirname)
578 ##             if not os.path.exists(distdirname):
579 ##                 Execute(Mkdir(distdirname))
580 ##         Execute(Copy(os.path.join(distdir, dirname, fname), str(fnode)))
581 ##     
582 ## def make_dist(target=None, source=None, env=None):
583 ##     return Popen([env['TAR'], "-zcf",
584 ##                   env.subst("${PACKAGE}-${VERSION}.tar.gz"),
585 ##                   env.subst('$DISTDIR')]).wait()
586 ## 
587 ## def make_distcheck(target=None, source=None, env=None):
588 ##     distdir = env.subst('$DISTDIR')
589 ##     distcheckinstdir = tempfile.mkdtemp('', env.subst('${PACKAGE}-${VERSION}-instdir-'))
590 ##     distcheckdestdir = tempfile.mkdtemp('', env.subst('${PACKAGE}-${VERSION}-destdir-'))
591 ##     instdirs = [os.path.join(distcheckinstdir, d) for d in
592 ##                 'lib', 'share', 'bin', 'include']
593 ##     for dir_ in instdirs:
594 ##         Execute(Mkdir(dir_))
595 ## 
596 ##     cmd = env.subst("cd $DISTDIR && scons DESTDIR=%s prefix=%s"
597 ##                     " && scons check && scons install") %\
598 ##             (os.path.join(distcheckdestdir, ''), distcheckinstdir)
599 ##     status = Popen(cmd, shell=True).wait()
600 ##     if status:
601 ##         return status
602 ##     ## Check that inst dirs are empty (to catch cases of $DESTDIR not being honored
603 ##     for dir_ in instdirs:
604 ##         if os.listdir(dir_):
605 ##             raise SCons.Errors.BuildError(target, "%s not empy" % dir_)
606 ##     ## Check that something inside $DESTDIR was installed
607 ##     dir_ = os.path.join(distcheckdestdir, distcheckinstdir)
608 ##     if not os.path.exists(dir_):
609 ##         raise SCons.Errors.BuildError(target, "%s does not exist" % dir_)
610 ##     Execute(Delete(distcheckinstdir))
611 ##     Execute(Delete(distcheckdestdir))
612 ##     Execute(Delete(distdir))
613 ## 
614 ## def InstallWithDestDir(self, dir_, source):
615 ##     dir_ = '${DESTDIR}' + str(dir_)
616 ##     return SConsEnvironment.Install(self, dir_, source)
617 ## 
618 ## 
619 ## def InstallAsWithDestDir(self, target, source):
620 ##     target = '${DESTDIR}' + str(target)
621 ##     return SConsEnvironment.InstallAs(self, target, source)
622 ## 
623 ## def generate(env):
624 ##     env.EnsureSConsVersion(0, 96, 91)
625 ## 
626 ##     opts = Options(['options.cache'], ARGUMENTS)
627 ##     opts.Add(PathOption('prefix', 'Installation prefix', '/usr/local'))
628 ##     opts.Add(PathOption('exec_prefix', 'Installation prefix blah blah',
629 ##                         '$prefix'))
630 ##     opts.Add(PathOption('libdir',
631 ##         'Installation prefix for architecture dependent files', '$prefix/lib'))
632 ##     opts.Add(PathOption('includedir',
633 ##         'Installation prefix for C header files', '$prefix/include'))
634 ##     opts.Add(PathOption('datadir',
635 ##         'Installation prefix for architecture independent files', '$prefix/share'))
636 ##     opts.Add(PathOption('bindir', 'Installation prefix for programs', '$prefix/bin'))
637 ##     opts.Add(PathOption('DESTDIR', 'blah blah', None))
638 ##     opts.Update(env)
639 ##     opts.Save('options.cache', env)
640 ##     SConsEnvironment.Help(env, opts.GenerateHelpText(env))
641 ##     
642 ##     env.Append(CPPFLAGS=r' -DVERSION=\"$VERSION\"')
643 ##     env.Append(CCFLAGS=ARGUMENTS.get('CCFLAGS', '-g -O2'))
644 ## 
645 ##     env['GNOME_TESTS'] = dict(CheckPython=CheckPython,
646 ##                               CheckPythonHeaders=CheckPythonHeaders,
647 ##                               PkgCheckModules=PkgCheckModules)
648 ## 
649 ##     SConsEnvironment.DistSources = DistSources
650 ##     SConsEnvironment.DistFiles = DistFiles
651 ##     env['DISTDIR'] = "${PACKAGE}-${VERSION}"
652 ## 
653 ##     #env.Command(env.Dir("$DISTDIR"), None, make_distdir)
654 ##     
655 ##     distdir_alias = env.Alias("distdir", None, make_distdir)
656 ##     dist_alias = env.Alias("dist", None, make_dist)
657 ##     env.Depends(dist_alias, distdir_alias)
658 ##     distcheck_alias = env.Alias("distcheck", None, make_distcheck)
659 ##     env.Depends(distcheck_alias, distdir_alias)
660 ##     env.AlwaysBuild(env.Alias('check'))
661 ## 
662 ##     #env['TARFLAGS'] ='-c -z'
663 ##     #env['TARSUFFIX'] = '.tar.gz'
664 ##     #tar = env.Tar('${PACKAGE}-${VERSION}.tar.gz', "${DISTDIR}")
665 ##     #env.Depends(tar, distdir_alias)
666 ##     #print env['DEFAULT_TARGETS']
667 ## 
668 ##     #env.Depends(distdir_alias, "${DISTFILES}")
669 ##     #env.Alias('dist', tar)
670 ##     env.AlwaysBuild('dist')
671 ##     env.AlwaysBuild('distdir')
672 ##     env.AlwaysBuild('distcheck')
673 ##     env.DistFiles(['SConstruct', 'scons/gnome.py'])
674 ## 
675 ##     env['BUILDERS']['EnvSubstFile'] = SCons.Builder.Builder(action=env_subst)
676 ## 
677 ##     SConsEnvironment.PythonByteCompile = env.Action(byte_compile_python)
678 ##     
679 ##     env.Install = new.instancemethod(InstallWithDestDir, env, env.__class__)
680 ##     env.InstallAs = new.instancemethod(InstallAsWithDestDir, env, env.__class__)
681 ## 
682 ## 
683 ##  
684