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