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, ...?)
69 # * split doc target: doc input examples mutopia?
71 # * grep FIXME $(find . -name 'S*t')
83 EnsureSConsVersion (0, 95)
86 scons [KEY=VALUE].. [TARGET|DIR]..
88 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
89 realclean, release, sconsclean, tar, TAGS
94 config_cache = 'scons.cache'
110 # Put your favourite stuff in custom.py
111 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
112 opts.Add ('prefix', 'Install prefix', '/usr/')
113 opts.Add ('out', 'Output directory', 'out-scons')
114 opts.Add ('build', 'Build directory', '.')
115 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
117 BoolOption ('warnings', 'compile with -Wall and similiar',
119 BoolOption ('debugging', 'compile with debugging symbols',
121 BoolOption ('optimising', 'compile with optimising',
123 BoolOption ('shared', 'build shared libraries',
125 BoolOption ('static', 'build static libraries',
127 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
129 BoolOption ('verbose', 'run commands with verbose flag',
131 BoolOption ('checksums', 'use checksums instead of timestamps',
133 BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
137 srcdir = Dir ('.').srcnode ().abspath
139 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
141 package = packagepython.Package (srcdir)
142 version = packagepython.version_tuple_to_str (package.version)
144 ENV = { 'PATH' : os.environ['PATH'] }
145 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH']:
146 if os.environ.has_key (key):
147 ENV[key] = os.environ[key]
153 PERL = '/usr/bin/perl',
154 PYTHON = '/usr/bin/python',
157 MAKEINFO = 'LANG= makeinfo',
158 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
160 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
161 'usr/pkg/gnome/lib'),
162 os.path.join (os.environ['HOME'],
163 'usr/pkg/pango/lib')],
166 TOPLEVEL_VERSION = version,
169 # Add all config_vars to opts, so that they will be read and saved
170 # together with the other configure options.
171 map (lambda x: opts.AddOptions ((x,)), config_vars)
173 Help (usage + opts.GenerateHelpText (env))
178 # Usability switch (Anthony Roach).
179 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
180 # First do: scons realclean .
182 SetOption ('max_drift', 1)
183 SetOption ('implicit_cache', 1)
184 elif env['checksums']:
185 # Always use checksums (makes more sense than timestamps).
186 SetOption ('max_drift', 0)
187 # Using *content* checksums prevents rebuilds after
188 # [re]configure if config.hh has not changed. Too bad that it
190 TargetSignatures ('content')
192 absbuild = Dir (env['build']).abspath
193 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
194 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
197 config_hh = os.path.join (outdir, 'config.hh')
198 version_hh = os.path.join (outdir, 'version.hh')
200 env.Alias ('config', config_cache)
202 cachedir = os.path.join (outdir, 'build-cache')
204 if not os.path.exists(cachedir):
205 os.makedirs(cachedir)
207 CacheDir (os.path.join (outdir, 'build-cache'))
209 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
210 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
211 env['prefix'] = run_prefix
213 prefix = env['prefix']
214 bindir = os.path.join (prefix, 'bin')
215 sharedir = os.path.join (prefix, 'share')
216 libdir = os.path.join (prefix, 'lib')
217 localedir = os.path.join (sharedir, 'locale')
218 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
219 sharedir_package = os.path.join (sharedir, package.name)
220 sharedir_package_version = os.path.join (sharedir_package, version)
221 lilypondprefix = sharedir_package_version
236 def configure (target, source, env):
237 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
238 def get_version (program):
239 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
240 pipe = os.popen (command)
241 output = pipe.read ()
244 v = re.sub (vre, '\\1', output)
245 return string.split (v, '.')
247 def test_program (lst, program, minimal, description, package):
248 sys.stdout.write ('Checking %s version... ' % program)
249 actual = get_version (program)
252 lst.append ((description, package, minimal, program,
255 sys.stdout.write (string.join (actual, '.'))
256 sys.stdout.write ('\n')
257 if actual < string.split (minimal, '.'):
258 lst.append ((description, package, minimal, program,
259 string.join (actual, '.')))
261 for i in ['bash', 'perl', 'python', 'sh']:
262 sys.stdout.write ('Checking for %s... ' % i)
264 key = string.upper (i)
269 sys.stdout.write ('not found: %s (using: %s)' \
272 sys.stdout.write ('\n')
275 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
276 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
277 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
278 test_program (required, 'guile-config', '1.6', 'GUILE development',
279 'libguile-dev or guile-devel')
280 # Do not use bison 1.50 and 1.75.
281 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
283 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
287 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
288 test_program (optional, 'guile', '1.6', 'GUILE scheme',
289 'libguile-dev or guile-devel')
290 test_program (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
292 test_program (optional, 'perl', '4.0',
293 'Perl practical efficient readonly language', 'perl')
294 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
296 def CheckYYCurrentBuffer (context):
297 context.Message ('Checking for yy_current_buffer... ')
298 ret = conf.TryCompile ("""using namespace std;
299 #include <FlexLexer.h>
300 class yy_flex_lexer: public yyFlexLexer
305 yy_current_buffer = 0;
311 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
312 : CheckYYCurrentBuffer })
315 'DIRSEP' : "'%s'" % os.sep,
316 'PATHSEP' : "'%s'" % os.pathsep,
317 'TOPLEVEL_VERSION' : '"' + version + '"',
318 'PACKAGE': '"' + package.name + '"',
319 'DATADIR' : '"' + sharedir + '"',
320 'LILYPOND_DATADIR' : '"' + sharedir_package + '"',
321 'LOCAL_LILYPOND_DATADIR' : '"' + sharedir_package_version + '"',
322 'LOCALEDIR' : '"' + localedir + '"',
324 conf.env.Append (DEFINES = defines)
326 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
327 PYTHON_INCLUDE = os.popen (command).read ()
329 env.Append (CCFLAGS = ['-I%s ' % PYTHON_INCLUDE])
331 env.Append (CPPPATH = PYTHON_INCLUDE)
333 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
336 if conf.CheckCHeader (i):
337 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
338 conf.env['DEFINES'][key] = 1
340 ccheaders = ('sstream',)
342 if conf.CheckCXXHeader (i):
343 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
344 conf.env['DEFINES'][key] = 1
346 functions = ('fopencookie', 'funopen',
347 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
349 if 0 or conf.CheckFunc (i):
350 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
351 conf.env['DEFINES'][key] = 1
353 if conf.CheckYYCurrentBuffer ():
354 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
356 if conf.CheckLib ('dl'):
359 if conf.CheckLib ('kpathsea'):
360 conf.env['DEFINES']['KPATHSEA'] = 1
363 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
364 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
365 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
366 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
370 if env.has_key ('CPPPATH'):
371 cpppath = env['CPPPATH']
373 ## FIXME: linkage, check for libguile.h and scm_boot_guile
374 #this could happen after flower...
375 env.ParseConfig ('guile-config compile')
377 #this could happen only for compiling pango-*
379 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
380 env.ParseConfig ('pkg-config --cflags --libs pango')
381 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
382 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
384 if conf.CheckLib ('pango-1.0',
385 'pango_fc_font_map_add_decoder_find_func'):
386 conf.env['DEFINES']['HAVE_PANGO_CVS'] = '1'
387 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
390 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
391 # <system-dir>] speeds up SCons
392 env['CCFLAGS'] += map (lambda x: '-I' + x,
393 env['CPPPATH'][len (cpppath):])
394 env['CPPPATH'] = cpppath
398 print '********************************'
399 print 'Please install required packages'
401 print '%s: %s-%s or newer (found: %s %s)' % i
406 print '*************************************'
407 print 'Consider installing optional packages'
409 print '%s: %s-%s or newer (found: %s %s)' % i
411 return conf.Finish ()
413 def config_header (target, source, env):
414 config = open (str (target[0]), 'w')
415 for i in list_sort (env['DEFINES'].keys ()):
416 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
418 env.Command (config_hh, config_cache, config_header)
434 if not d.has_key (lst[i]):
442 def uniquify_config_vars (env):
443 for i in config_vars:
444 if env.has_key (i) and type (env[i]) == type ([]):
445 env[i] = uniquify (env[i])
447 def save_config_cache (env):
448 ## FIXME: Is this smart, using option cache for saving
449 ## config.cache? I cannot seem to find the official method.
450 uniquify_config_vars (env)
451 opts.Save (config_cache, env)
453 if 'config' in COMMAND_LINE_TARGETS:
454 sys.stdout.write ('\n')
455 sys.stdout.write ('LilyPond configured')
456 sys.stdout.write ('\n')
457 sys.stdout.write ('now run')
458 sys.stdout.write ('\n')
459 sys.stdout.write (' scons [TARGET|DIR]...')
460 sys.stdout.write ('\n')
462 elif not env['checksums']:
463 # When using timestams, config.hh is NEW. The next
464 # build triggers recompilation of everything. Exiting
465 # here makes SCons use the actual timestamp for config.hh
466 # and prevents recompiling everything the next run.
467 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
468 sys.stdout.write ('Running %s ... ' % command)
469 sys.stdout.write ('\n')
470 s = os.system (command)
474 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
475 os.unlink (config_cache)
477 # scons: *** Calling Configure from Builders is not supported.
478 # env.Command (config_cache, None, configure)
479 if not os.path.exists (config_cache) \
480 or (os.stat ('SConstruct')[stat.ST_MTIME]
481 > os.stat (config_cache)[stat.ST_MTIME]):
482 env = configure (None, None, env)
483 save_config_cache (env)
484 elif env['checksums']:
485 # just save everything
486 save_config_cache (env)
488 #urg how does #/ subst work?
490 SConscript ('buildscripts/builder.py')
492 env.PrependENVPath ('PATH',
493 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
495 if os.environ.has_key ('TEXMF'):
496 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
498 'TEXMF' : '{$LILYPONDPREFIX,' \
499 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
500 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
503 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
504 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
505 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
506 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
509 # post-option environment-update
513 lilypond_datadir = sharedir_package,
514 localedir = localedir,
515 local_lilypond_datadir = sharedir_package_version,
516 lilypondprefix = lilypondprefix,
517 sharedir_package = sharedir_package,
518 sharedir_doc_package = sharedir_doc_package,
519 sharedir_package_version = sharedir_package_version,
521 LILYPOND = BUILD_LILYPOND,
522 ABC2LY = BUILD_ABC2LY,
523 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
524 LILYPOND_BOOK_FORMAT = 'texi-html',
525 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
527 TEXI2DVI_PAPERSIZE = '@afourpaper',
528 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
529 DVIPS_PAPERSIZE = 'a4',
530 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
532 '-u+ec-mftrace.map'],
533 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
537 env.Append (CCFLAGS = ['-g', '-pipe'])
538 if env['optimising']:
539 env.Append (CCFLAGS = '-O2')
540 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
542 env.Append (CCFLAGS = ['-W', '-Wall'])
543 env.Append (CXXFLAGS = ['-Wconversion'])
546 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
549 env['__verbose'] = ' --verbose'
550 env['set__x'] = 'set -x;'
553 ## Explicit target and dependencies
555 if 'clean' in COMMAND_LINE_TARGETS:
556 # ugh: prevent reconfigure instead of clean
557 os.system ('touch %s' % config_cache)
559 command = sys.argv[0] + ' -c .'
560 sys.stdout.write ('Running %s ... ' % command)
561 sys.stdout.write ('\n')
562 s = os.system (command)
563 if os.path.exists (config_cache):
564 os.unlink (config_cache)
567 if 'sconsclean' in COMMAND_LINE_TARGETS:
568 command = 'rm -rf scons.cache $(find . -name ".scon*")'
569 s = os.system (command)
570 if os.path.exists (config_cache):
571 os.unlink (config_cache)
574 if 'realclean' in COMMAND_LINE_TARGETS:
575 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
576 sys.stdout.write ('Running %s ... ' % command)
577 sys.stdout.write ('\n')
578 s = os.system (command)
579 if os.path.exists (config_cache):
580 os.unlink (config_cache)
583 # Declare SConscript phonies
584 env.Alias ('minimal', config_cache)
585 env.Alias ('mf-essential', config_cache)
587 env.Alias ('minimal', ['lily', 'mf-essential'])
588 env.Alias ('all', ['minimal', 'mf', '.'])
589 # Do we want the doc/web separation?
592 'Documentation/user',
593 'Documentation/topdocs',
594 'Documentation/bibliography',
597 # Without target arguments, do minimal build
598 if not COMMAND_LINE_TARGETS:
599 env.Default (['minimal'])
601 # GNU Make rerouting compat:
602 env.Alias ('web', 'doc')
605 env.Command (version_hh, '#/VERSION',
606 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
608 # post-config environment update
610 run_prefix = run_prefix,
611 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
613 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),],
614 CPPPATH = [outdir, ],
615 LILYPOND_PATH = ['.', '$srcdir/input',
616 '$srcdir/input/regression',
617 '$srcdir/input/test',
618 '$srcdir/input/tutorial',
619 '$srcdir/Documentation/user',
621 # os.path.join (absbuild, 'Documentation',
623 # os.path.join (absbuild, 'Documentation/user',
626 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
627 '$absbuild/Documentation/user/$out'],
630 def symlink_tree (target, source, env):
636 if not os.path.isdir (dir):
637 if os.path.exists (dir):
641 map (mkdir, string.split (dir, os.sep))
642 def symlink (src, dst):
644 dir = os.path.dirname (dst)
647 frm = os.path.join (srcdir, src[1:])
649 depth = len (string.split (dir, '/'))
650 if src.find ('@') > -1:
651 frm = os.path.join ('../' * depth,
652 string.replace (src, '@',
655 frm = os.path.join ('../' * depth, src,
658 frm = os.path.join (frm, os.path.basename (dst))
660 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
661 os.symlink (frm, os.path.basename (dst))
662 shutil.rmtree (run_prefix)
663 prefix = os.path.join (env['out'], 'usr')
664 map (lambda x: symlink (x[0], os.path.join (prefix,
665 x[1] % {'ver' : version})),
668 # /$ := add dst file_name
669 (('python', 'lib/lilypond/python'),
670 ('lily/', 'bin/lilypond-bin'),
671 ('scripts/', 'bin/lilypond'),
672 ('scripts/', 'bin/lilypond-book'),
673 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
674 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
675 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
676 ('mf', 'share/lilypond/%(ver)s/otf'),
677 ('mf', 'share/lilypond/%(ver)s/tfm'),
678 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
679 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
680 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
681 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
682 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
683 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
684 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
685 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
686 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
687 ('#ly', 'share/lilypond/%(ver)s/ly'),
688 ('#scm', 'share/lilypond/%(ver)s/scm'),
689 ('#ps', 'share/lilypond/%(ver)s/ps'),
690 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
691 ('elisp', 'share/lilypond/%(ver)s/elisp')))
695 stamp = os.path.join (run_prefix, 'stamp')
696 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
697 env.Depends ('lily', stamp)
703 def cvs_entry_is_dir (line):
704 return line[0] == 'D' and line[-2] == '/'
706 def cvs_entry_is_file (line):
707 return line[0] == '/' and line[-2] == '/'
710 ENTRIES = os.path.join (dir, 'CVS/Entries')
711 if not os.path.exists (ENTRIES):
713 entries = open (ENTRIES).readlines ()
714 dir_entries = filter (cvs_entry_is_dir, entries)
715 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
717 return dirs + map (cvs_dirs, dirs)
720 ENTRIES = os.path.join (dir, 'CVS/Entries')
721 entries = open (ENTRIES).readlines ()
722 file_entries = filter (cvs_entry_is_file, entries)
723 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
724 return map (lambda x: os.path.join (dir, x), files)
726 def flatten (tree, lst):
727 if type (tree) == type ([]):
729 if type (i) == type ([]):
736 and 'all' not in COMMAND_LINE_TARGETS\
737 and 'doc' not in COMMAND_LINE_TARGETS\
738 and 'web' not in COMMAND_LINE_TARGETS\
739 and 'install' not in COMMAND_LINE_TARGETS\
740 and 'clean' not in COMMAND_LINE_TARGETS:
741 subdirs = ['lily', 'lily/include', 'flower', 'flower/include', 'mf']
743 subdirs = flatten (cvs_dirs ('.'), [])
745 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
746 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
747 txt_files = map (lambda x: x + '.txt', readme_files)
751 # speeds up build by +- 5%
754 foo = map (lambda x: env.TXT (x + '.txt',
755 os.path.join ('Documentation/topdocs', x)),
757 tar_base = package.name + '-' + version
758 tar_name = tar_base + '.tar.gz'
759 ball_prefix = os.path.join (outdir, tar_base)
760 tar_ball = os.path.join (outdir, tar_name)
762 dist_files = src_files + txt_files
763 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
764 map (lambda x: env.Depends (tar_ball, x), ball_files)
765 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
766 'ln $SOURCE $TARGET'), dist_files)
767 tar = env.Command (tar_ball, src_files,
768 ['rm -f $$(find $TARGET.dir -name .sconsign)',
769 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
770 env.Alias ('tar', tar)
772 dist_ball = os.path.join (package.release_dir, tar_name)
773 env.Command (dist_ball, tar_ball,
774 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
775 + 'ln $SOURCE $TARGET')
776 env.Depends ('dist', dist_ball)
777 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
778 patch = env.PATCH (patch_name, tar_ball)
779 env.Depends (patch_name, dist_ball)
780 env.Alias ('release', patch)
784 web_base = os.path.join (outdir, 'web')
785 web_ball = web_base + '.tar.gz'
786 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
787 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
788 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
789 env['web_path'] = web_path
790 web_list = os.path.join (outdir, 'weblist')
791 # compatible make heritits
792 # fixme: generate in $outdir is cwd/builddir
793 env.Command (web_list,
794 ## this is correct, but takes > 5min if you have a peder :-)
797 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
798 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
799 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
800 'cd $absbuild && find Documentation input $web_path \
802 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
803 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
804 'cd $absbuild && ls *.html >> $TARGET',])
805 env.Command (web_ball, web_list,
806 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
807 #env.Alias ('web', web_ball)
808 www_base = os.path.join (outdir, 'www')
809 www_ball = www_base + '.tar.gz'
810 env.Command (www_ball, web_ball,
812 'mkdir -p $absbuild/$out/tmp',
813 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
814 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
815 + ' do mv $$i $$(dirname $$i)/out-www; done',
816 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
817 env.Alias ('web', www_ball)
821 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
822 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
823 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
824 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
826 'etags $ETAGSFLAGS $SOURCES')
828 # Note: SConscripts are only needed in directories where something needs
829 # to be done, building or installing
831 if os.path.exists (os.path.join (d, 'SConscript')):
832 b = os.path.join (env['build'], d, env['out'])
833 # Support clean sourcetree build (--srcdir build)
835 if os.path.abspath (b) != os.path.abspath (d):
836 env.BuildDir (b, d, duplicate = 0)
837 SConscript (os.path.join (b, 'SConscript'))