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)
198 CacheDir (os.path.join (outdir, 'build-cache'))
200 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
201 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
202 env['prefix'] = run_prefix
204 prefix = env['prefix']
205 bindir = os.path.join (prefix, 'bin')
206 sharedir = os.path.join (prefix, 'share')
207 libdir = os.path.join (prefix, 'lib')
208 localedir = os.path.join (sharedir, 'locale')
209 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
210 sharedir_package = os.path.join (sharedir, package.name)
211 sharedir_package_version = os.path.join (sharedir_package, version)
212 lilypondprefix = sharedir_package_version
227 def configure (target, source, env):
228 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
229 def get_version (program):
230 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
231 pipe = os.popen (command)
232 output = pipe.read ()
235 v = re.sub (vre, '\\1', output)
236 return string.split (v, '.')
238 def test_program (lst, program, minimal, description, package):
239 sys.stdout.write ('Checking %s version... ' % program)
240 actual = get_version (program)
243 lst.append ((description, package, minimal, program,
246 sys.stdout.write (string.join (actual, '.'))
247 sys.stdout.write ('\n')
248 if actual < string.split (minimal, '.'):
249 lst.append ((description, package, minimal, program,
250 string.join (actual, '.')))
252 for i in ['bash', 'perl', 'python', 'sh']:
253 sys.stdout.write ('Checking for %s... ' % i)
255 key = string.upper (i)
260 sys.stdout.write ('not found: %s (using: %s)' \
263 sys.stdout.write ('\n')
266 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
267 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
268 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
269 test_program (required, 'guile-config', '1.6', 'GUILE development',
270 'libguile-dev or guile-devel')
271 # Do not use bison 1.50 and 1.75.
272 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
274 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
278 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
279 test_program (optional, 'guile', '1.6', 'GUILE scheme',
280 'libguile-dev or guile-devel')
281 test_program (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
283 test_program (optional, 'perl', '4.0',
284 'Perl practical efficient readonly language', 'perl')
285 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
287 def CheckYYCurrentBuffer (context):
288 context.Message ('Checking for yy_current_buffer... ')
289 ret = conf.TryCompile ("""using namespace std;
290 #include <FlexLexer.h>
291 class yy_flex_lexer: public yyFlexLexer
296 yy_current_buffer = 0;
302 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
303 : CheckYYCurrentBuffer })
306 'DIRSEP' : "'%s'" % os.sep,
307 'PATHSEP' : "'%s'" % os.pathsep,
308 'TOPLEVEL_VERSION' : '"' + version + '"',
309 'PACKAGE': '"' + package.name + '"',
310 'DATADIR' : '"' + sharedir + '"',
311 'LILYPOND_DATADIR' : '"' + sharedir_package + '"',
312 'LOCAL_LILYPOND_DATADIR' : '"' + sharedir_package_version + '"',
313 'LOCALEDIR' : '"' + localedir + '"',
315 conf.env.Append (DEFINES = defines)
317 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
318 PYTHON_INCLUDE = os.popen (command).read ()
319 env.Append (CPPPATH = PYTHON_INCLUDE)
321 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
323 if conf.CheckCHeader (i):
324 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
325 conf.env['DEFINES'][key] = 1
327 ccheaders = ('sstream',)
329 if conf.CheckCXXHeader (i):
330 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
331 conf.env['DEFINES'][key] = 1
333 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
335 if 0 or conf.CheckFunc (i):
336 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
337 conf.env['DEFINES'][key] = 1
339 if conf.CheckYYCurrentBuffer ():
340 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
342 if conf.CheckLib ('dl'):
345 if conf.CheckLib ('kpathsea'):
346 conf.env['DEFINES']['KPATHSEA'] = 1
349 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
350 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
351 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
352 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
354 #this could happen after flower...
355 env.ParseConfig ('guile-config compile')
357 #this could happen only for compiling pango-*
359 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
360 env.ParseConfig ('pkg-config --cflags --libs pango')
361 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
362 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
364 if conf.CheckLib ('pango-1.0',
365 'pango_fc_font_map_add_decoder_find_func'):
366 conf.env['DEFINES']['HAVE_PANGO_CVS'] = '1'
367 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
371 print '********************************'
372 print 'Please install required packages'
374 print '%s: %s-%s or newer (found: %s %s)' % i
379 print '*************************************'
380 print 'Consider installing optional packages'
382 print '%s: %s-%s or newer (found: %s %s)' % i
384 return conf.Finish ()
386 def config_header (target, source, env):
387 config = open (str (target[0]), 'w')
388 for i in list_sort (env['DEFINES'].keys ()):
389 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
391 env.Command (config_hh, config_cache, config_header)
407 if not d.has_key (lst[i]):
415 def uniquify_config_vars (env):
416 for i in config_vars:
417 if env.has_key (i) and type (env[i]) == type ([]):
418 env[i] = uniquify (env[i])
420 def save_config_cache (env):
421 ## FIXME: Is this smart, using option cache for saving
422 ## config.cache? I cannot seem to find the official method.
423 uniquify_config_vars (env)
424 opts.Save (config_cache, env)
426 if 'config' in COMMAND_LINE_TARGETS:
427 sys.stdout.write ('\n')
428 sys.stdout.write ('LilyPond configured')
429 sys.stdout.write ('\n')
430 sys.stdout.write ('now run')
431 sys.stdout.write ('\n')
432 sys.stdout.write (' scons [TARGET|DIR]...')
433 sys.stdout.write ('\n')
435 elif not env['checksums']:
436 # When using timestams, config.hh is NEW. The next
437 # build triggers recompilation of everything. Exiting
438 # here makes SCons use the actual timestamp for config.hh
439 # and prevents recompiling everything the next run.
440 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
441 sys.stdout.write ('Running %s ... ' % command)
442 sys.stdout.write ('\n')
443 s = os.system (command)
447 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
448 os.unlink (config_cache)
450 # scons: *** Calling Configure from Builders is not supported.
451 # env.Command (config_cache, None, configure)
452 if not os.path.exists (config_cache) \
453 or (os.stat ('SConstruct')[stat.ST_MTIME]
454 > os.stat (config_cache)[stat.ST_MTIME]):
455 env = configure (None, None, env)
456 save_config_cache (env)
457 elif env['checksums']:
458 # just save everything
459 save_config_cache (env)
461 #urg how does #/ subst work?
463 SConscript ('buildscripts/builder.py')
465 env.PrependENVPath ('PATH',
466 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
468 if os.environ.has_key ('TEXMF'):
469 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
471 'TEXMF' : '{$LILYPONDPREFIX,' \
472 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
473 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
476 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
477 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
478 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
479 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
482 # post-option environment-update
486 lilypond_datadir = sharedir_package,
487 localedir = localedir,
488 local_lilypond_datadir = sharedir_package_version,
489 lilypondprefix = lilypondprefix,
490 sharedir_package = sharedir_package,
491 sharedir_doc_package = sharedir_doc_package,
492 sharedir_package_version = sharedir_package_version,
494 LILYPOND = BUILD_LILYPOND,
495 ABC2LY = BUILD_ABC2LY,
496 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
497 LILYPOND_BOOK_FORMAT = 'texi-html',
498 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
500 TEXI2DVI_PAPERSIZE = '@afourpaper',
501 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
502 DVIPS_PAPERSIZE = 'a4',
503 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
505 '-u+ec-mftrace.map'],
506 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
510 env.Append (CCFLAGS = ['-g', '-pipe'])
511 if env['optimising']:
512 env.Append (CCFLAGS = '-O2')
513 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
515 env.Append (CCFLAGS = ['-W', '-Wall'])
516 env.Append (CXXFLAGS = ['-Wconversion'])
519 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
522 env['__verbose'] = ' --verbose'
523 env['set__x'] = 'set -x;'
526 ## Explicit target and dependencies
528 if 'clean' in COMMAND_LINE_TARGETS:
529 # ugh: prevent reconfigure instead of clean
530 os.system ('touch %s' % config_cache)
532 command = sys.argv[0] + ' -c .'
533 sys.stdout.write ('Running %s ... ' % command)
534 sys.stdout.write ('\n')
535 s = os.system (command)
536 if os.path.exists (config_cache):
537 os.unlink (config_cache)
540 if 'realclean' in COMMAND_LINE_TARGETS:
541 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
542 sys.stdout.write ('Running %s ... ' % command)
543 sys.stdout.write ('\n')
544 s = os.system (command)
545 if os.path.exists (config_cache):
546 os.unlink (config_cache)
549 # Declare SConscript phonies
550 env.Alias ('minimal', config_cache)
551 env.Alias ('mf-essential', config_cache)
553 env.Alias ('minimal', ['lily', 'mf-essential'])
554 env.Alias ('all', ['minimal', 'mf', '.'])
555 # Do we want the doc/web separation?
558 'Documentation/user',
559 'Documentation/topdocs',
560 'Documentation/bibliography',
563 # Without target arguments, do minimal build
564 if not COMMAND_LINE_TARGETS:
565 env.Default (['minimal'])
567 # GNU Make rerouting compat:
568 env.Alias ('web', 'doc')
571 env.Command (version_hh, '#/VERSION',
572 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
574 # post-config environment update
576 run_prefix = run_prefix,
577 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
579 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),],
580 ##CPPPATH = [outdir, '#',], # do not read auto*'s header
581 CPPPATH = [outdir, ],
582 LILYPOND_PATH = ['.', '$srcdir/input',
583 '$srcdir/input/regression',
584 '$srcdir/input/test',
585 '$srcdir/input/tutorial',
586 '$srcdir/Documentation/user',
588 # os.path.join (absbuild, 'Documentation',
590 # os.path.join (absbuild, 'Documentation/user',
593 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
594 '$absbuild/Documentation/user/$out'],
597 def symlink_tree (target, source, env):
603 if not os.path.isdir (dir):
604 if os.path.exists (dir):
608 map (mkdir, string.split (dir, os.sep))
609 def symlink (src, dst):
611 dir = os.path.dirname (dst)
614 frm = os.path.join (srcdir, src[1:])
616 depth = len (string.split (dir, '/'))
617 if src.find ('@') > -1:
618 frm = os.path.join ('../' * depth,
619 string.replace (src, '@',
622 frm = os.path.join ('../' * depth, src,
625 frm = os.path.join (frm, os.path.basename (dst))
627 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
628 os.symlink (frm, os.path.basename (dst))
629 shutil.rmtree (run_prefix)
630 prefix = os.path.join (env['out'], 'usr')
631 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
634 # /$ := add dst file_name
635 (('python', 'lib/lilypond/python'),
636 ('lily/', 'bin/lilypond-bin'),
637 ('scripts/', 'bin/lilypond'),
638 ('scripts/', 'bin/lilypond-book'),
639 ('mf', 'share/lilypond/dvips'),
640 ('#ps', 'share/lilypond/tex/music-drawing-routines.ps'),
641 ('mf', 'share/lilypond/afm'),
642 ('mf', 'share/lilypond/tfm'),
643 ('#mf', 'share/lilypond/fonts/mf'),
644 ('mf', 'share/lilypond/fonts/afm'),
645 ('mf', 'share/lilypond/fonts/tfm'),
646 ('mf', 'share/lilypond/fonts/type1'),
647 ('#tex', 'share/lilypond/tex/source'),
648 ('mf', 'share/lilypond/tex/generate'),
649 ('#ly', 'share/lilypond/ly'),
650 ('#scm', 'share/lilypond/scm'),
651 ('#ps', 'share/lilypond/ps'),
652 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
653 ('elisp', 'share/lilypond/elisp')))
657 stamp = os.path.join (run_prefix, 'stamp')
658 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
659 env.Depends ('lily', stamp)
665 def cvs_entry_is_dir (line):
666 return line[0] == 'D' and line[-2] == '/'
668 def cvs_entry_is_file (line):
669 return line[0] == '/' and line[-2] == '/'
672 ENTRIES = os.path.join (dir, 'CVS/Entries')
673 if not os.path.exists (ENTRIES):
675 entries = open (ENTRIES).readlines ()
676 dir_entries = filter (cvs_entry_is_dir, entries)
677 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
679 return dirs + map (cvs_dirs, dirs)
682 ENTRIES = os.path.join (dir, 'CVS/Entries')
683 entries = open (ENTRIES).readlines ()
684 file_entries = filter (cvs_entry_is_file, entries)
685 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
686 return map (lambda x: os.path.join (dir, x), files)
688 def flatten (tree, lst):
689 if type (tree) == type ([]):
691 if type (i) == type ([]):
697 subdirs = flatten (cvs_dirs ('.'), [])
698 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
699 foo = map (lambda x: env.TXT (x + '.txt',
700 os.path.join ('Documentation/topdocs', x)),
702 txt_files = map (lambda x: x + '.txt', readme_files)
703 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
704 tar_base = package.name + '-' + version
705 tar_name = tar_base + '.tar.gz'
706 ball_prefix = os.path.join (outdir, tar_base)
707 tar_ball = os.path.join (outdir, tar_name)
709 dist_files = src_files + txt_files
710 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
711 map (lambda x: env.Depends (tar_ball, x), ball_files)
712 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
713 'ln $SOURCE $TARGET'), dist_files)
714 tar = env.Command (tar_ball, src_files,
715 ['rm -f $$(find $TARGET.dir -name .sconsign)',
716 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
717 env.Alias ('tar', tar)
719 dist_ball = os.path.join (package.release_dir, tar_name)
720 env.Command (dist_ball, tar_ball,
721 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
722 + 'ln $SOURCE $TARGET')
723 env.Depends ('dist', dist_ball)
724 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
725 patch = env.PATCH (patch_name, tar_ball)
726 env.Depends (patch_name, dist_ball)
727 env.Alias ('release', patch)
730 web_base = os.path.join (outdir, 'web')
731 web_ball = web_base + '.tar.gz'
732 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
733 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
734 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
735 env['web_path'] = web_path
736 web_list = os.path.join (outdir, 'weblist')
737 # compatible make heritits
738 # fixme: generate in $outdir is cwd/builddir
739 env.Command (web_list,
740 ## this is correct, but takes > 5min if you have a peder :-)
743 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
744 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
745 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
746 'cd $absbuild && find Documentation input $web_path \
748 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
749 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
750 'cd $absbuild && ls *.html >> $TARGET',])
751 env.Command (web_ball, web_list,
752 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
753 #env.Alias ('web', web_ball)
754 www_base = os.path.join (outdir, 'www')
755 www_ball = www_base + '.tar.gz'
756 env.Command (www_ball, web_ball,
758 'mkdir -p $absbuild/$out/tmp',
759 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
760 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"; do mv $i out-www; done',
761 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
762 env.Alias ('web', www_ball)
766 ETAGSFLAGS = ["""--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\1/'""",
767 """--regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\1/'"""])
768 # filter-out some files?
769 env.Command ('TAGS', src_files, 'etags $ETAGSFLAGS $SOURCES')
772 # Note: SConscripts are only needed in directories where something needs
773 # to be done, building or installing
775 if os.path.exists (os.path.join (d, 'SConscript')):
776 b = os.path.join (env['build'], d, env['out'])
777 # Support clean sourcetree build (--srcdir build)
779 if os.path.abspath (b) != os.path.abspath (d):
780 env.BuildDir (b, d, duplicate = 0)
781 SConscript (os.path.join (b, 'SConscript'))