4 Experimental scons (www.scons.org) building.
10 build from source directory ./TARGET (not recursive)
14 scons [config] # configure
19 run=$(pwd)/out-scons/usr
20 export LOCALE=$run/share/locale
21 export TEXMF='{'$run/share/lilypond,$(kpsexpand '$TEXMF')'}'
24 #optionally, if you do not use custom.py below
25 #export LILYPONDPREFIX=$run/share/lilypond
27 lilypond-bin input/simple
30 scons mf-essential # build minimal mf stuff
32 scons doc # build web doc
33 scons config # reconfigure
34 scons install # install
38 scons / # build *everything* (including installation)
40 Options (see scons -h)
41 scons build=DIR # clean srcdir build, output below DIR
42 scons out=DIR # write output for alterative config to DIR
56 os.path.join (os.getcwd (), '=install')
57 prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
65 # * more program configure tests (mfont, ...?)
67 # * split doc target: doc input examples mutopia?
69 # * more fine-grained config.hh -- move lilypondprefix to version.hh?
70 # - config.hh: changes after system upgrades, affects all files
71 # - version.hh: prefix, version etc? affects few
73 # - what about GUILE_*_VERSION, seems to be the major culprit,
74 # for config.hh dependency escalation. Is the lily-guile.hh
75 # workaround necessary at all for GUILE > 1.5?
77 # * grep FIXME $(find . -name 'S*t')
89 EnsureSConsVersion (0, 95)
92 scons [KEY=VALUE].. [TARGET|DIR]..
94 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
95 realclean, release, tar, TAGS
100 config_cache = 'scons.cache'
116 # Put your favourite stuff in custom.py
117 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
118 opts.Add ('prefix', 'Install prefix', '/usr/')
119 opts.Add ('out', 'Output directory', 'out-scons')
120 opts.Add ('build', 'Build directory', '.')
121 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
123 BoolOption ('warnings', 'compile with -Wall and similiar',
125 BoolOption ('debugging', 'compile with debugging symbols',
127 BoolOption ('optimising', 'compile with optimising',
129 BoolOption ('shared', 'build shared libraries',
131 BoolOption ('static', 'build static libraries',
133 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
135 BoolOption ('verbose', 'run commands with verbose flag',
137 BoolOption ('checksums', 'use checksums instead of timestamps',
141 srcdir = Dir ('.').srcnode ().abspath
143 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
145 package = packagepython.Package (srcdir)
146 version = packagepython.version_tuple_to_str (package.version)
148 ENV = { 'PATH' : os.environ['PATH'] }
149 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH']:
150 if os.environ.has_key (key):
151 ENV[key] = os.environ[key]
157 PERL = '/usr/bin/perl',
158 PYTHON = '/usr/bin/python',
161 MAKEINFO = 'LANG= makeinfo',
162 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
164 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
165 'usr/pkg/gnome/lib'),
166 os.path.join (os.environ['HOME'],
167 'usr/pkg/pango/lib')],
170 TOPLEVEL_VERSION = version,
173 # Add all config_vars to opts, so that they will be read and saved
174 # together with the other configure options.
175 map (lambda x: opts.AddOptions ((x,)), config_vars)
177 Help (usage + opts.GenerateHelpText (env))
181 # Using content checksums prevents rebuilds after [re]configure if
182 # config.hh has not changed.
184 SetOption ('max_drift', 0)
185 TargetSignatures ("content")
187 absbuild = Dir (env['build']).abspath
188 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
189 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
192 config_hh = os.path.join (outdir, 'config.hh')
193 version_hh = os.path.join (outdir, 'version.hh')
195 env.Alias ('config', config_cache)
197 cachedir = os.path.join (outdir, 'build-cache')
199 if not os.path.exists(cachedir):
200 os.makedirs(cachedir)
202 CacheDir (os.path.join (outdir, 'build-cache'))
204 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
205 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
206 env['prefix'] = run_prefix
208 prefix = env['prefix']
209 bindir = os.path.join (prefix, 'bin')
210 sharedir = os.path.join (prefix, 'share')
211 libdir = os.path.join (prefix, 'lib')
212 localedir = os.path.join (sharedir, 'locale')
213 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
214 sharedir_package = os.path.join (sharedir, package.name)
215 sharedir_package_version = os.path.join (sharedir_package, version)
216 lilypondprefix = sharedir_package_version
231 def configure (target, source, env):
232 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
233 def get_version (program):
234 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
235 pipe = os.popen (command)
236 output = pipe.read ()
239 v = re.sub (vre, '\\1', output)
240 return string.split (v, '.')
242 def test_program (lst, program, minimal, description, package):
243 sys.stdout.write ('Checking %s version... ' % program)
244 actual = get_version (program)
247 lst.append ((description, package, minimal, program,
250 sys.stdout.write (string.join (actual, '.'))
251 sys.stdout.write ('\n')
252 if actual < string.split (minimal, '.'):
253 lst.append ((description, package, minimal, program,
254 string.join (actual, '.')))
256 for i in ['bash', 'perl', 'python', 'sh']:
257 sys.stdout.write ('Checking for %s... ' % i)
259 key = string.upper (i)
264 sys.stdout.write ('not found: %s (using: %s)' \
267 sys.stdout.write ('\n')
270 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
271 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
272 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
273 test_program (required, 'guile-config', '1.6', 'GUILE development',
274 'libguile-dev or guile-devel')
275 # Do not use bison 1.50 and 1.75.
276 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
278 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
282 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
283 test_program (optional, 'guile', '1.6', 'GUILE scheme',
284 'libguile-dev or guile-devel')
285 test_program (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
287 test_program (optional, 'perl', '4.0',
288 'Perl practical efficient readonly language', 'perl')
289 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
291 def CheckYYCurrentBuffer (context):
292 context.Message ('Checking for yy_current_buffer... ')
293 ret = conf.TryCompile ("""using namespace std;
294 #include <FlexLexer.h>
295 class yy_flex_lexer: public yyFlexLexer
300 yy_current_buffer = 0;
306 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
307 : CheckYYCurrentBuffer })
310 'DIRSEP' : "'%s'" % os.sep,
311 'PATHSEP' : "'%s'" % os.pathsep,
312 'TOPLEVEL_VERSION' : '"' + version + '"',
313 'PACKAGE': '"' + package.name + '"',
314 'DATADIR' : '"' + sharedir + '"',
315 'LILYPOND_DATADIR' : '"' + sharedir_package + '"',
316 'LOCAL_LILYPOND_DATADIR' : '"' + sharedir_package_version + '"',
317 'LOCALEDIR' : '"' + localedir + '"',
319 conf.env.Append (DEFINES = defines)
321 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
322 PYTHON_INCLUDE = os.popen (command).read ()
323 env.Append (CPPPATH = PYTHON_INCLUDE)
325 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
327 if conf.CheckCHeader (i):
328 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
329 conf.env['DEFINES'][key] = 1
331 ccheaders = ('sstream',)
333 if conf.CheckCXXHeader (i):
334 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
335 conf.env['DEFINES'][key] = 1
337 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
339 if 0 or conf.CheckFunc (i):
340 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
341 conf.env['DEFINES'][key] = 1
343 if conf.CheckYYCurrentBuffer ():
344 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
346 if conf.CheckLib ('dl'):
349 if conf.CheckLib ('kpathsea'):
350 conf.env['DEFINES']['KPATHSEA'] = 1
353 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
354 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
355 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
356 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
358 #this could happen after flower...
359 env.ParseConfig ('guile-config compile')
361 #this could happen only for compiling pango-*
363 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
364 env.ParseConfig ('pkg-config --cflags --libs pango')
365 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
366 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
368 if conf.CheckLib ('pango-1.0',
369 'pango_fc_font_map_add_decoder_find_func'):
370 conf.env['DEFINES']['HAVE_PANGO_CVS'] = '1'
371 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
375 print '********************************'
376 print 'Please install required packages'
378 print '%s: %s-%s or newer (found: %s %s)' % i
383 print '*************************************'
384 print 'Consider installing optional packages'
386 print '%s: %s-%s or newer (found: %s %s)' % i
388 return conf.Finish ()
390 def config_header (target, source, env):
391 config = open (str (target[0]), 'w')
392 for i in list_sort (env['DEFINES'].keys ()):
393 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
395 env.Command (config_hh, config_cache, config_header)
411 if not d.has_key (lst[i]):
419 def uniquify_config_vars (env):
420 for i in config_vars:
421 if env.has_key (i) and type (env[i]) == type ([]):
422 env[i] = uniquify (env[i])
424 def save_config_cache (env):
425 ## FIXME: Is this smart, using option cache for saving
426 ## config.cache? I cannot seem to find the official method.
427 uniquify_config_vars (env)
428 opts.Save (config_cache, env)
430 if 'config' in COMMAND_LINE_TARGETS:
431 sys.stdout.write ('\n')
432 sys.stdout.write ('LilyPond configured')
433 sys.stdout.write ('\n')
434 sys.stdout.write ('now run')
435 sys.stdout.write ('\n')
436 sys.stdout.write (' scons [TARGET|DIR]...')
437 sys.stdout.write ('\n')
439 elif not env['checksums']:
440 # When using timestams, config.hh is NEW. The next
441 # build triggers recompilation of everything. Exiting
442 # here makes SCons use the actual timestamp for config.hh
443 # and prevents recompiling everything the next run.
444 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
445 sys.stdout.write ('Running %s ... ' % command)
446 sys.stdout.write ('\n')
447 s = os.system (command)
451 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
452 os.unlink (config_cache)
454 # scons: *** Calling Configure from Builders is not supported.
455 # env.Command (config_cache, None, configure)
456 if not os.path.exists (config_cache) \
457 or (os.stat ('SConstruct')[stat.ST_MTIME]
458 > os.stat (config_cache)[stat.ST_MTIME]):
459 env = configure (None, None, env)
460 save_config_cache (env)
461 elif env['checksums']:
462 # just save everything
463 save_config_cache (env)
465 #urg how does #/ subst work?
467 SConscript ('buildscripts/builder.py')
469 env.PrependENVPath ('PATH',
470 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
472 if os.environ.has_key ('TEXMF'):
473 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
475 'TEXMF' : '{$LILYPONDPREFIX,' \
476 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
477 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
480 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
481 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
482 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
483 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
486 # post-option environment-update
490 lilypond_datadir = sharedir_package,
491 localedir = localedir,
492 local_lilypond_datadir = sharedir_package_version,
493 lilypondprefix = lilypondprefix,
494 sharedir_package = sharedir_package,
495 sharedir_doc_package = sharedir_doc_package,
496 sharedir_package_version = sharedir_package_version,
498 LILYPOND = BUILD_LILYPOND,
499 ABC2LY = BUILD_ABC2LY,
500 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
501 LILYPOND_BOOK_FORMAT = 'texi-html',
502 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
504 TEXI2DVI_PAPERSIZE = '@afourpaper',
505 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
506 DVIPS_PAPERSIZE = 'a4',
507 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
509 '-u+ec-mftrace.map'],
510 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
514 env.Append (CCFLAGS = ['-g', '-pipe'])
515 if env['optimising']:
516 env.Append (CCFLAGS = '-O2')
517 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
519 env.Append (CCFLAGS = ['-W', '-Wall'])
520 env.Append (CXXFLAGS = ['-Wconversion'])
523 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
526 env['__verbose'] = ' --verbose'
527 env['set__x'] = 'set -x;'
530 ## Explicit target and dependencies
532 if 'clean' in COMMAND_LINE_TARGETS:
533 # ugh: prevent reconfigure instead of clean
534 os.system ('touch %s' % config_cache)
536 command = sys.argv[0] + ' -c .'
537 sys.stdout.write ('Running %s ... ' % command)
538 sys.stdout.write ('\n')
539 s = os.system (command)
540 if os.path.exists (config_cache):
541 os.unlink (config_cache)
544 if 'realclean' in COMMAND_LINE_TARGETS:
545 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
546 sys.stdout.write ('Running %s ... ' % command)
547 sys.stdout.write ('\n')
548 s = os.system (command)
549 if os.path.exists (config_cache):
550 os.unlink (config_cache)
553 # Declare SConscript phonies
554 env.Alias ('minimal', config_cache)
555 env.Alias ('mf-essential', config_cache)
557 env.Alias ('minimal', ['lily', 'mf-essential'])
558 env.Alias ('all', ['minimal', 'mf', '.'])
559 # Do we want the doc/web separation?
562 'Documentation/user',
563 'Documentation/topdocs',
564 'Documentation/bibliography',
567 # Without target arguments, do minimal build
568 if not COMMAND_LINE_TARGETS:
569 env.Default (['minimal'])
571 # GNU Make rerouting compat:
572 env.Alias ('web', 'doc')
575 env.Command (version_hh, '#/VERSION',
576 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
578 # post-config environment update
580 run_prefix = run_prefix,
581 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
583 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),],
584 ##CPPPATH = [outdir, '#',], # do not read auto*'s header
585 CPPPATH = [outdir, ],
586 LILYPOND_PATH = ['.', '$srcdir/input',
587 '$srcdir/input/regression',
588 '$srcdir/input/test',
589 '$srcdir/input/tutorial',
590 '$srcdir/Documentation/user',
592 # os.path.join (absbuild, 'Documentation',
594 # os.path.join (absbuild, 'Documentation/user',
597 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
598 '$absbuild/Documentation/user/$out'],
601 def symlink_tree (target, source, env):
607 if not os.path.isdir (dir):
608 if os.path.exists (dir):
612 map (mkdir, string.split (dir, os.sep))
613 def symlink (src, dst):
615 dir = os.path.dirname (dst)
618 frm = os.path.join (srcdir, src[1:])
620 depth = len (string.split (dir, '/'))
621 if src.find ('@') > -1:
622 frm = os.path.join ('../' * depth,
623 string.replace (src, '@',
626 frm = os.path.join ('../' * depth, src,
629 frm = os.path.join (frm, os.path.basename (dst))
631 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
632 os.symlink (frm, os.path.basename (dst))
633 shutil.rmtree (run_prefix)
634 prefix = os.path.join (env['out'], 'usr')
635 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
638 # /$ := add dst file_name
639 (('python', 'lib/lilypond/python'),
640 ('lily/', 'bin/lilypond-bin'),
641 ('scripts/', 'bin/lilypond'),
642 ('scripts/', 'bin/lilypond-book'),
643 ('mf', 'share/lilypond/dvips'),
644 ('#ps', 'share/lilypond/tex/music-drawing-routines.ps'),
645 ('mf', 'share/lilypond/afm'),
646 ('mf', 'share/lilypond/tfm'),
647 ('#mf', 'share/lilypond/fonts/mf'),
648 ('mf', 'share/lilypond/fonts/afm'),
649 ('mf', 'share/lilypond/fonts/tfm'),
650 ('mf', 'share/lilypond/fonts/type1'),
651 ('#tex', 'share/lilypond/tex/source'),
652 ('mf', 'share/lilypond/tex/generate'),
653 ('#ly', 'share/lilypond/ly'),
654 ('#scm', 'share/lilypond/scm'),
655 ('#ps', 'share/lilypond/ps'),
656 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
657 ('elisp', 'share/lilypond/elisp')))
661 stamp = os.path.join (run_prefix, 'stamp')
662 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
663 env.Depends ('lily', stamp)
669 def cvs_entry_is_dir (line):
670 return line[0] == 'D' and line[-2] == '/'
672 def cvs_entry_is_file (line):
673 return line[0] == '/' and line[-2] == '/'
676 ENTRIES = os.path.join (dir, 'CVS/Entries')
677 if not os.path.exists (ENTRIES):
679 entries = open (ENTRIES).readlines ()
680 dir_entries = filter (cvs_entry_is_dir, entries)
681 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
683 return dirs + map (cvs_dirs, dirs)
686 ENTRIES = os.path.join (dir, 'CVS/Entries')
687 entries = open (ENTRIES).readlines ()
688 file_entries = filter (cvs_entry_is_file, entries)
689 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
690 return map (lambda x: os.path.join (dir, x), files)
692 def flatten (tree, lst):
693 if type (tree) == type ([]):
695 if type (i) == type ([]):
701 subdirs = flatten (cvs_dirs ('.'), [])
702 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
703 foo = map (lambda x: env.TXT (x + '.txt',
704 os.path.join ('Documentation/topdocs', x)),
706 txt_files = map (lambda x: x + '.txt', readme_files)
707 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
708 tar_base = package.name + '-' + version
709 tar_name = tar_base + '.tar.gz'
710 ball_prefix = os.path.join (outdir, tar_base)
711 tar_ball = os.path.join (outdir, tar_name)
713 dist_files = src_files + txt_files
714 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
715 map (lambda x: env.Depends (tar_ball, x), ball_files)
716 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
717 'ln $SOURCE $TARGET'), dist_files)
718 tar = env.Command (tar_ball, src_files,
719 ['rm -f $$(find $TARGET.dir -name .sconsign)',
720 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
721 env.Alias ('tar', tar)
723 dist_ball = os.path.join (package.release_dir, tar_name)
724 env.Command (dist_ball, tar_ball,
725 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
726 + 'ln $SOURCE $TARGET')
727 env.Depends ('dist', dist_ball)
728 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
729 patch = env.PATCH (patch_name, tar_ball)
730 env.Depends (patch_name, dist_ball)
731 env.Alias ('release', patch)
734 web_base = os.path.join (outdir, 'web')
735 web_ball = web_base + '.tar.gz'
736 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
737 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
738 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
739 env['web_path'] = web_path
740 web_list = os.path.join (outdir, 'weblist')
741 # compatible make heritits
742 # fixme: generate in $outdir is cwd/builddir
743 env.Command (web_list,
744 ## this is correct, but takes > 5min if you have a peder :-)
747 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
748 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
749 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
750 'cd $absbuild && find Documentation input $web_path \
752 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
753 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
754 'cd $absbuild && ls *.html >> $TARGET',])
755 env.Command (web_ball, web_list,
756 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
757 #env.Alias ('web', web_ball)
758 www_base = os.path.join (outdir, 'www')
759 www_ball = www_base + '.tar.gz'
760 env.Command (www_ball, web_ball,
762 'mkdir -p $absbuild/$out/tmp',
763 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
764 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"; do mv $i out-www; done',
765 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
766 env.Alias ('web', www_ball)
770 ETAGSFLAGS = ["""--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\1/'""",
771 """--regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\1/'"""])
772 # filter-out some files?
773 env.Command ('TAGS', src_files, 'etags $ETAGSFLAGS $SOURCES')
776 # Note: SConscripts are only needed in directories where something needs
777 # to be done, building or installing
779 if os.path.exists (os.path.join (d, 'SConscript')):
780 b = os.path.join (env['build'], d, env['out'])
781 # Support clean sourcetree build (--srcdir build)
783 if os.path.abspath (b) != os.path.abspath (d):
784 env.BuildDir (b, d, duplicate = 0)
785 SConscript (os.path.join (b, 'SConscript'))