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