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 CPPDEFINES = '-DHAVE_CONFIG_H',
154 PERL = '/usr/bin/perl',
155 PYTHON = '/usr/bin/python',
158 MAKEINFO = 'LANG= makeinfo',
159 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
161 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
162 'usr/pkg/gnome/lib'),
163 os.path.join (os.environ['HOME'],
164 'usr/pkg/pango/lib')],
167 TOPLEVEL_VERSION = version,
170 # Add all config_vars to opts, so that they will be read and saved
171 # together with the other configure options.
172 map (lambda x: opts.AddOptions ((x,)), config_vars)
174 Help (usage + opts.GenerateHelpText (env))
179 # Usability switch (Anthony Roach).
180 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
181 # First do: scons realclean .
183 SetOption ('max_drift', 1)
184 SetOption ('implicit_cache', 1)
185 elif env['checksums']:
186 # Always use checksums (makes more sense than timestamps).
187 SetOption ('max_drift', 0)
188 # Using *content* checksums prevents rebuilds after
189 # [re]configure if config.hh has not changed. Too bad that it
191 TargetSignatures ('content')
193 absbuild = Dir (env['build']).abspath
194 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
195 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
198 config_hh = os.path.join (outdir, 'config.hh')
199 version_hh = os.path.join (outdir, 'version.hh')
201 env.Alias ('config', config_cache)
203 cachedir = os.path.join (outdir, 'build-cache')
205 if not os.path.exists (cachedir):
206 os.makedirs (cachedir)
210 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
211 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
212 env['prefix'] = run_prefix
214 prefix = env['prefix']
215 bindir = os.path.join (prefix, 'bin')
216 sharedir = os.path.join (prefix, 'share')
217 libdir = os.path.join (prefix, 'lib')
218 localedir = os.path.join (sharedir, 'locale')
219 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
220 sharedir_package = os.path.join (sharedir, package.name)
221 sharedir_package_version = os.path.join (sharedir_package, version)
222 lilypondprefix = sharedir_package_version
237 def configure (target, source, env):
238 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
239 def get_version (program):
240 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
241 pipe = os.popen (command)
242 output = pipe.read ()
245 v = re.sub (vre, '\\1', output)
248 return string.split (v, '.')
250 def test_program (lst, program, minimal, description, package):
251 sys.stdout.write ('Checking %s version... ' % program)
252 actual = get_version (program)
255 lst.append ((description, package, minimal, program,
258 sys.stdout.write (string.join (actual, '.'))
259 sys.stdout.write ('\n')
260 if actual < string.split (minimal, '.'):
261 lst.append ((description, package, minimal, program,
262 string.join (actual, '.')))
266 def test_lib (lst, program, minimal, description):
267 # FIXME: test for Debian or RPM (or -foo?) based dists
268 # to guess (or get correct!: apt-cache search?)
270 #if os.system ('pkg-config --atleast-version=0 freetype2'):
272 if test_program (lst, program, minimal, description,
273 'lib%(program)s-dev or %(program)s-devel'
275 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
280 for i in ['bash', 'perl', 'python', 'sh']:
281 sys.stdout.write ('Checking for %s... ' % i)
283 key = string.upper (i)
288 sys.stdout.write ('not found: %s (using: %s)' \
291 sys.stdout.write ('\n')
294 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
295 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
296 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
297 test_program (required, 'guile-config', '1.6', 'GUILE development',
298 'libguile-dev or guile-devel')
299 # Do not use bison 1.50 and 1.75.
300 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
302 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
305 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
306 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
307 test_program (optional, 'mftrace', '1.1.0', 'Metafont tracing Type1',
309 test_program (optional, 'perl', '4.0',
310 'Perl practical efficient readonly language', 'perl')
311 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
313 def CheckYYCurrentBuffer (context):
314 context.Message ('Checking for yy_current_buffer... ')
315 ret = conf.TryCompile ("""using namespace std;
316 #include <FlexLexer.h>
317 class yy_flex_lexer: public yyFlexLexer
322 yy_current_buffer = 0;
328 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
329 : CheckYYCurrentBuffer })
332 'DIRSEP' : "'%s'" % os.sep,
333 'PATHSEP' : "'%s'" % os.pathsep,
334 'PACKAGE': '"%s"' % package.name,
335 'DATADIR' : '"%s"' % sharedir,
336 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
337 'LOCALEDIR' : '"%s"' %localedir,
339 conf.env.Append (DEFINES = defines)
341 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
342 PYTHON_INCLUDE = os.popen (command).read ()
344 env.Append (CCFLAGS = ['-I%s ' % PYTHON_INCLUDE])
346 env.Append (CPPPATH = PYTHON_INCLUDE)
348 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
351 if conf.CheckCHeader (i):
352 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
353 conf.env['DEFINES'][key] = 1
355 ccheaders = ('sstream',)
357 if conf.CheckCXXHeader (i):
358 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
359 conf.env['DEFINES'][key] = 1
361 functions = ('fopencookie', 'funopen',
362 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
364 if 0 or conf.CheckFunc (i):
365 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
366 conf.env['DEFINES'][key] = 1
368 if conf.CheckYYCurrentBuffer ():
369 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
371 if conf.CheckLib ('dl'):
374 if conf.CheckLib ('kpathsea'):
375 conf.env['DEFINES']['KPATHSEA'] = 1
378 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
379 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
380 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
381 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
383 # FIXME fc3 - move to kpath-guile/SConscript?
384 conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
388 if env.has_key ('CPPPATH'):
389 cpppath = env['CPPPATH']
391 ## FIXME: linkage, check for libguile.h and scm_boot_guile
392 #this could happen after flower...
393 env.ParseConfig ('guile-config compile')
395 test_program (required, 'pkg-config', '0.9.0',
396 'pkg-config library compile manager', 'pkg-config')
397 if test_lib (required, 'freetype2', '0.0',
398 'Development files for FreeType 2 font engine'):
399 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
401 if test_lib (required, 'pangoft2', '1.6.0',
402 'Development files for pango, with fontconfig2'):
403 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
404 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
406 if test_lib (optional, 'fontconfig', '2.2.0',
407 'Development files for fontconfig'):
408 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
410 #this could happen only for compiling pango-*
412 test_lib (required, 'gtk+-2.0', '2.4.0',
413 'Development files for GTK+')
414 if test_lib (required, 'pango', '1.6.0',
415 'Development files for pango'):
416 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
418 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
419 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
420 if conf.CheckLib ('pango-1.0',
421 'pango_fc_font_map_add_decoder_find_func'):
422 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
423 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
426 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
427 # <system-dir>] speeds up SCons
428 env['CCFLAGS'] += map (lambda x: '-I' + x,
429 env['CPPPATH'][len (cpppath):])
430 env['CPPPATH'] = cpppath
434 print '********************************'
435 print 'Please install required packages'
437 print '%s: %s-%s or newer (found: %s %s)' % i
442 print '*************************************'
443 print 'Consider installing optional packages'
445 print '%s: %s-%s or newer (found: %s %s)' % i
447 return conf.Finish ()
449 def config_header (target, source, env):
450 config = open (str (target[0]), 'w')
451 for i in list_sort (env['DEFINES'].keys ()):
452 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
454 env.Command (config_hh, config_cache, config_header)
470 if not d.has_key (lst[i]):
478 def uniquify_config_vars (env):
479 for i in config_vars:
480 if env.has_key (i) and type (env[i]) == type ([]):
481 env[i] = uniquify (env[i])
483 def save_config_cache (env):
484 ## FIXME: Is this smart, using option cache for saving
485 ## config.cache? I cannot seem to find the official method.
486 uniquify_config_vars (env)
487 opts.Save (config_cache, env)
489 if 'config' in COMMAND_LINE_TARGETS:
490 sys.stdout.write ('\n')
491 sys.stdout.write ('LilyPond configured')
492 sys.stdout.write ('\n')
493 sys.stdout.write ('now run')
494 sys.stdout.write ('\n')
495 sys.stdout.write (' scons [TARGET|DIR]...')
496 sys.stdout.write ('\n')
498 elif not env['checksums']:
499 # When using timestams, config.hh is NEW. The next
500 # build triggers recompilation of everything. Exiting
501 # here makes SCons use the actual timestamp for config.hh
502 # and prevents recompiling everything the next run.
503 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
504 sys.stdout.write ('Running %s ... ' % command)
505 sys.stdout.write ('\n')
506 s = os.system (command)
510 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
511 os.unlink (config_cache)
513 # scons: *** Calling Configure from Builders is not supported.
514 # env.Command (config_cache, None, configure)
515 if not os.path.exists (config_cache) \
516 or (os.stat ('SConstruct')[stat.ST_MTIME]
517 > os.stat (config_cache)[stat.ST_MTIME]):
518 env = configure (None, None, env)
519 save_config_cache (env)
520 elif env['checksums']:
521 # just save everything
522 save_config_cache (env)
524 #urg how does #/ subst work?
526 SConscript ('buildscripts/builder.py')
528 env.PrependENVPath ('PATH',
529 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
531 if os.environ.has_key ('TEXMF'):
532 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
534 'TEXMF' : '{$LILYPONDPREFIX,' \
535 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
536 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
539 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
540 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
541 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
542 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
545 # post-option environment-update
549 lilypond_datadir = sharedir_package,
550 localedir = localedir,
551 local_lilypond_datadir = sharedir_package_version,
552 lilypondprefix = lilypondprefix,
553 sharedir_package = sharedir_package,
554 sharedir_doc_package = sharedir_doc_package,
555 sharedir_package_version = sharedir_package_version,
557 LILYPOND = BUILD_LILYPOND,
558 ABC2LY = BUILD_ABC2LY,
559 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
560 LILYPOND_BOOK_FORMAT = 'texi-html',
561 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
563 TEXI2DVI_PAPERSIZE = '@afourpaper',
564 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
565 DVIPS_PAPERSIZE = 'a4',
566 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
568 '-u+ec-mftrace.map'],
569 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
573 env.Append (CCFLAGS = ['-g', '-pipe'])
574 if env['optimising']:
575 env.Append (CCFLAGS = '-O2')
576 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
578 env.Append (CCFLAGS = ['-W', '-Wall'])
579 env.Append (CXXFLAGS = ['-Wconversion'])
582 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
585 env['__verbose'] = ' --verbose'
586 env['set__x'] = 'set -x;'
589 ## Explicit target and dependencies
591 if 'clean' in COMMAND_LINE_TARGETS:
592 # ugh: prevent reconfigure instead of clean
593 os.system ('touch %s' % config_cache)
595 command = sys.argv[0] + ' -c .'
596 sys.stdout.write ('Running %s ... ' % command)
597 sys.stdout.write ('\n')
598 s = os.system (command)
599 if os.path.exists (config_cache):
600 os.unlink (config_cache)
603 if 'sconsclean' in COMMAND_LINE_TARGETS:
604 command = 'rm -rf scons.cache $(find . -name ".scon*")'
605 s = os.system (command)
606 if os.path.exists (config_cache):
607 os.unlink (config_cache)
610 if 'realclean' in COMMAND_LINE_TARGETS:
611 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
612 sys.stdout.write ('Running %s ... ' % command)
613 sys.stdout.write ('\n')
614 s = os.system (command)
615 if os.path.exists (config_cache):
616 os.unlink (config_cache)
619 # Declare SConscript phonies
620 env.Alias ('minimal', config_cache)
621 env.Alias ('mf-essential', config_cache)
623 env.Alias ('minimal', ['lily', 'mf-essential'])
624 env.Alias ('all', ['minimal', 'mf', '.'])
625 # Do we want the doc/web separation?
628 'Documentation/user',
629 'Documentation/topdocs',
630 'Documentation/bibliography',
633 # Without target arguments, do minimal build
634 if not COMMAND_LINE_TARGETS:
635 env.Default (['minimal'])
637 # GNU Make rerouting compat:
638 env.Alias ('web', 'doc')
641 env.Command (version_hh, '#/VERSION',
642 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
644 # post-config environment update
646 run_prefix = run_prefix,
647 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
649 # FIXME: move to lily/SConscript?
650 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
651 os.path.join (absbuild, 'kpath-guile', env['out']),
652 os.path.join (absbuild, 'ttftool', env['out']),],
653 CPPPATH = [outdir, ],
654 LILYPOND_PATH = ['.', '$srcdir/input',
655 '$srcdir/input/regression',
656 '$srcdir/input/test',
657 '$srcdir/input/tutorial',
658 '$srcdir/Documentation/user',
660 # os.path.join (absbuild, 'Documentation',
662 # os.path.join (absbuild, 'Documentation/user',
665 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
666 '$absbuild/Documentation/user/$out'],
669 def symlink_tree (target, source, env):
675 if not os.path.isdir (dir):
676 if os.path.exists (dir):
680 map (mkdir, string.split (dir, os.sep))
681 def symlink (src, dst):
683 dir = os.path.dirname (dst)
686 frm = os.path.join (srcdir, src[1:])
688 depth = len (string.split (dir, '/'))
689 if src.find ('@') > -1:
690 frm = os.path.join ('../' * depth,
691 string.replace (src, '@',
694 frm = os.path.join ('../' * depth, src,
697 frm = os.path.join (frm, os.path.basename (dst))
699 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
700 os.symlink (frm, os.path.basename (dst))
701 shutil.rmtree (run_prefix)
702 prefix = os.path.join (env['out'], 'usr')
703 map (lambda x: symlink (x[0], os.path.join (prefix,
704 x[1] % {'ver' : version})),
707 # /$ := add dst file_name
708 (('python', 'lib/lilypond/python'),
709 ('lily/', 'bin/lilypond'),
710 ('scripts/', 'bin/convert-ly'),
711 ('scripts/', 'bin/lilypond-book'),
712 ('scripts/', 'bin/ps2png'),
713 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
714 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
715 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
716 ('mf', 'share/lilypond/%(ver)s/otf'),
717 ('mf', 'share/lilypond/%(ver)s/tfm'),
718 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
719 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
720 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
721 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
722 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
723 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
724 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
725 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
726 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
727 ('#ly', 'share/lilypond/%(ver)s/ly'),
728 ('#scm', 'share/lilypond/%(ver)s/scm'),
729 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
730 ('#ps', 'share/lilypond/%(ver)s/ps'),
731 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
732 ('elisp', 'share/lilypond/%(ver)s/elisp')))
736 stamp = os.path.join (run_prefix, 'stamp')
737 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
738 env.Depends ('lily', stamp)
744 def cvs_entry_is_dir (line):
745 return line[0] == 'D' and line[-2] == '/'
747 def cvs_entry_is_file (line):
748 return line[0] == '/' and line[-2] == '/'
751 ENTRIES = os.path.join (dir, 'CVS/Entries')
752 if not os.path.exists (ENTRIES):
754 entries = open (ENTRIES).readlines ()
755 dir_entries = filter (cvs_entry_is_dir, entries)
756 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
758 return dirs + map (cvs_dirs, dirs)
761 ENTRIES = os.path.join (dir, 'CVS/Entries')
762 entries = open (ENTRIES).readlines ()
763 file_entries = filter (cvs_entry_is_file, entries)
764 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
765 return map (lambda x: os.path.join (dir, x), files)
767 def flatten (tree, lst):
768 if type (tree) == type ([]):
770 if type (i) == type ([]):
777 and 'all' not in COMMAND_LINE_TARGETS\
778 and 'doc' not in COMMAND_LINE_TARGETS\
779 and 'web' not in COMMAND_LINE_TARGETS\
780 and 'install' not in COMMAND_LINE_TARGETS\
781 and 'clean' not in COMMAND_LINE_TARGETS:
782 subdirs = ['lily', 'lily/include',
783 'flower', 'flower/include',
789 subdirs = flatten (cvs_dirs ('.'), [])
791 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
792 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
793 txt_files = map (lambda x: x + '.txt', readme_files)
797 # speeds up build by +- 5%
800 foo = map (lambda x: env.TXT (x + '.txt',
801 os.path.join ('Documentation/topdocs', x)),
803 tar_base = package.name + '-' + version
804 tar_name = tar_base + '.tar.gz'
805 ball_prefix = os.path.join (outdir, tar_base)
806 tar_ball = os.path.join (outdir, tar_name)
808 dist_files = src_files + txt_files
809 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
810 map (lambda x: env.Depends (tar_ball, x), ball_files)
811 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
812 'ln $SOURCE $TARGET'), dist_files)
813 tar = env.Command (tar_ball, src_files,
814 ['rm -f $$(find $TARGET.dir -name .sconsign)',
815 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
816 env.Alias ('tar', tar)
818 dist_ball = os.path.join (package.release_dir, tar_name)
819 env.Command (dist_ball, tar_ball,
820 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
821 + 'ln $SOURCE $TARGET')
822 env.Depends ('dist', dist_ball)
823 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
824 patch = env.PATCH (patch_name, tar_ball)
825 env.Depends (patch_name, dist_ball)
826 env.Alias ('release', patch)
830 web_base = os.path.join (outdir, 'web')
831 web_ball = web_base + '.tar.gz'
832 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
833 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
834 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
835 env['web_path'] = web_path
836 web_list = os.path.join (outdir, 'weblist')
837 # compatible make heritits
838 # fixme: generate in $outdir is cwd/builddir
839 env.Command (web_list,
840 ## this is correct, but takes > 5min if you have a peder :-)
843 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
844 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
845 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
846 'cd $absbuild && find Documentation input $web_path \
848 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
849 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
850 'cd $absbuild && ls *.html >> $TARGET',])
851 env.Command (web_ball, web_list,
852 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
853 #env.Alias ('web', web_ball)
854 www_base = os.path.join (outdir, 'www')
855 www_ball = www_base + '.tar.gz'
856 env.Command (www_ball, web_ball,
858 'mkdir -p $absbuild/$out/tmp',
859 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
860 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
861 + ' do mv $$i $$(dirname $$i)/out-www; done',
862 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
863 env.Alias ('web', www_ball)
867 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
868 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
869 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
870 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
872 'etags $ETAGSFLAGS $SOURCES')
874 # Note: SConscripts are only needed in directories where something needs
875 # to be done, building or installing
877 if os.path.exists (os.path.join (d, 'SConscript')):
878 b = os.path.join (env['build'], d, env['out'])
879 # Support clean sourcetree build (--srcdir build)
881 if os.path.abspath (b) != os.path.abspath (d):
882 env.BuildDir (b, d, duplicate = 0)
883 SConscript (os.path.join (b, 'SConscript'))