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 if test_lib (required, 'freetype2', '0.0',
396 'Development files for FreeType 2 font engine'):
397 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
399 if test_lib (required, 'pangoft2', '1.6.0',
400 'Development files for pango, with fontconfig2'):
401 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
402 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
404 if test_lib (optional, 'fontconfig', '2.2.0',
405 'Development files for fontconfig'):
406 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
408 #this could happen only for compiling pango-*
410 test_lib (required, 'gtk+-2.0', '2.4.0',
411 'Development files for GTK+')
412 if test_lib (required, 'pango', '1.6.0',
413 'Development files for pango'):
414 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
416 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
417 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
418 if conf.CheckLib ('pango-1.0',
419 'pango_fc_font_map_add_decoder_find_func'):
420 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
421 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
424 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
425 # <system-dir>] speeds up SCons
426 env['CCFLAGS'] += map (lambda x: '-I' + x,
427 env['CPPPATH'][len (cpppath):])
428 env['CPPPATH'] = cpppath
432 print '********************************'
433 print 'Please install required packages'
435 print '%s: %s-%s or newer (found: %s %s)' % i
440 print '*************************************'
441 print 'Consider installing optional packages'
443 print '%s: %s-%s or newer (found: %s %s)' % i
445 return conf.Finish ()
447 def config_header (target, source, env):
448 config = open (str (target[0]), 'w')
449 for i in list_sort (env['DEFINES'].keys ()):
450 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
452 env.Command (config_hh, config_cache, config_header)
468 if not d.has_key (lst[i]):
476 def uniquify_config_vars (env):
477 for i in config_vars:
478 if env.has_key (i) and type (env[i]) == type ([]):
479 env[i] = uniquify (env[i])
481 def save_config_cache (env):
482 ## FIXME: Is this smart, using option cache for saving
483 ## config.cache? I cannot seem to find the official method.
484 uniquify_config_vars (env)
485 opts.Save (config_cache, env)
487 if 'config' in COMMAND_LINE_TARGETS:
488 sys.stdout.write ('\n')
489 sys.stdout.write ('LilyPond configured')
490 sys.stdout.write ('\n')
491 sys.stdout.write ('now run')
492 sys.stdout.write ('\n')
493 sys.stdout.write (' scons [TARGET|DIR]...')
494 sys.stdout.write ('\n')
496 elif not env['checksums']:
497 # When using timestams, config.hh is NEW. The next
498 # build triggers recompilation of everything. Exiting
499 # here makes SCons use the actual timestamp for config.hh
500 # and prevents recompiling everything the next run.
501 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
502 sys.stdout.write ('Running %s ... ' % command)
503 sys.stdout.write ('\n')
504 s = os.system (command)
508 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
509 os.unlink (config_cache)
511 # scons: *** Calling Configure from Builders is not supported.
512 # env.Command (config_cache, None, configure)
513 if not os.path.exists (config_cache) \
514 or (os.stat ('SConstruct')[stat.ST_MTIME]
515 > os.stat (config_cache)[stat.ST_MTIME]):
516 env = configure (None, None, env)
517 save_config_cache (env)
518 elif env['checksums']:
519 # just save everything
520 save_config_cache (env)
522 #urg how does #/ subst work?
524 SConscript ('buildscripts/builder.py')
526 env.PrependENVPath ('PATH',
527 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
529 if os.environ.has_key ('TEXMF'):
530 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
532 'TEXMF' : '{$LILYPONDPREFIX,' \
533 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
534 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
537 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
538 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
539 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
540 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
543 # post-option environment-update
547 lilypond_datadir = sharedir_package,
548 localedir = localedir,
549 local_lilypond_datadir = sharedir_package_version,
550 lilypondprefix = lilypondprefix,
551 sharedir_package = sharedir_package,
552 sharedir_doc_package = sharedir_doc_package,
553 sharedir_package_version = sharedir_package_version,
555 LILYPOND = BUILD_LILYPOND,
556 ABC2LY = BUILD_ABC2LY,
557 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
558 LILYPOND_BOOK_FORMAT = 'texi-html',
559 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
561 TEXI2DVI_PAPERSIZE = '@afourpaper',
562 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
563 DVIPS_PAPERSIZE = 'a4',
564 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
566 '-u+ec-mftrace.map'],
567 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
571 env.Append (CCFLAGS = ['-g', '-pipe'])
572 if env['optimising']:
573 env.Append (CCFLAGS = '-O2')
574 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
576 env.Append (CCFLAGS = ['-W', '-Wall'])
577 env.Append (CXXFLAGS = ['-Wconversion'])
580 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
583 env['__verbose'] = ' --verbose'
584 env['set__x'] = 'set -x;'
587 ## Explicit target and dependencies
589 if 'clean' in COMMAND_LINE_TARGETS:
590 # ugh: prevent reconfigure instead of clean
591 os.system ('touch %s' % config_cache)
593 command = sys.argv[0] + ' -c .'
594 sys.stdout.write ('Running %s ... ' % command)
595 sys.stdout.write ('\n')
596 s = os.system (command)
597 if os.path.exists (config_cache):
598 os.unlink (config_cache)
601 if 'sconsclean' in COMMAND_LINE_TARGETS:
602 command = 'rm -rf scons.cache $(find . -name ".scon*")'
603 s = os.system (command)
604 if os.path.exists (config_cache):
605 os.unlink (config_cache)
608 if 'realclean' in COMMAND_LINE_TARGETS:
609 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
610 sys.stdout.write ('Running %s ... ' % command)
611 sys.stdout.write ('\n')
612 s = os.system (command)
613 if os.path.exists (config_cache):
614 os.unlink (config_cache)
617 # Declare SConscript phonies
618 env.Alias ('minimal', config_cache)
619 env.Alias ('mf-essential', config_cache)
621 env.Alias ('minimal', ['lily', 'mf-essential'])
622 env.Alias ('all', ['minimal', 'mf', '.'])
623 # Do we want the doc/web separation?
626 'Documentation/user',
627 'Documentation/topdocs',
628 'Documentation/bibliography',
631 # Without target arguments, do minimal build
632 if not COMMAND_LINE_TARGETS:
633 env.Default (['minimal'])
635 # GNU Make rerouting compat:
636 env.Alias ('web', 'doc')
639 env.Command (version_hh, '#/VERSION',
640 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
642 # post-config environment update
644 run_prefix = run_prefix,
645 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
647 # FIXME: move to lily/SConscript?
648 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
649 os.path.join (absbuild, 'kpath-guile', env['out']),
650 os.path.join (absbuild, 'ttftool', env['out']),],
651 CPPPATH = [outdir, ],
652 LILYPOND_PATH = ['.', '$srcdir/input',
653 '$srcdir/input/regression',
654 '$srcdir/input/test',
655 '$srcdir/input/tutorial',
656 '$srcdir/Documentation/user',
658 # os.path.join (absbuild, 'Documentation',
660 # os.path.join (absbuild, 'Documentation/user',
663 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
664 '$absbuild/Documentation/user/$out'],
667 def symlink_tree (target, source, env):
673 if not os.path.isdir (dir):
674 if os.path.exists (dir):
678 map (mkdir, string.split (dir, os.sep))
679 def symlink (src, dst):
681 dir = os.path.dirname (dst)
684 frm = os.path.join (srcdir, src[1:])
686 depth = len (string.split (dir, '/'))
687 if src.find ('@') > -1:
688 frm = os.path.join ('../' * depth,
689 string.replace (src, '@',
692 frm = os.path.join ('../' * depth, src,
695 frm = os.path.join (frm, os.path.basename (dst))
697 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
698 os.symlink (frm, os.path.basename (dst))
699 shutil.rmtree (run_prefix)
700 prefix = os.path.join (env['out'], 'usr')
701 map (lambda x: symlink (x[0], os.path.join (prefix,
702 x[1] % {'ver' : version})),
705 # /$ := add dst file_name
706 (('python', 'lib/lilypond/python'),
707 ('lily/', 'bin/lilypond'),
708 ('scripts/', 'bin/convert-ly'),
709 ('scripts/', 'bin/lilypond-book'),
710 ('scripts/', 'bin/ps2png'),
711 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
712 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
713 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
714 ('mf', 'share/lilypond/%(ver)s/otf'),
715 ('mf', 'share/lilypond/%(ver)s/tfm'),
716 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
717 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
718 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
719 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
720 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
721 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
722 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
723 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
724 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
725 ('#ly', 'share/lilypond/%(ver)s/ly'),
726 ('#scm', 'share/lilypond/%(ver)s/scm'),
727 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
728 ('#ps', 'share/lilypond/%(ver)s/ps'),
729 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
730 ('elisp', 'share/lilypond/%(ver)s/elisp')))
734 stamp = os.path.join (run_prefix, 'stamp')
735 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
736 env.Depends ('lily', stamp)
742 def cvs_entry_is_dir (line):
743 return line[0] == 'D' and line[-2] == '/'
745 def cvs_entry_is_file (line):
746 return line[0] == '/' and line[-2] == '/'
749 ENTRIES = os.path.join (dir, 'CVS/Entries')
750 if not os.path.exists (ENTRIES):
752 entries = open (ENTRIES).readlines ()
753 dir_entries = filter (cvs_entry_is_dir, entries)
754 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
756 return dirs + map (cvs_dirs, dirs)
759 ENTRIES = os.path.join (dir, 'CVS/Entries')
760 entries = open (ENTRIES).readlines ()
761 file_entries = filter (cvs_entry_is_file, entries)
762 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
763 return map (lambda x: os.path.join (dir, x), files)
765 def flatten (tree, lst):
766 if type (tree) == type ([]):
768 if type (i) == type ([]):
775 and 'all' not in COMMAND_LINE_TARGETS\
776 and 'doc' not in COMMAND_LINE_TARGETS\
777 and 'web' not in COMMAND_LINE_TARGETS\
778 and 'install' not in COMMAND_LINE_TARGETS\
779 and 'clean' not in COMMAND_LINE_TARGETS:
780 subdirs = ['lily', 'lily/include',
781 'flower', 'flower/include',
787 subdirs = flatten (cvs_dirs ('.'), [])
789 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
790 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
791 txt_files = map (lambda x: x + '.txt', readme_files)
795 # speeds up build by +- 5%
798 foo = map (lambda x: env.TXT (x + '.txt',
799 os.path.join ('Documentation/topdocs', x)),
801 tar_base = package.name + '-' + version
802 tar_name = tar_base + '.tar.gz'
803 ball_prefix = os.path.join (outdir, tar_base)
804 tar_ball = os.path.join (outdir, tar_name)
806 dist_files = src_files + txt_files
807 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
808 map (lambda x: env.Depends (tar_ball, x), ball_files)
809 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
810 'ln $SOURCE $TARGET'), dist_files)
811 tar = env.Command (tar_ball, src_files,
812 ['rm -f $$(find $TARGET.dir -name .sconsign)',
813 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
814 env.Alias ('tar', tar)
816 dist_ball = os.path.join (package.release_dir, tar_name)
817 env.Command (dist_ball, tar_ball,
818 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
819 + 'ln $SOURCE $TARGET')
820 env.Depends ('dist', dist_ball)
821 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
822 patch = env.PATCH (patch_name, tar_ball)
823 env.Depends (patch_name, dist_ball)
824 env.Alias ('release', patch)
828 web_base = os.path.join (outdir, 'web')
829 web_ball = web_base + '.tar.gz'
830 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
831 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
832 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
833 env['web_path'] = web_path
834 web_list = os.path.join (outdir, 'weblist')
835 # compatible make heritits
836 # fixme: generate in $outdir is cwd/builddir
837 env.Command (web_list,
838 ## this is correct, but takes > 5min if you have a peder :-)
841 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
842 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
843 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
844 'cd $absbuild && find Documentation input $web_path \
846 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
847 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
848 'cd $absbuild && ls *.html >> $TARGET',])
849 env.Command (web_ball, web_list,
850 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
851 #env.Alias ('web', web_ball)
852 www_base = os.path.join (outdir, 'www')
853 www_ball = www_base + '.tar.gz'
854 env.Command (www_ball, web_ball,
856 'mkdir -p $absbuild/$out/tmp',
857 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
858 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
859 + ' do mv $$i $$(dirname $$i)/out-www; done',
860 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
861 env.Alias ('web', www_ball)
865 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
866 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
867 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
868 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
870 'etags $ETAGSFLAGS $SOURCES')
872 # Note: SConscripts are only needed in directories where something needs
873 # to be done, building or installing
875 if os.path.exists (os.path.join (d, 'SConscript')):
876 b = os.path.join (env['build'], d, env['out'])
877 # Support clean sourcetree build (--srcdir build)
879 if os.path.abspath (b) != os.path.abspath (d):
880 env.BuildDir (b, d, duplicate = 0)
881 SConscript (os.path.join (b, 'SConscript'))