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 # build web in out-www, so that scons is a drop-in replacement for make
188 # we can revise the entire web building when web is built with scons.
190 # Hmm: scons: *** maximum recursion limit exceeded
191 if 0 and 'web' in COMMAND_LINE_TARGETS:
192 web_kluts = 'out-scons' #env['out']
193 env['out'] = 'out-www'
195 absbuild = Dir (env['build']).abspath
196 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
197 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
200 config_hh = os.path.join (outdir, 'config.hh')
201 version_hh = os.path.join (outdir, 'version.hh')
203 env.Alias ('config', config_cache)
206 CacheDir (os.path.join (outdir, 'build-cache'))
208 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
209 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
210 env['prefix'] = run_prefix
212 prefix = env['prefix']
213 bindir = os.path.join (prefix, 'bin')
214 sharedir = os.path.join (prefix, 'share')
215 libdir = os.path.join (prefix, 'lib')
216 localedir = os.path.join (sharedir, 'locale')
217 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
218 sharedir_package = os.path.join (sharedir, package.name)
219 sharedir_package_version = os.path.join (sharedir_package, version)
220 lilypondprefix = sharedir_package_version
235 def configure (target, source, env):
236 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
237 def get_version (program):
238 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
239 pipe = os.popen (command)
240 output = pipe.read ()
243 v = re.sub (vre, '\\1', output)
244 return string.split (v, '.')
246 def test_program (lst, program, minimal, description, package):
247 sys.stdout.write ('Checking %s version... ' % program)
248 actual = get_version (program)
251 lst.append ((description, package, minimal, program,
254 sys.stdout.write (string.join (actual, '.'))
255 sys.stdout.write ('\n')
256 if actual < string.split (minimal, '.'):
257 lst.append ((description, package, minimal, program,
258 string.join (actual, '.')))
260 for i in ['bash', 'perl', 'python', 'sh']:
261 sys.stdout.write ('Checking for %s... ' % i)
263 key = string.upper (i)
268 sys.stdout.write ('not found: %s (using: %s)' \
271 sys.stdout.write ('\n')
274 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
275 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
276 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
277 test_program (required, 'guile-config', '1.6', 'GUILE development',
278 'libguile-dev or guile-devel')
279 # Do not use bison 1.50 and 1.75.
280 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
282 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
286 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
287 test_program (optional, 'guile', '1.6', 'GUILE scheme',
288 'libguile-dev or guile-devel')
289 test_program (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
291 test_program (optional, 'perl', '4.0',
292 'Perl practical efficient readonly language', 'perl')
293 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
295 def CheckYYCurrentBuffer (context):
296 context.Message ('Checking for yy_current_buffer... ')
297 ret = conf.TryCompile ("""using namespace std;
298 #include <FlexLexer.h>
299 class yy_flex_lexer: public yyFlexLexer
304 yy_current_buffer = 0;
310 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
311 : CheckYYCurrentBuffer })
314 'DIRSEP' : "'%s'" % os.sep,
315 'PATHSEP' : "'%s'" % os.pathsep,
316 'TOPLEVEL_VERSION' : '"' + version + '"',
317 'PACKAGE': '"' + package.name + '"',
318 'DATADIR' : '"' + sharedir + '"',
319 'LILYPOND_DATADIR' : '"' + sharedir_package + '"',
320 'LOCAL_LILYPOND_DATADIR' : '"' + sharedir_package_version + '"',
321 'LOCALEDIR' : '"' + localedir + '"',
323 conf.env.Append (DEFINES = defines)
325 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
326 PYTHON_INCLUDE = os.popen (command).read ()
327 env.Append (CPPPATH = PYTHON_INCLUDE)
329 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
331 if conf.CheckCHeader (i):
332 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
333 conf.env['DEFINES'][key] = 1
335 ccheaders = ('sstream',)
337 if conf.CheckCXXHeader (i):
338 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
339 conf.env['DEFINES'][key] = 1
341 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
343 if 0 or conf.CheckFunc (i):
344 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
345 conf.env['DEFINES'][key] = 1
347 if conf.CheckYYCurrentBuffer ():
348 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
350 if conf.CheckLib ('dl'):
353 if conf.CheckLib ('kpathsea'):
354 conf.env['DEFINES']['KPATHSEA'] = 1
357 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
358 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
359 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
360 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
362 #this could happen after flower...
363 env.ParseConfig ('guile-config compile')
365 #this could happen only for compiling pango-*
367 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
368 env.ParseConfig ('pkg-config --cflags --libs pango')
369 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
370 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
372 if conf.CheckLib ('pango-1.0',
373 'pango_fc_font_map_add_decoder_find_func'):
374 conf.env['DEFINES']['HAVE_PANGO_CVS'] = '1'
375 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
379 print '********************************'
380 print 'Please install required packages'
382 print '%s: %s-%s or newer (found: %s %s)' % i
387 print '*************************************'
388 print 'Consider installing optional packages'
390 print '%s: %s-%s or newer (found: %s %s)' % i
392 return conf.Finish ()
394 def config_header (target, source, env):
395 config = open (str (target[0]), 'w')
396 for i in list_sort (env['DEFINES'].keys ()):
397 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
399 env.Command (config_hh, config_cache, config_header)
415 if not d.has_key (lst[i]):
423 def uniquify_config_vars (env):
424 for i in config_vars:
425 if env.has_key (i) and type (env[i]) == type ([]):
426 env[i] = uniquify (env[i])
428 def save_config_cache (env):
429 ## FIXME: Is this smart, using option cache for saving
430 ## config.cache? I cannot seem to find the official method.
431 uniquify_config_vars (env)
432 opts.Save (config_cache, env)
434 if 'config' in COMMAND_LINE_TARGETS:
435 sys.stdout.write ('\n')
436 sys.stdout.write ('LilyPond configured')
437 sys.stdout.write ('\n')
438 sys.stdout.write ('now run')
439 sys.stdout.write ('\n')
440 sys.stdout.write (' scons [TARGET|DIR]...')
441 sys.stdout.write ('\n')
443 elif not env['checksums']:
444 # When using timestams, config.hh is NEW. The next
445 # build triggers recompilation of everything. Exiting
446 # here makes SCons use the actual timestamp for config.hh
447 # and prevents recompiling everything the next run.
448 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
449 sys.stdout.write ('Running %s ... ' % command)
450 sys.stdout.write ('\n')
451 s = os.system (command)
455 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
456 os.unlink (config_cache)
458 # scons: *** Calling Configure from Builders is not supported.
459 # env.Command (config_cache, None, configure)
460 if not os.path.exists (config_cache) \
461 or (os.stat ('SConstruct')[stat.ST_MTIME]
462 > os.stat (config_cache)[stat.ST_MTIME]):
463 env = configure (None, None, env)
464 save_config_cache (env)
465 elif env['checksums']:
466 # just save everything
467 save_config_cache (env)
469 #urg how does #/ subst work?
471 SConscript ('buildscripts/builder.py')
473 env.PrependENVPath ('PATH',
474 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
476 if os.environ.has_key ('TEXMF'):
477 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
478 env.Append (ENV = {'TEXMF' : '{$LILYPONDPREFIX,' \
479 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}' })
483 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
484 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
485 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
486 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
489 # post-option environment-update
493 lilypond_datadir = sharedir_package,
494 localedir = localedir,
495 local_lilypond_datadir = sharedir_package_version,
496 lilypondprefix = lilypondprefix,
497 sharedir_package = sharedir_package,
498 sharedir_doc_package = sharedir_doc_package,
499 sharedir_package_version = sharedir_package_version,
501 LILYPOND = BUILD_LILYPOND,
502 ABC2LY = BUILD_ABC2LY,
503 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
504 LILYPOND_BOOK_FORMAT = 'texi-html',
505 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
507 TEXI2DVI_PAPERSIZE = '@afourpaper',
508 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
509 DVIPS_PAPERSIZE = 'a4',
510 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
512 '-u+ec-mftrace.map'],
513 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
517 env.Append (CCFLAGS = ['-g', '-pipe'])
518 if env['optimising']:
519 env.Append (CCFLAGS = '-O2')
520 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
522 env.Append (CCFLAGS = ['-W', '-Wall'])
523 env.Append (CXXFLAGS = ['-Wconversion'])
526 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
529 env['__verbose'] = ' --verbose'
530 env['set__x'] = 'set -x;'
533 ## Explicit target and dependencies
535 if 'clean' in COMMAND_LINE_TARGETS:
536 # ugh: prevent reconfigure instead of clean
537 os.system ('touch %s' % config_cache)
539 command = sys.argv[0] + ' -c .'
540 sys.stdout.write ('Running %s ... ' % command)
541 sys.stdout.write ('\n')
542 s = os.system (command)
543 if os.path.exists (config_cache):
544 os.unlink (config_cache)
547 if 'realclean' in COMMAND_LINE_TARGETS:
548 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
549 sys.stdout.write ('Running %s ... ' % command)
550 sys.stdout.write ('\n')
551 s = os.system (command)
552 if os.path.exists (config_cache):
553 os.unlink (config_cache)
556 # Declare SConscript phonies
557 env.Alias ('minimal', config_cache)
558 env.Alias ('mf-essential', config_cache)
560 env.Alias ('minimal', ['lily', 'mf-essential'])
561 env.Alias ('all', ['minimal', 'mf', '.'])
562 # Do we want the doc/web separation?
565 'Documentation/user',
566 'Documentation/topdocs',
567 'Documentation/bibliography',
570 # Without target arguments, do minimal build
571 if not COMMAND_LINE_TARGETS:
572 env.Default (['minimal'])
574 # GNU Make rerouting compat:
575 env.Alias ('web', 'doc')
578 env.Command (version_hh, '#/VERSION',
579 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
581 # post-config environment update
583 run_prefix = run_prefix,
584 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
586 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),],
587 ##CPPPATH = [outdir, '#',], # do not read auto*'s header
588 CPPPATH = [outdir, ],
589 LILYPOND_PATH = ['.', '$srcdir/input',
590 '$srcdir/input/regression',
591 '$srcdir/input/test',
592 '$srcdir/input/tutorial',
593 '$srcdir/Documentation/user',
595 # os.path.join (absbuild, 'Documentation',
597 # os.path.join (absbuild, 'Documentation/user',
600 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
601 '$absbuild/Documentation/user/$out'],
604 def symlink_tree (target, source, env):
610 if not os.path.isdir (dir):
611 if os.path.exists (dir):
615 map (mkdir, string.split (dir, os.sep))
616 def symlink (src, dst):
618 dir = os.path.dirname (dst)
621 frm = os.path.join (srcdir, src[1:])
623 depth = len (string.split (dir, '/'))
624 if src.find ('@') > -1:
625 frm = os.path.join ('../' * depth,
626 string.replace (src, '@',
629 frm = os.path.join ('../' * depth, src,
632 frm = os.path.join (frm, os.path.basename (dst))
634 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
635 os.symlink (frm, os.path.basename (dst))
636 shutil.rmtree (run_prefix)
637 prefix = os.path.join (env['out'], 'usr')
638 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
641 # /$ := add dst file_name
642 (('python', 'lib/lilypond/python'),
643 ('lily/', 'bin/lilypond-bin'),
644 ('scripts/', 'bin/lilypond'),
645 ('scripts/', 'bin/lilypond-book'),
646 ('mf', 'share/lilypond/dvips'),
647 ('#ps', 'share/lilypond/tex/music-drawing-routines.ps'),
648 ('mf', 'share/lilypond/afm'),
649 ('mf', 'share/lilypond/tfm'),
650 ('#mf', 'share/lilypond/fonts/mf'),
651 ('mf', 'share/lilypond/fonts/afm'),
652 ('mf', 'share/lilypond/fonts/tfm'),
653 ('mf', 'share/lilypond/fonts/type1'),
654 ('#tex', 'share/lilypond/tex/source'),
655 ('mf', 'share/lilypond/tex/generate'),
656 ('#ly', 'share/lilypond/ly'),
657 ('#scm', 'share/lilypond/scm'),
658 ('#ps', 'share/lilypond/ps'),
659 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
660 ('elisp', 'share/lilypond/elisp')))
664 stamp = os.path.join (run_prefix, 'stamp')
665 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
666 env.Depends ('lily', stamp)
672 def cvs_entry_is_dir (line):
673 return line[0] == 'D' and line[-2] == '/'
675 def cvs_entry_is_file (line):
676 return line[0] == '/' and line[-2] == '/'
679 ENTRIES = os.path.join (dir, 'CVS/Entries')
680 if not os.path.exists (ENTRIES):
682 entries = open (ENTRIES).readlines ()
683 dir_entries = filter (cvs_entry_is_dir, entries)
684 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
686 return dirs + map (cvs_dirs, dirs)
689 ENTRIES = os.path.join (dir, 'CVS/Entries')
690 entries = open (ENTRIES).readlines ()
691 file_entries = filter (cvs_entry_is_file, entries)
692 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
693 return map (lambda x: os.path.join (dir, x), files)
695 def flatten (tree, lst):
696 if type (tree) == type ([]):
698 if type (i) == type ([]):
704 subdirs = flatten (cvs_dirs ('.'), [])
705 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
706 foo = map (lambda x: env.TXT (x + '.txt',
707 os.path.join ('Documentation/topdocs', x)),
709 txt_files = map (lambda x: x + '.txt', readme_files)
710 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
711 tar_base = package.name + '-' + version
712 tar_name = tar_base + '.tar.gz'
713 ball_prefix = os.path.join (outdir, tar_base)
714 tar_ball = os.path.join (outdir, tar_name)
716 dist_files = src_files + txt_files
717 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
718 map (lambda x: env.Depends (tar_ball, x), ball_files)
719 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
720 'ln $SOURCE $TARGET'), dist_files)
721 tar = env.Command (tar_ball, src_files,
722 ['rm -f $$(find $TARGET.dir -name .sconsign)',
723 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
724 env.Alias ('tar', tar)
726 dist_ball = os.path.join (package.release_dir, tar_name)
727 env.Command (dist_ball, tar_ball,
728 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
729 + 'ln $SOURCE $TARGET')
730 env.Depends ('dist', dist_ball)
731 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
732 patch = env.PATCH (patch_name, tar_ball)
733 env.Depends (patch_name, dist_ball)
734 env.Alias ('release', patch)
737 web_base = os.path.join (outdir, 'web')
738 web_ball = web_base + '.tar.gz'
739 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
740 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
741 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
742 env['web_path'] = web_path
743 web_list = os.path.join (outdir, 'weblist')
744 # compatible make heritits
745 # fixme: generate in $outdir is cwd/builddir
746 env.Command (web_list,
747 ## this is correct, but takes > 5min if you have a peder :-)
750 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
751 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
753 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
754 'cd $absbuild && find Documentation input $web_path \
756 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
757 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
758 # UGHR? all .html cruft in cwd goes into the web ball?
759 'cd $absbuild && ls *.html >> $TARGET',])
760 env.Command (web_ball, web_list,
761 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
762 env.Alias ('web', web_ball)
763 env.Alias ('roll-web', web_ball)
767 ETAGSFLAGS = ["""--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\1/'""",
768 """--regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\1/'"""])
769 # filter-out some files?
770 env.Command ('TAGS', src_files, 'etags $ETAGSFLAGS $SOURCES')
773 # Note: SConscripts are only needed in directories where something needs
774 # to be done, building or installing
776 if os.path.exists (os.path.join (d, 'SConscript')):
777 b = os.path.join (env['build'], d, env['out'])
778 # Support clean sourcetree build (--srcdir build)
780 if os.path.abspath (b) != os.path.abspath (d):
781 env.BuildDir (b, d, duplicate = 0)
784 env.Repository (os.path.join (env['build'], d,
786 SConscript (os.path.join (b, 'SConscript'))