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 [ENVVAR=VALUE]... scons [OPTION=VALUE]... [TARGET|DIR]...
100 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
101 realclean, release, sconsclean, tar, TAGS
103 ENVVARS: BASH, CCFLAGS, CC, CXX, LIBS, PYTHON, SH...
104 (see SConstruct:config_vars)
110 config_cache = 'scons.cache'
111 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
112 os.unlink (config_cache)
114 # All config_vars can be set as ENVVAR, eg:
116 # CXX=g++-4.0 GS=~/usr/pkg/gs/bin/gs scons config
118 # append test_program variables automagically?
143 # Put your favourite stuff in custom.py
144 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
145 opts.Add ('prefix', 'Install prefix', '/usr/')
146 opts.Add ('out', 'Output directory', 'out-scons')
147 opts.Add ('build', 'Build directory', '.')
148 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
150 BoolOption ('warnings', 'compile with -Wall and similiar',
152 BoolOption ('debugging', 'compile with debugging symbols',
154 BoolOption ('optimising', 'compile with optimising',
156 BoolOption ('shared', 'build shared libraries',
158 BoolOption ('static', 'build static libraries',
160 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
162 BoolOption ('verbose', 'run commands with verbose flag',
164 BoolOption ('checksums', 'use checksums instead of timestamps',
166 BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
170 srcdir = Dir ('.').srcnode ().abspath
172 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
174 package = packagepython.Package (srcdir)
175 version = packagepython.version_tuple_to_str (package.version)
177 ENV = { 'PATH' : os.environ['PATH'] }
178 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH', 'TEXMF']:
179 if os.environ.has_key (key):
180 ENV[key] = os.environ[key]
184 BYTEORDER = sys.byteorder.upper (),
187 CPPDEFINES = '-DHAVE_CONFIG_H',
188 MAKEINFO = 'LANG= makeinfo',
189 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
191 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
192 'usr/pkg/gnome/lib'),
193 os.path.join (os.environ['HOME'],
194 'usr/pkg/pango/lib')],
197 TOPLEVEL_VERSION = version,
200 Help (usage + opts.GenerateHelpText (env))
202 # Add all config_vars to opts, so that they will be read and saved
203 # together with the other configure options.
204 map (lambda x: opts.AddOptions ((x,)), config_vars)
207 for key in config_vars:
208 if os.environ.has_key (key):
209 env[key] = os.environ[key]
212 # Usability switch (Anthony Roach).
213 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
214 # First do: scons realclean .
216 SetOption ('max_drift', 1)
217 SetOption ('implicit_cache', 1)
218 elif env['checksums']:
219 # Always use checksums (makes more sense than timestamps).
220 SetOption ('max_drift', 0)
221 # Using *content* checksums prevents rebuilds after
222 # [re]configure if config.hh has not changed. Too bad that it
224 TargetSignatures ('content')
226 absbuild = Dir (env['build']).abspath
227 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
228 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
231 config_hh = os.path.join (outdir, 'config.hh')
232 version_hh = os.path.join (outdir, 'version.hh')
234 env.Alias ('config', config_cache)
236 cachedir = os.path.join (outdir, 'build-cache')
238 if not os.path.exists (cachedir):
239 os.makedirs (cachedir)
243 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
244 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
245 env['prefix'] = run_prefix
247 prefix = env['prefix']
248 bindir = os.path.join (prefix, 'bin')
249 sharedir = os.path.join (prefix, 'share')
250 libdir = os.path.join (prefix, 'lib')
251 libdir_package = os.path.join (libdir, package.name)
252 libdir_package_version = os.path.join (libdir_package, version)
253 localedir = os.path.join (sharedir, 'locale')
254 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
255 sharedir_package = os.path.join (sharedir, package.name)
256 sharedir_package_version = os.path.join (sharedir_package, version)
257 lilypondprefix = sharedir_package_version
272 def configure (target, source, env):
273 dre = re.compile ('\n(200[0-9]{5})')
274 vre = re.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
276 def get_version (program):
277 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
278 pipe = os.popen (command)
279 output = pipe.read ()
282 splits = re.sub ('^|\s', '\n', output)
283 date_hack = re.sub (dre, '\n0.0.\\1', splits)
284 m = re.match (vre, date_hack)
288 return string.split (v, '.')
290 def test_version (lst, full_name, minimal, description, package):
291 program = os.path.basename (full_name)
292 sys.stdout.write ('Checking %s version... ' % program)
293 actual = get_version (program)
296 lst.append ((description, package, minimal, program,
299 print string.join (actual, '.')
300 if map (string.atoi, actual) \
301 < map (string.atoi, string.split (minimal, '.')):
302 lst.append ((description, package, minimal, program,
303 string.join (actual, '.')))
307 def test_program (lst, program, minimal, description, package):
308 key = program.upper ()
310 key = re.sub ('\+', 'X', key)
311 key = re.sub ('-', '_', key)
312 sys.stdout.write ('Checking for %s ... ' % program)
313 if env.has_key (key):
315 sys.stdout.write ('(cached) ')
317 f = WhereIs (program)
321 lst.append ((description, package, minimal, program,
325 return test_version (lst, program, minimal, description, package)
327 def test_lib (lst, program, minimal, description, package):
328 # FIXME: test for Debian or RPM (or -foo?) based dists
329 # to guess (or get correct!: apt-cache search?)
331 #if os.system ('pkg-config --atleast-version=0 freetype2'):
333 if test_version (lst, program, minimal, description,
334 'lib%(package)s-dev or %(package)s-devel'
336 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
342 test_program (required, 'bash', '2.0', 'Bash', 'bash')
343 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
344 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
345 test_program (required, 'guile-config', '1.6', 'GUILE development',
346 'libguile-dev or guile-devel')
347 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
348 test_program (required, 'mftrace', '1.1.9',
349 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
350 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
351 test_program (required, 'python', '2.1', 'Python (www.python.org)',
353 test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
356 # Do not use bison 1.50 and 1.75.
357 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
358 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
360 test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
361 test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
363 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
365 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
366 test_program (optional, 'gs', '8.15',
367 'Ghostscript PostScript interpreter',
368 'gs or gs-afpl or gs-esp or gs-gpl')
369 test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
371 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
372 test_program (optional, 'perl', '4.0',
373 'Perl practical efficient readonly language', 'perl')
374 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
376 def CheckYYCurrentBuffer (context):
377 context.Message ('Checking for yy_current_buffer... ')
378 ret = conf.TryCompile ("""using namespace std;
379 #include <FlexLexer.h>
380 class yy_flex_lexer: public yyFlexLexer
385 yy_current_buffer = 0;
391 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
392 : CheckYYCurrentBuffer })
395 'DIRSEP' : "'%s'" % os.sep,
396 'PATHSEP' : "'%s'" % os.pathsep,
397 'PACKAGE': '"%s"' % package.name,
398 'DATADIR' : '"%s"' % sharedir,
399 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
400 'LOCALEDIR' : '"%s"' %localedir,
402 conf.env.Append (DEFINES = defines)
404 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
405 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
407 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
409 env.Append (CPPPATH = [PYTHON_INCLUDE])
411 headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
412 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
414 if conf.CheckCHeader (i):
415 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
416 conf.env['DEFINES'][key] = 1
418 ccheaders = ('sstream',)
420 if conf.CheckCXXHeader (i):
421 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
422 conf.env['DEFINES'][key] = 1
424 functions = ('chroot', 'fopencookie', 'funopen',
426 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
428 if 0 or conf.CheckFunc (i):
429 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
430 conf.env['DEFINES'][key] = 1
432 if conf.CheckYYCurrentBuffer ():
433 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
435 if conf.CheckLib ('dl'):
440 if env.has_key ('CPPPATH'):
441 cpppath = env['CPPPATH']
443 ## FIXME: linkage, check for libguile.h and scm_boot_guile
444 #this could happen after flower...
445 env.ParseConfig ('guile-config compile')
447 test_program (required, 'pkg-config', '0.9.0',
448 'pkg-config library compile manager', 'pkg-config')
449 if test_lib (required, 'freetype2', '0.0',
450 'Development files for FreeType 2 font engine',
452 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
454 if test_lib (required, 'pangoft2', '1.6.0',
455 'Development files for pango, with FreeType2',
457 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
459 if test_lib (optional, 'fontconfig', '2.2.0',
460 'Development files for fontconfig', 'fontconfig1'):
461 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
463 #this could happen only for compiling pango-*
465 test_lib (required, 'gtk+-2.0', '2.4.0',
466 'Development files for GTK+', 'gtk2.0')
469 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
470 # <system-dir>] speeds up SCons
471 env['CCFLAGS'] += map (lambda x: '-I' + x,
472 env['CPPPATH'][len (cpppath):])
473 env['CPPPATH'] = cpppath
477 print '********************************'
478 print 'Please install required packages'
480 print '%s: %s-%s or newer (found: %s %s)' % i
485 print '*************************************'
486 print 'Consider installing optional packages'
488 print '%s: %s-%s or newer (found: %s %s)' % i
490 return conf.Finish ()
492 def config_header (target, source, env):
493 config = open (str (target[0]), 'w')
494 for i in list_sort (env['DEFINES'].keys ()):
495 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
497 env.Command (config_hh, config_cache, config_header)
513 if not d.has_key (lst[i]):
521 def uniquify_config_vars (env):
522 for i in config_vars:
523 if env.has_key (i) and type (env[i]) == type ([]):
524 env[i] = uniquify (env[i])
526 def save_config_cache (env):
527 ## FIXME: Is this smart, using option cache for saving
528 ## config.cache? I cannot seem to find the official method.
529 uniquify_config_vars (env)
530 opts.Save (config_cache, env)
532 if 'config' in COMMAND_LINE_TARGETS:
533 sys.stdout.write ('\n')
534 sys.stdout.write ('LilyPond configured')
535 sys.stdout.write ('\n')
536 sys.stdout.write ('Now run')
537 sys.stdout.write ('\n')
538 sys.stdout.write (' scons [TARGET|DIR]...')
539 sys.stdout.write ('\n')
540 sys.stdout.write ('\n')
541 sys.stdout.write ('Examples:')
542 sys.stdout.write ('\n')
543 sys.stdout.write (' scons lily # build lilypond')
544 sys.stdout.write ('\n')
545 sys.stdout.write (' scons all # build everything')
546 sys.stdout.write ('\n')
547 sys.stdout.write (' scons doc # build documentation')
548 sys.stdout.write ('\n')
550 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
551 ## sys.stdout.write ('\n')
553 elif not env['checksums']:
554 # When using timestams, config.hh is NEW. The next
555 # build triggers recompilation of everything. Exiting
556 # here makes SCons use the actual timestamp for config.hh
557 # and prevents recompiling everything the next run.
558 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
559 sys.stdout.write ('Running %s ... ' % command)
560 sys.stdout.write ('\n')
561 s = os.system (command)
565 # scons: *** Calling Configure from Builders is not supported.
566 # env.Command (config_cache, None, configure)
567 if not os.path.exists (config_cache) \
568 or (os.stat ('SConstruct')[stat.ST_MTIME]
569 > os.stat (config_cache)[stat.ST_MTIME]):
570 env = configure (None, None, env)
571 save_config_cache (env)
572 elif env['checksums']:
573 # just save everything
574 save_config_cache (env)
576 #urg how does #/ subst work?
578 SConscript ('buildscripts/builder.py')
580 env.PrependENVPath ('PATH',
581 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
583 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
586 'LILYPONDPREFIX' : LILYPONDPREFIX,
587 'TEXMF' : '{$LILYPONDPREFIX,'
588 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
591 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
592 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
593 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
596 # post-option environment-update
600 lilypond_datadir = sharedir_package,
601 localedir = localedir,
602 local_lilypond_datadir = sharedir_package_version,
603 lilypondprefix = lilypondprefix,
604 sharedir_package = sharedir_package,
605 sharedir_doc_package = sharedir_doc_package,
606 sharedir_package_version = sharedir_package_version,
607 libdir_package = libdir_package,
608 libdir_package_version = libdir_package_version,
610 # global build verbosity switch
611 __verbose = ' --verbose',
613 LILYPOND = BUILD_LILYPOND,
614 ABC2LY = BUILD_ABC2LY,
615 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
616 LILYPOND_BOOK_FORMAT = 'texi-html',
617 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
618 # PYTHONPATH = ['$absbuild/python/$out'],
619 TEXI2DVI_PAPERSIZE = '@afourpaper',
620 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
621 DVIPS_PAPERSIZE = 'a4',
622 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
624 '-u+ec-mftrace.map'],
625 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
628 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
630 env.Append (CCFLAGS = ['-g'])
631 if env['optimising']:
632 env.Append (CCFLAGS = '-O2')
634 env.Append (CCFLAGS = ['-W', '-Wall'])
635 env.Append (CXXFLAGS = ['-Wconversion'])
638 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
639 # FIXME: ParseConfig ignores -L flag?
640 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
643 env['__verbose'] = ' --verbose'
644 env['set__x'] = 'set -x;'
647 ## Explicit target and dependencies
649 if 'clean' in COMMAND_LINE_TARGETS:
650 # ugh: prevent reconfigure instead of clean
651 os.system ('touch %s' % config_cache)
653 command = sys.argv[0] + ' -c .'
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 if 'sconsclean' in COMMAND_LINE_TARGETS:
662 command = 'rm -rf scons.cache $(find . -name ".scon*")'
663 s = os.system (command)
664 if os.path.exists (config_cache):
665 os.unlink (config_cache)
668 if 'realclean' in COMMAND_LINE_TARGETS:
669 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
670 sys.stdout.write ('Running %s ... ' % command)
671 sys.stdout.write ('\n')
672 s = os.system (command)
673 if os.path.exists (config_cache):
674 os.unlink (config_cache)
677 # Declare SConscript phonies
678 env.Alias ('minimal', config_cache)
681 env.Alias ('mf-essential', config_cache)
682 env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
683 env.Alias ('all', ['minimal', 'mf', '.'])
686 env.Alias ('minimal', ['python', 'mf', 'lily'])
687 env.Alias ('all', ['minimal', '.'])
690 # Do we want the doc/web separation?
694 'Documentation/user',
695 'Documentation/topdocs',
696 'Documentation/bibliography',
699 # Without target arguments, do minimal build
700 if not COMMAND_LINE_TARGETS:
701 env.Default (['minimal'])
703 # GNU Make rerouting compat:
704 env.Alias ('web', 'doc')
707 env.Command (version_hh, '#/VERSION',
708 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
710 # post-config environment update
712 run_prefix = run_prefix,
713 LILYPONDPREFIX = LILYPONDPREFIX,
715 # FIXME: move to lily/SConscript?
716 LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
717 CPPPATH = [outdir, ],
718 LILYPOND_PATH = ['.',
720 '$srcdir/input/regression',
721 '$srcdir/input/test',
722 '$srcdir/input/tutorial',
723 '$srcdir/Documentation/user',
725 # os.path.join (absbuild, 'Documentation',
727 # os.path.join (absbuild, 'Documentation/user',
730 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
731 '$absbuild/Documentation/user/$out'],
734 def symlink_tree (target, source, env):
740 if not os.path.isdir (dir):
741 if os.path.exists (dir):
745 map (mkdir, string.split (dir, os.sep))
746 def symlink (src, dst):
748 dir = os.path.dirname (dst)
751 frm = os.path.join (srcdir, src[1:])
753 depth = len (string.split (dir, '/'))
754 if src.find ('@') > -1:
755 frm = os.path.join ('../' * depth,
756 string.replace (src, '@',
759 frm = os.path.join ('../' * depth, src,
762 frm = os.path.join (frm, os.path.basename (dst))
764 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
765 os.symlink (frm, os.path.basename (dst))
766 shutil.rmtree (run_prefix)
767 prefix = os.path.join (env['out'], 'usr')
768 map (lambda x: symlink (x[0], os.path.join (prefix,
769 x[1] % {'ver' : version})),
772 # /$ := add dst file_name
773 (('python', 'lib/lilypond/python'),
775 ('python', 'share/lilypond/%(ver)s/python'),
776 ('lily/', 'bin/lilypond'),
777 ('scripts/', 'bin/convert-ly'),
778 ('scripts/', 'bin/lilypond-book'),
779 ('scripts/', 'bin/ps2png'),
780 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
781 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
782 ('#ps/music-drawing-routines.ps',
783 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
784 ('mf', 'share/lilypond/%(ver)s/otf'),
785 ('mf', 'share/lilypond/%(ver)s/tfm'),
786 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
787 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
788 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
789 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
790 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
791 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
792 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
793 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
794 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
795 ('#ly', 'share/lilypond/%(ver)s/ly'),
796 ('#scm', 'share/lilypond/%(ver)s/scm'),
797 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
798 ('#ps', 'share/lilypond/%(ver)s/ps'),
799 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
800 ('elisp', 'share/lilypond/%(ver)s/elisp')))
802 print "FIXME: BARF BARF BARF"
806 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
808 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
809 dir = os.path.join (absbuild, prefix, ext)
810 os.system ('rm -f ' + dir)
813 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
817 env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
818 env.Depends ('lily', LILYPONDPREFIX)
819 env.Depends ('doc', LILYPONDPREFIX)
825 def cvs_entry_is_dir (line):
826 return line[0] == 'D' and line[-2] == '/'
828 def cvs_entry_is_file (line):
829 return line[0] == '/' and line[-2] == '/'
832 entries = os.path.join (dir, 'CVS/Entries')
833 if not os.path.exists (entries):
835 entries = open (entries).readlines ()
836 dir_entries = filter (cvs_entry_is_dir, entries)
837 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
839 return dirs + map (cvs_dirs, dirs)
842 entries = os.path.join (dir, 'CVS/Entries')
843 if not os.path.exists (entries):
845 entries = open (entries).readlines ()
846 file_entries = filter (cvs_entry_is_file, entries)
847 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
848 return map (lambda x: os.path.join (dir, x), files)
850 def flatten (tree, lst):
851 if type (tree) == type ([]):
853 if type (i) == type ([]):
859 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
860 subdirs = flatten (cvs_dirs ('.'), [])
863 command = 'cd %(srcdir)s \
864 && find . -name SConscript | sed s@/SConscript@@' % vars ()
865 subdirs = string.split (os.popen (command).read ())
868 and 'all' not in COMMAND_LINE_TARGETS\
869 and 'doc' not in COMMAND_LINE_TARGETS\
870 and 'web' not in COMMAND_LINE_TARGETS\
871 and 'install' not in COMMAND_LINE_TARGETS\
872 and 'clean' not in COMMAND_LINE_TARGETS:
873 subdirs = [ 'python',
879 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
880 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
882 src_files = ['foobar']
884 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
885 txt_files = map (lambda x: x + '.txt', readme_files)
889 # speeds up build by +- 5%
892 foo = map (lambda x: env.TXT (x + '.txt',
893 os.path.join ('Documentation/topdocs', x)),
895 tar_base = package.name + '-' + version
896 tar_name = tar_base + '.tar.gz'
897 ball_prefix = os.path.join (outdir, tar_base)
898 tar_ball = os.path.join (outdir, tar_name)
900 dist_files = src_files + txt_files
901 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
902 map (lambda x: env.Depends (tar_ball, x), ball_files)
903 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
904 'ln $SOURCE $TARGET'), dist_files)
905 tar = env.Command (tar_ball, src_files,
906 ['rm -f $$(find $TARGET.dir -name .sconsign)',
907 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
908 env.Alias ('tar', tar)
910 dist_ball = os.path.join (package.release_dir, tar_name)
911 env.Command (dist_ball, tar_ball,
912 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
913 + 'ln $SOURCE $TARGET')
914 env.Depends ('dist', dist_ball)
915 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
916 patch = env.PATCH (patch_name, tar_ball)
917 env.Depends (patch_name, dist_ball)
918 env.Alias ('release', patch)
922 web_base = os.path.join (outdir, 'web')
923 web_ball = web_base + '.tar.gz'
924 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
925 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
926 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
927 env['web_path'] = web_path
928 web_list = os.path.join (outdir, 'weblist')
929 # compatible make heritits
930 # fixme: generate in $outdir is cwd/builddir
931 env.Command (web_list,
932 ## Adding 'doc' dependency is correct, but takes
933 ## > 5min extra if you have a peder :-)
937 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
938 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
939 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
940 'cd $absbuild && find Documentation input $web_path \
942 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
943 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
944 'cd $absbuild && ls *.html >> $TARGET',])
945 env.Command (web_ball, web_list,
946 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
947 #env.Alias ('web', web_ball)
948 www_base = os.path.join (outdir, 'www')
949 www_ball = www_base + '.tar.gz'
950 env.Command (www_ball, web_ball,
952 'mkdir -p $absbuild/$out/tmp',
953 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
954 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
955 + ' do mv $$i $$(dirname $$i)/out-www; done',
956 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
957 env.Alias ('web', www_ball)
961 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
962 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
963 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
964 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
966 'etags $ETAGSFLAGS $SOURCES')
968 # Note: SConscripts are only needed in directories where something needs
969 # to be done, building or installing
971 if os.path.exists (os.path.join (d, 'SConscript')):
972 b = os.path.join (env['build'], d, env['out'])
973 # Support clean sourcetree build (--srcdir build)
975 if os.path.abspath (b) != os.path.abspath (d):
976 env.BuildDir (b, d, duplicate = 0)
977 SConscript (os.path.join (b, 'SConscript'))