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