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/<VERSION>
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 # - too many stages in Environments setup
66 # (see also buildscripts/builders.py)
67 # - Home-brew scons.cach configuration caching
68 # - Home-brew source tarball generating -- [why] isn't that in SCons?
70 # * usability and documentation for "./configure; make" users
72 # * too much cruft in toplevel SConstruct
74 # * (optional) operation without CVS directories, from tarball
76 # * more program configure tests, actually use full executable name
80 # * split doc target: doc input examples mutopia?
82 # * grep FIXME $(find . -name 'S*t')
95 EnsureSConsVersion (0, 95)
98 scons [KEY=VALUE].. [TARGET|DIR]..
100 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
101 realclean, release, sconsclean, tar, TAGS
106 config_cache = 'scons.cache'
108 # append test_program variables automagically?
130 # Put your favourite stuff in custom.py
131 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
132 opts.Add ('prefix', 'Install prefix', '/usr/')
133 opts.Add ('out', 'Output directory', 'out-scons')
134 opts.Add ('build', 'Build directory', '.')
135 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
137 BoolOption ('warnings', 'compile with -Wall and similiar',
139 BoolOption ('debugging', 'compile with debugging symbols',
141 BoolOption ('optimising', 'compile with optimising',
143 BoolOption ('shared', 'build shared libraries',
145 BoolOption ('static', 'build static libraries',
147 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
149 BoolOption ('verbose', 'run commands with verbose flag',
151 BoolOption ('checksums', 'use checksums instead of timestamps',
153 BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
157 srcdir = Dir ('.').srcnode ().abspath
159 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
161 package = packagepython.Package (srcdir)
162 version = packagepython.version_tuple_to_str (package.version)
164 ENV = { 'PATH' : os.environ['PATH'] }
165 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH']:
166 if os.environ.has_key (key):
167 ENV[key] = os.environ[key]
169 for key in config_vars:
170 if os.environ.has_key (key):
171 ENV[key] = os.environ[key]
177 BYTEORDER = sys.byteorder.upper (),
178 CPPDEFINES = '-DHAVE_CONFIG_H',
179 #PERL = '/usr/bin/perl',
180 #PYTHON = '/usr/bin/python',
183 MAKEINFO = 'LANG= makeinfo',
184 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
186 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
187 'usr/pkg/gnome/lib'),
188 os.path.join (os.environ['HOME'],
189 'usr/pkg/pango/lib')],
192 TOPLEVEL_VERSION = version,
195 # Add all config_vars to opts, so that they will be read and saved
196 # together with the other configure options.
197 map (lambda x: opts.AddOptions ((x,)), config_vars)
199 Help (usage + opts.GenerateHelpText (env))
204 # Usability switch (Anthony Roach).
205 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
206 # First do: scons realclean .
208 SetOption ('max_drift', 1)
209 SetOption ('implicit_cache', 1)
210 elif env['checksums']:
211 # Always use checksums (makes more sense than timestamps).
212 SetOption ('max_drift', 0)
213 # Using *content* checksums prevents rebuilds after
214 # [re]configure if config.hh has not changed. Too bad that it
216 TargetSignatures ('content')
218 absbuild = Dir (env['build']).abspath
219 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
220 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
223 config_hh = os.path.join (outdir, 'config.hh')
224 version_hh = os.path.join (outdir, 'version.hh')
226 env.Alias ('config', config_cache)
228 cachedir = os.path.join (outdir, 'build-cache')
230 if not os.path.exists (cachedir):
231 os.makedirs (cachedir)
235 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
236 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
237 env['prefix'] = run_prefix
239 prefix = env['prefix']
240 bindir = os.path.join (prefix, 'bin')
241 sharedir = os.path.join (prefix, 'share')
242 libdir = os.path.join (prefix, 'lib')
243 localedir = os.path.join (sharedir, 'locale')
244 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
245 sharedir_package = os.path.join (sharedir, package.name)
246 sharedir_package_version = os.path.join (sharedir_package, version)
247 lilypondprefix = sharedir_package_version
262 def configure (target, source, env):
263 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$',
265 def get_version (program):
266 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
267 pipe = os.popen (command)
268 output = pipe.read ()
271 v = re.sub (vre, '\\1', output)
274 return string.split (v, '.')
276 def test_version (lst, full_name, minimal, description, package):
277 program = os.path.basename (full_name)
278 sys.stdout.write ('Checking %s version... ' % program)
279 actual = get_version (program)
282 lst.append ((description, package, minimal, program,
285 print string.join (actual, '.')
286 if map (string.atoi, actual) \
287 < map (string.atoi, string.split (minimal, '.')):
288 lst.append ((description, package, minimal, program,
289 string.join (actual, '.')))
293 def test_program (lst, program, minimal, description, package):
294 sys.stdout.write ('Checking for %s ... ' % program)
295 f = WhereIs (program)
298 lst.append ((description, package, minimal, program,
302 key = program.upper ()
304 key = re.sub ('\+', 'X', key)
305 key = re.sub ('-', '_', key)
307 return test_version (lst, program, minimal, description, package)
309 def test_lib (lst, program, minimal, description):
310 # FIXME: test for Debian or RPM (or -foo?) based dists
311 # to guess (or get correct!: apt-cache search?)
313 #if os.system ('pkg-config --atleast-version=0 freetype2'):
315 if test_version (lst, program, minimal, description,
316 'lib%(program)s-dev or %(program)s-devel'
318 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
323 for i in []: #['bash', 'perl', 'python', 'sh']:
324 sys.stdout.write ('Checking for %s... ' % i)
326 key = string.upper (i)
331 sys.stdout.write ('not found: %s (using: %s)' \
334 sys.stdout.write ('\n')
337 test_program (required, 'bash', '2.0', 'Bash', 'bash')
338 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
339 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
340 test_program (required, 'guile-config', '1.6', 'GUILE development',
341 'libguile-dev or guile-devel')
342 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
343 test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
346 # Do not use bison 1.50 and 1.75.
347 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
349 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
350 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
351 test_program (optional, 'gs', '8.14', 'Ghostscript PostScript interpreter', 'gs or gs-afpl or gs-esp or gs-gpl')
352 test_program (optional, 'mftrace', '1.1.0', 'Metafont tracing Type1',
354 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
355 test_program (optional, 'perl', '4.0',
356 'Perl practical efficient readonly language', 'perl')
357 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
358 test_program (optional, 'fontforge', '0.0.20041224', 'FontForge', 'fontforge')
360 def CheckYYCurrentBuffer (context):
361 context.Message ('Checking for yy_current_buffer... ')
362 ret = conf.TryCompile ("""using namespace std;
363 #include <FlexLexer.h>
364 class yy_flex_lexer: public yyFlexLexer
369 yy_current_buffer = 0;
375 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
376 : CheckYYCurrentBuffer })
379 'DIRSEP' : "'%s'" % os.sep,
380 'PATHSEP' : "'%s'" % os.pathsep,
381 'PACKAGE': '"%s"' % package.name,
382 'DATADIR' : '"%s"' % sharedir,
383 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
384 'LOCALEDIR' : '"%s"' %localedir,
386 conf.env.Append (DEFINES = defines)
388 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
389 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
391 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
393 env.Append (CPPPATH = [PYTHON_INCLUDE])
395 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
398 if conf.CheckCHeader (i):
399 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
400 conf.env['DEFINES'][key] = 1
402 ccheaders = ('sstream',)
404 if conf.CheckCXXHeader (i):
405 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
406 conf.env['DEFINES'][key] = 1
408 functions = ('fopencookie', 'funopen',
409 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
411 if 0 or conf.CheckFunc (i):
412 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
413 conf.env['DEFINES'][key] = 1
415 if conf.CheckYYCurrentBuffer ():
416 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
418 if conf.CheckLib ('dl'):
421 if conf.CheckLib ('kpathsea'):
422 conf.env['DEFINES']['KPATHSEA'] = 1
425 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
426 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
427 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
428 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
430 # FIXME fc3 - move to kpath-guile/SConscript?
431 conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
435 if env.has_key ('CPPPATH'):
436 cpppath = env['CPPPATH']
438 ## FIXME: linkage, check for libguile.h and scm_boot_guile
439 #this could happen after flower...
440 env.ParseConfig ('guile-config compile')
442 test_program (required, 'pkg-config', '0.9.0',
443 'pkg-config library compile manager', 'pkg-config')
444 if test_lib (required, 'freetype2', '0.0',
445 'Development files for FreeType 2 font engine'):
446 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
448 if test_lib (required, 'pangoft2', '1.6.0',
449 'Development files for pango, with fontconfig2'):
450 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
451 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
453 if test_lib (optional, 'fontconfig', '2.2.0',
454 'Development files for fontconfig'):
455 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
457 #this could happen only for compiling pango-*
459 test_lib (required, 'gtk+-2.0', '2.4.0',
460 'Development files for GTK+')
461 if test_lib (required, 'pango', '1.6.0',
462 'Development files for pango'):
463 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
465 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
466 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
468 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
469 # <system-dir>] speeds up SCons
470 env['CCFLAGS'] += map (lambda x: '-I' + x,
471 env['CPPPATH'][len (cpppath):])
472 env['CPPPATH'] = cpppath
476 print '********************************'
477 print 'Please install required packages'
479 print '%s: %s-%s or newer (found: %s %s)' % i
484 print '*************************************'
485 print 'Consider installing optional packages'
487 print '%s: %s-%s or newer (found: %s %s)' % i
489 return conf.Finish ()
491 def config_header (target, source, env):
492 config = open (str (target[0]), 'w')
493 for i in list_sort (env['DEFINES'].keys ()):
494 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
496 env.Command (config_hh, config_cache, config_header)
512 if not d.has_key (lst[i]):
520 def uniquify_config_vars (env):
521 for i in config_vars:
522 if env.has_key (i) and type (env[i]) == type ([]):
523 env[i] = uniquify (env[i])
525 def save_config_cache (env):
526 ## FIXME: Is this smart, using option cache for saving
527 ## config.cache? I cannot seem to find the official method.
528 uniquify_config_vars (env)
529 opts.Save (config_cache, env)
531 if 'config' in COMMAND_LINE_TARGETS:
532 sys.stdout.write ('\n')
533 sys.stdout.write ('LilyPond configured')
534 sys.stdout.write ('\n')
535 sys.stdout.write ('now run')
536 sys.stdout.write ('\n')
537 sys.stdout.write (' scons [TARGET|DIR]...')
538 sys.stdout.write ('\n')
540 elif not env['checksums']:
541 # When using timestams, config.hh is NEW. The next
542 # build triggers recompilation of everything. Exiting
543 # here makes SCons use the actual timestamp for config.hh
544 # and prevents recompiling everything the next run.
545 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
546 sys.stdout.write ('Running %s ... ' % command)
547 sys.stdout.write ('\n')
548 s = os.system (command)
552 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
553 os.unlink (config_cache)
555 # scons: *** Calling Configure from Builders is not supported.
556 # env.Command (config_cache, None, configure)
557 if not os.path.exists (config_cache) \
558 or (os.stat ('SConstruct')[stat.ST_MTIME]
559 > os.stat (config_cache)[stat.ST_MTIME]):
560 env = configure (None, None, env)
561 save_config_cache (env)
562 elif env['checksums']:
563 # just save everything
564 save_config_cache (env)
566 #urg how does #/ subst work?
568 SConscript ('buildscripts/builder.py')
570 env.PrependENVPath ('PATH',
571 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
573 if os.environ.has_key ('TEXMF'):
574 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
576 'TEXMF' : '{$LILYPONDPREFIX,' \
577 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
578 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond/', version),
581 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
582 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
583 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
586 # post-option environment-update
590 lilypond_datadir = sharedir_package,
591 localedir = localedir,
592 local_lilypond_datadir = sharedir_package_version,
593 lilypondprefix = lilypondprefix,
594 sharedir_package = sharedir_package,
595 sharedir_doc_package = sharedir_doc_package,
596 sharedir_package_version = sharedir_package_version,
598 LILYPOND = BUILD_LILYPOND,
599 ABC2LY = BUILD_ABC2LY,
600 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
601 LILYPOND_BOOK_FORMAT = 'texi-html',
602 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
603 # should not be necessary
604 # PYTHONPATH = ['$absbuild/python/$out'],
605 TEXI2DVI_PAPERSIZE = '@afourpaper',
606 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
607 DVIPS_PAPERSIZE = 'a4',
608 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
610 '-u+ec-mftrace.map'],
611 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
615 env.Append (CCFLAGS = ['-g', '-pipe'])
616 if env['optimising']:
617 env.Append (CCFLAGS = '-O2')
618 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
620 env.Append (CCFLAGS = ['-W', '-Wall'])
621 env.Append (CXXFLAGS = ['-Wconversion'])
624 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
627 env['__verbose'] = ' --verbose'
628 env['set__x'] = 'set -x;'
631 ## Explicit target and dependencies
633 if 'clean' in COMMAND_LINE_TARGETS:
634 # ugh: prevent reconfigure instead of clean
635 os.system ('touch %s' % config_cache)
637 command = sys.argv[0] + ' -c .'
638 sys.stdout.write ('Running %s ... ' % command)
639 sys.stdout.write ('\n')
640 s = os.system (command)
641 if os.path.exists (config_cache):
642 os.unlink (config_cache)
645 if 'sconsclean' in COMMAND_LINE_TARGETS:
646 command = 'rm -rf scons.cache $(find . -name ".scon*")'
647 s = os.system (command)
648 if os.path.exists (config_cache):
649 os.unlink (config_cache)
652 if 'realclean' in COMMAND_LINE_TARGETS:
653 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
654 sys.stdout.write ('Running %s ... ' % command)
655 sys.stdout.write ('\n')
656 s = os.system (command)
657 if os.path.exists (config_cache):
658 os.unlink (config_cache)
661 # Declare SConscript phonies
662 env.Alias ('minimal', config_cache)
663 env.Alias ('mf-essential', config_cache)
665 env.Alias ('minimal', ['lily', 'mf-essential'])
666 env.Alias ('all', ['minimal', 'mf', '.'])
667 # Do we want the doc/web separation?
670 'Documentation/user',
671 'Documentation/topdocs',
672 'Documentation/bibliography',
675 # Without target arguments, do minimal build
676 if not COMMAND_LINE_TARGETS:
677 env.Default (['minimal'])
679 # GNU Make rerouting compat:
680 env.Alias ('web', 'doc')
683 env.Command (version_hh, '#/VERSION',
684 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
686 # post-config environment update
688 run_prefix = run_prefix,
689 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version),
691 # FIXME: move to lily/SConscript?
692 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
693 os.path.join (absbuild, 'kpath-guile', env['out']),
694 os.path.join (absbuild, 'ttftool', env['out']),],
695 CPPPATH = [outdir, ],
696 LILYPOND_PATH = ['.', '$srcdir/input',
697 '$srcdir/input/regression',
698 '$srcdir/input/test',
699 '$srcdir/input/tutorial',
700 '$srcdir/Documentation/user',
702 # os.path.join (absbuild, 'Documentation',
704 # os.path.join (absbuild, 'Documentation/user',
707 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
708 '$absbuild/Documentation/user/$out'],
711 def symlink_tree (target, source, env):
717 if not os.path.isdir (dir):
718 if os.path.exists (dir):
722 map (mkdir, string.split (dir, os.sep))
723 def symlink (src, dst):
725 dir = os.path.dirname (dst)
728 frm = os.path.join (srcdir, src[1:])
730 depth = len (string.split (dir, '/'))
731 if src.find ('@') > -1:
732 frm = os.path.join ('../' * depth,
733 string.replace (src, '@',
736 frm = os.path.join ('../' * depth, src,
739 frm = os.path.join (frm, os.path.basename (dst))
741 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
742 os.symlink (frm, os.path.basename (dst))
743 shutil.rmtree (run_prefix)
744 prefix = os.path.join (env['out'], 'usr')
745 map (lambda x: symlink (x[0], os.path.join (prefix,
746 x[1] % {'ver' : version})),
749 # /$ := add dst file_name
750 (('python', 'lib/lilypond/python'),
752 ('python', 'share/lilypond/%(ver)s/python'),
753 ('lily/', 'bin/lilypond'),
754 ('scripts/', 'bin/convert-ly'),
755 ('scripts/', 'bin/lilypond-book'),
756 ('scripts/', 'bin/ps2png'),
757 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
758 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
759 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
760 ('mf', 'share/lilypond/%(ver)s/otf'),
761 ('mf', 'share/lilypond/%(ver)s/tfm'),
762 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
763 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
764 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
765 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
766 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
767 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
768 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
769 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
770 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
771 ('#ly', 'share/lilypond/%(ver)s/ly'),
772 ('#scm', 'share/lilypond/%(ver)s/scm'),
773 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
774 ('#ps', 'share/lilypond/%(ver)s/ps'),
775 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
776 ('elisp', 'share/lilypond/%(ver)s/elisp')))
778 print "FIXME: BARF BARF BARF"
782 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
784 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
785 dir = os.path.join (absbuild, prefix, ext)
786 os.system ('rm -f ' + dir)
789 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
794 stamp = os.path.join (run_prefix, 'stamp')
795 env.Command (stamp, ['#/SConstruct', '#/VERSION'],
796 [symlink_tree, 'touch $TARGET'])
797 env.Depends ('lily', stamp)
803 def cvs_entry_is_dir (line):
804 return line[0] == 'D' and line[-2] == '/'
806 def cvs_entry_is_file (line):
807 return line[0] == '/' and line[-2] == '/'
810 ENTRIES = os.path.join (dir, 'CVS/Entries')
811 if not os.path.exists (ENTRIES):
813 entries = open (ENTRIES).readlines ()
814 dir_entries = filter (cvs_entry_is_dir, entries)
815 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
817 return dirs + map (cvs_dirs, dirs)
820 ENTRIES = os.path.join (dir, 'CVS/Entries')
821 entries = open (ENTRIES).readlines ()
822 file_entries = filter (cvs_entry_is_file, entries)
823 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
824 return map (lambda x: os.path.join (dir, x), files)
826 def flatten (tree, lst):
827 if type (tree) == type ([]):
829 if type (i) == type ([]):
835 if os.path.isdir ('$srcdir/CVS'):
836 subdirs = flatten (cvs_dirs ('.'), [])
839 command = 'cd %(srcdir)s \
840 && find . -name SConscript | sed s@/SConscript@@' % vars ()
841 subdirs = string.split (os.popen (command).read ())
844 and 'all' not in COMMAND_LINE_TARGETS\
845 and 'doc' not in COMMAND_LINE_TARGETS\
846 and 'web' not in COMMAND_LINE_TARGETS\
847 and 'install' not in COMMAND_LINE_TARGETS\
848 and 'clean' not in COMMAND_LINE_TARGETS:
849 subdirs = ['lily', 'lily/include',
850 'flower', 'flower/include',
856 if os.path.isdir ('$srcdir/CVS'):
857 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
859 src_files = ['foobar']
861 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
862 txt_files = map (lambda x: x + '.txt', readme_files)
866 # speeds up build by +- 5%
869 foo = map (lambda x: env.TXT (x + '.txt',
870 os.path.join ('Documentation/topdocs', x)),
872 tar_base = package.name + '-' + version
873 tar_name = tar_base + '.tar.gz'
874 ball_prefix = os.path.join (outdir, tar_base)
875 tar_ball = os.path.join (outdir, tar_name)
877 dist_files = src_files + txt_files
878 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
879 map (lambda x: env.Depends (tar_ball, x), ball_files)
880 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
881 'ln $SOURCE $TARGET'), dist_files)
882 tar = env.Command (tar_ball, src_files,
883 ['rm -f $$(find $TARGET.dir -name .sconsign)',
884 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
885 env.Alias ('tar', tar)
887 dist_ball = os.path.join (package.release_dir, tar_name)
888 env.Command (dist_ball, tar_ball,
889 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
890 + 'ln $SOURCE $TARGET')
891 env.Depends ('dist', dist_ball)
892 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
893 patch = env.PATCH (patch_name, tar_ball)
894 env.Depends (patch_name, dist_ball)
895 env.Alias ('release', patch)
899 web_base = os.path.join (outdir, 'web')
900 web_ball = web_base + '.tar.gz'
901 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
902 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
903 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
904 env['web_path'] = web_path
905 web_list = os.path.join (outdir, 'weblist')
906 # compatible make heritits
907 # fixme: generate in $outdir is cwd/builddir
908 env.Command (web_list,
909 ## this is correct, but takes > 5min if you have a peder :-)
912 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
913 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
914 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
915 'cd $absbuild && find Documentation input $web_path \
917 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
918 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
919 'cd $absbuild && ls *.html >> $TARGET',])
920 env.Command (web_ball, web_list,
921 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
922 #env.Alias ('web', web_ball)
923 www_base = os.path.join (outdir, 'www')
924 www_ball = www_base + '.tar.gz'
925 env.Command (www_ball, web_ball,
927 'mkdir -p $absbuild/$out/tmp',
928 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
929 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
930 + ' do mv $$i $$(dirname $$i)/out-www; done',
931 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
932 env.Alias ('web', www_ball)
936 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
937 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
938 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
939 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
941 'etags $ETAGSFLAGS $SOURCES')
943 # Note: SConscripts are only needed in directories where something needs
944 # to be done, building or installing
946 if os.path.exists (os.path.join (d, 'SConscript')):
947 b = os.path.join (env['build'], d, env['out'])
948 # Support clean sourcetree build (--srcdir build)
950 if os.path.abspath (b) != os.path.abspath (d):
951 env.BuildDir (b, d, duplicate = 0)
952 SConscript (os.path.join (b, 'SConscript'))