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'
112 # All config_vars can be set as ENVVAR, eg:
114 # CXX=g++-4.0 GS=~/usr/pkg/gs/bin/gs scons config
116 # append test_program variables automagically?
141 # Put your favourite stuff in custom.py
142 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
143 opts.Add ('prefix', 'Install prefix', '/usr/')
144 opts.Add ('out', 'Output directory', 'out-scons')
145 opts.Add ('build', 'Build directory', '.')
146 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
148 BoolOption ('warnings', 'compile with -Wall and similiar',
150 BoolOption ('debugging', 'compile with debugging symbols',
152 BoolOption ('optimising', 'compile with optimising',
154 BoolOption ('shared', 'build shared libraries',
156 BoolOption ('static', 'build static libraries',
158 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
160 BoolOption ('verbose', 'run commands with verbose flag',
162 BoolOption ('checksums', 'use checksums instead of timestamps',
164 BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
168 srcdir = Dir ('.').srcnode ().abspath
170 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
172 package = packagepython.Package (srcdir)
173 version = packagepython.version_tuple_to_str (package.version)
175 ENV = { 'PATH' : os.environ['PATH'] }
176 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH', 'TEXMF']:
177 if os.environ.has_key (key):
178 ENV[key] = os.environ[key]
182 BYTEORDER = sys.byteorder.upper (),
185 CPPDEFINES = '-DHAVE_CONFIG_H',
186 MAKEINFO = 'LANG= makeinfo',
187 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
189 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
190 'usr/pkg/gnome/lib'),
191 os.path.join (os.environ['HOME'],
192 'usr/pkg/pango/lib')],
195 TOPLEVEL_VERSION = version,
198 Help (usage + opts.GenerateHelpText (env))
200 # Add all config_vars to opts, so that they will be read and saved
201 # together with the other configure options.
202 map (lambda x: opts.AddOptions ((x,)), config_vars)
205 for key in config_vars:
206 if os.environ.has_key (key):
207 env[key] = os.environ[key]
210 # Usability switch (Anthony Roach).
211 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
212 # First do: scons realclean .
214 SetOption ('max_drift', 1)
215 SetOption ('implicit_cache', 1)
216 elif env['checksums']:
217 # Always use checksums (makes more sense than timestamps).
218 SetOption ('max_drift', 0)
219 # Using *content* checksums prevents rebuilds after
220 # [re]configure if config.hh has not changed. Too bad that it
222 TargetSignatures ('content')
224 absbuild = Dir (env['build']).abspath
225 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
226 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
229 config_hh = os.path.join (outdir, 'config.hh')
230 version_hh = os.path.join (outdir, 'version.hh')
232 env.Alias ('config', config_cache)
234 cachedir = os.path.join (outdir, 'build-cache')
236 if not os.path.exists (cachedir):
237 os.makedirs (cachedir)
241 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
242 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
243 env['prefix'] = run_prefix
245 prefix = env['prefix']
246 bindir = os.path.join (prefix, 'bin')
247 sharedir = os.path.join (prefix, 'share')
248 libdir = os.path.join (prefix, 'lib')
249 localedir = os.path.join (sharedir, 'locale')
250 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
251 sharedir_package = os.path.join (sharedir, package.name)
252 sharedir_package_version = os.path.join (sharedir_package, version)
253 lilypondprefix = sharedir_package_version
268 def configure (target, source, env):
269 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*).*$',
271 def get_version (program):
272 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
273 pipe = os.popen (command)
274 output = pipe.read ()
277 v = re.sub (vre, '\\1', output)
280 return string.split (v, '.')
282 def test_version (lst, full_name, minimal, description, package):
283 program = os.path.basename (full_name)
284 sys.stdout.write ('Checking %s version... ' % program)
285 actual = get_version (program)
288 lst.append ((description, package, minimal, program,
291 print string.join (actual, '.')
292 if map (string.atoi, actual) \
293 < map (string.atoi, string.split (minimal, '.')):
294 lst.append ((description, package, minimal, program,
295 string.join (actual, '.')))
299 def test_program (lst, program, minimal, description, package):
300 key = program.upper ()
302 key = re.sub ('\+', 'X', key)
303 key = re.sub ('-', '_', key)
304 sys.stdout.write ('Checking for %s ... ' % program)
305 if env.has_key (key):
307 sys.stdout.write ('(cached) ')
309 f = WhereIs (program)
313 lst.append ((description, package, minimal, program,
317 return test_version (lst, program, minimal, description, package)
319 def test_lib (lst, program, minimal, description):
320 # FIXME: test for Debian or RPM (or -foo?) based dists
321 # to guess (or get correct!: apt-cache search?)
323 #if os.system ('pkg-config --atleast-version=0 freetype2'):
325 if test_version (lst, program, minimal, description,
326 'lib%(program)s-dev or %(program)s-devel'
328 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
334 test_program (required, 'bash', '2.0', 'Bash', 'bash')
335 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
336 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
337 test_program (required, 'guile-config', '1.6', 'GUILE development',
338 'libguile-dev or guile-devel')
339 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
340 test_program (required, 'mftrace', '1.1.6', 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
341 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
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, 'foo', '2.0', 'Foomatic tester', 'bar')
348 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
350 test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
351 test_program (optional, 'fontforge', '0.0.20041224', 'FontForge', 'fontforge')
352 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
353 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
354 test_program (optional, 'gs', '8.14', 'Ghostscript PostScript interpreter', 'gs or gs-afpl or gs-esp or gs-gpl')
355 test_program (optional, 'mftrace', '1.1.0', 'Metafont tracing Type1',
357 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
358 test_program (optional, 'perl', '4.0',
359 'Perl practical efficient readonly language', 'perl')
360 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
362 def CheckYYCurrentBuffer (context):
363 context.Message ('Checking for yy_current_buffer... ')
364 ret = conf.TryLink ("""using namespace std;
365 #include <FlexLexer.h>
366 class yy_flex_lexer: public yyFlexLexer
371 yy_current_buffer = 0;
377 def CheckLibkpathseaSo (context):
379 if context.env.has_key ('CFLAGS'):
380 saveCFLAGS = context.env['CFLAGS']
381 CFLAGS_shared_no_debugging = filter (lambda x: x != '-g',
384 # FIXME: how does this work, with scons
385 context.env.Replace (CFLAGS = CFLAGS_shared_no_debugging)
386 #context.env.Replace (CFLAGS = '')
387 #context.env.Append (CFLAGS = ['-shared'])
388 context.Message ('Checking for libkpathsea... ')
389 ret = conf.TryLink ('''#include <kpathsea/kpathsea.h>
392 kpse_var_expand ("\$TEXMF");
396 context.env.Replace (CFLAGS = saveCFLAGS)
397 # FIXME: this prints 'ok' already
402 sys.stdout.write ('Checking for libkpathsea.so... ')
403 testfile = str (context.sconf.lastTarget)
404 shared_size = os.path.getsize (testfile)
405 ret = shared_size < 40000
412 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
413 : CheckYYCurrentBuffer,
415 : CheckLibkpathseaSo })
418 'DIRSEP' : "'%s'" % os.sep,
419 'PATHSEP' : "'%s'" % os.pathsep,
420 'PACKAGE': '"%s"' % package.name,
421 'DATADIR' : '"%s"' % sharedir,
422 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
423 'LOCALEDIR' : '"%s"' %localedir,
425 conf.env.Append (DEFINES = defines)
427 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
428 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
430 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
432 env.Append (CPPPATH = [PYTHON_INCLUDE])
434 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
437 if conf.CheckCHeader (i):
438 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
439 conf.env['DEFINES'][key] = 1
441 ccheaders = ('sstream',)
443 if conf.CheckCXXHeader (i):
444 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
445 conf.env['DEFINES'][key] = 1
447 functions = ('fopencookie', 'funopen',
448 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
450 if 0 or conf.CheckFunc (i):
451 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
452 conf.env['DEFINES'][key] = 1
454 if conf.CheckYYCurrentBuffer ():
455 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
457 if conf.CheckLibkpathseaSo ():
458 conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
460 if conf.CheckLib ('dl'):
463 if conf.CheckLib ('kpathsea'):
464 conf.env['DEFINES']['KPATHSEA'] = 1
467 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
468 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
469 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
470 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
474 if env.has_key ('CPPPATH'):
475 cpppath = env['CPPPATH']
477 ## FIXME: linkage, check for libguile.h and scm_boot_guile
478 #this could happen after flower...
479 env.ParseConfig ('guile-config compile')
481 test_program (required, 'pkg-config', '0.9.0',
482 'pkg-config library compile manager', 'pkg-config')
483 if test_lib (required, 'freetype2', '0.0',
484 'Development files for FreeType 2 font engine'):
485 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
487 if test_lib (required, 'pangoft2', '1.6.0',
488 'Development files for pango, with fontconfig2'):
489 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
490 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
492 if test_lib (optional, 'fontconfig', '2.2.0',
493 'Development files for fontconfig'):
494 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
496 #this could happen only for compiling pango-*
498 test_lib (required, 'gtk+-2.0', '2.4.0',
499 'Development files for GTK+')
500 if test_lib (required, 'pango', '1.6.0',
501 'Development files for pango'):
502 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
504 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
505 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
507 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
508 # <system-dir>] speeds up SCons
509 env['CCFLAGS'] += map (lambda x: '-I' + x,
510 env['CPPPATH'][len (cpppath):])
511 env['CPPPATH'] = cpppath
515 print '********************************'
516 print 'Please install required packages'
518 print '%s: %s-%s or newer (found: %s %s)' % i
523 print '*************************************'
524 print 'Consider installing optional packages'
526 print '%s: %s-%s or newer (found: %s %s)' % i
528 return conf.Finish ()
530 def config_header (target, source, env):
531 config = open (str (target[0]), 'w')
532 for i in list_sort (env['DEFINES'].keys ()):
533 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
535 env.Command (config_hh, config_cache, config_header)
551 if not d.has_key (lst[i]):
559 def uniquify_config_vars (env):
560 for i in config_vars:
561 if env.has_key (i) and type (env[i]) == type ([]):
562 env[i] = uniquify (env[i])
564 def save_config_cache (env):
565 ## FIXME: Is this smart, using option cache for saving
566 ## config.cache? I cannot seem to find the official method.
567 uniquify_config_vars (env)
568 opts.Save (config_cache, env)
570 if 'config' in COMMAND_LINE_TARGETS:
571 sys.stdout.write ('\n')
572 sys.stdout.write ('LilyPond configured')
573 sys.stdout.write ('\n')
574 sys.stdout.write ('now run')
575 sys.stdout.write ('\n')
576 sys.stdout.write (' scons [TARGET|DIR]...')
577 sys.stdout.write ('\n')
579 elif not env['checksums']:
580 # When using timestams, config.hh is NEW. The next
581 # build triggers recompilation of everything. Exiting
582 # here makes SCons use the actual timestamp for config.hh
583 # and prevents recompiling everything the next run.
584 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
585 sys.stdout.write ('Running %s ... ' % command)
586 sys.stdout.write ('\n')
587 s = os.system (command)
591 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
592 os.unlink (config_cache)
594 # scons: *** Calling Configure from Builders is not supported.
595 # env.Command (config_cache, None, configure)
596 if not os.path.exists (config_cache) \
597 or (os.stat ('SConstruct')[stat.ST_MTIME]
598 > os.stat (config_cache)[stat.ST_MTIME]):
599 env = configure (None, None, env)
600 save_config_cache (env)
601 elif env['checksums']:
602 # just save everything
603 save_config_cache (env)
605 #urg how does #/ subst work?
607 SConscript ('buildscripts/builder.py')
609 env.PrependENVPath ('PATH',
610 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
612 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
615 #'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond/', version),
616 'LILYPONDPREFIX' : LILYPONDPREFIX,
617 # ugh, can't use LILYPONDPREFIX here
618 #'TEXMF' : '{' + os.path.join (run_prefix, 'share/lilypond/', version)\
620 'TEXMF' : '{$LILYPONDPREFIX,'
621 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
624 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
625 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
626 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
629 # post-option environment-update
633 lilypond_datadir = sharedir_package,
634 localedir = localedir,
635 local_lilypond_datadir = sharedir_package_version,
636 lilypondprefix = lilypondprefix,
637 sharedir_package = sharedir_package,
638 sharedir_doc_package = sharedir_doc_package,
639 sharedir_package_version = sharedir_package_version,
641 # global build verbosity switch
642 __verbose = ' --verbose',
644 LILYPOND = BUILD_LILYPOND,
645 ABC2LY = BUILD_ABC2LY,
646 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
647 LILYPOND_BOOK_FORMAT = 'texi-html',
648 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
649 # should not be necessary
650 # PYTHONPATH = ['$absbuild/python/$out'],
651 TEXI2DVI_PAPERSIZE = '@afourpaper',
652 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
653 DVIPS_PAPERSIZE = 'a4',
654 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
656 '-u+ec-mftrace.map'],
657 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
661 env.Append (CCFLAGS = ['-g', '-pipe'])
662 if env['optimising']:
663 env.Append (CCFLAGS = '-O2')
664 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
666 env.Append (CCFLAGS = ['-W', '-Wall'])
667 env.Append (CXXFLAGS = ['-Wconversion'])
670 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
673 env['__verbose'] = ' --verbose'
674 env['set__x'] = 'set -x;'
677 ## Explicit target and dependencies
679 if 'clean' in COMMAND_LINE_TARGETS:
680 # ugh: prevent reconfigure instead of clean
681 os.system ('touch %s' % config_cache)
683 command = sys.argv[0] + ' -c .'
684 sys.stdout.write ('Running %s ... ' % command)
685 sys.stdout.write ('\n')
686 s = os.system (command)
687 if os.path.exists (config_cache):
688 os.unlink (config_cache)
691 if 'sconsclean' in COMMAND_LINE_TARGETS:
692 command = 'rm -rf scons.cache $(find . -name ".scon*")'
693 s = os.system (command)
694 if os.path.exists (config_cache):
695 os.unlink (config_cache)
698 if 'realclean' in COMMAND_LINE_TARGETS:
699 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
700 sys.stdout.write ('Running %s ... ' % command)
701 sys.stdout.write ('\n')
702 s = os.system (command)
703 if os.path.exists (config_cache):
704 os.unlink (config_cache)
707 # Declare SConscript phonies
708 env.Alias ('minimal', config_cache)
709 env.Alias ('mf-essential', config_cache)
711 env.Alias ('minimal', ['lily', 'mf-essential'])
712 env.Alias ('all', ['minimal', 'mf', '.'])
713 # Do we want the doc/web separation?
716 'Documentation/user',
717 'Documentation/topdocs',
718 'Documentation/bibliography',
721 # Without target arguments, do minimal build
722 if not COMMAND_LINE_TARGETS:
723 env.Default (['minimal'])
725 # GNU Make rerouting compat:
726 env.Alias ('web', 'doc')
729 env.Command (version_hh, '#/VERSION',
730 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
732 # post-config environment update
734 run_prefix = run_prefix,
735 LILYPONDPREFIX = LILYPONDPREFIX,
737 # FIXME: move to lily/SConscript?
738 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
739 os.path.join (absbuild, 'kpath-guile', env['out']),
740 os.path.join (absbuild, 'ttftool', env['out']),],
741 CPPPATH = [outdir, ],
742 LILYPOND_PATH = ['.', '$srcdir/input',
743 '$srcdir/input/regression',
744 '$srcdir/input/test',
745 '$srcdir/input/tutorial',
746 '$srcdir/Documentation/user',
748 # os.path.join (absbuild, 'Documentation',
750 # os.path.join (absbuild, 'Documentation/user',
753 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
754 '$absbuild/Documentation/user/$out'],
757 def symlink_tree (target, source, env):
763 if not os.path.isdir (dir):
764 if os.path.exists (dir):
768 map (mkdir, string.split (dir, os.sep))
769 def symlink (src, dst):
771 dir = os.path.dirname (dst)
774 frm = os.path.join (srcdir, src[1:])
776 depth = len (string.split (dir, '/'))
777 if src.find ('@') > -1:
778 frm = os.path.join ('../' * depth,
779 string.replace (src, '@',
782 frm = os.path.join ('../' * depth, src,
785 frm = os.path.join (frm, os.path.basename (dst))
787 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
788 os.symlink (frm, os.path.basename (dst))
789 shutil.rmtree (run_prefix)
790 prefix = os.path.join (env['out'], 'usr')
791 map (lambda x: symlink (x[0], os.path.join (prefix,
792 x[1] % {'ver' : version})),
795 # /$ := add dst file_name
796 (('python', 'lib/lilypond/python'),
798 ('python', 'share/lilypond/%(ver)s/python'),
799 ('lily/', 'bin/lilypond'),
800 ('scripts/', 'bin/convert-ly'),
801 ('scripts/', 'bin/lilypond-book'),
802 ('scripts/', 'bin/ps2png'),
803 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
804 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
805 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
806 ('mf', 'share/lilypond/%(ver)s/otf'),
807 ('mf', 'share/lilypond/%(ver)s/tfm'),
808 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
809 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
810 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
811 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
812 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
813 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
814 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
815 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
816 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
817 ('#ly', 'share/lilypond/%(ver)s/ly'),
818 ('#scm', 'share/lilypond/%(ver)s/scm'),
819 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
820 ('#ps', 'share/lilypond/%(ver)s/ps'),
821 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
822 ('elisp', 'share/lilypond/%(ver)s/elisp')))
824 print "FIXME: BARF BARF BARF"
828 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
830 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
831 dir = os.path.join (absbuild, prefix, ext)
832 os.system ('rm -f ' + dir)
835 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
840 stamp = os.path.join (run_prefix, 'stamp')
841 env.Command (stamp, ['#/SConstruct', '#/VERSION'],
842 [symlink_tree, 'touch $TARGET'])
843 env.Depends ('lily', stamp)
849 def cvs_entry_is_dir (line):
850 return line[0] == 'D' and line[-2] == '/'
852 def cvs_entry_is_file (line):
853 return line[0] == '/' and line[-2] == '/'
856 ENTRIES = os.path.join (dir, 'CVS/Entries')
857 if not os.path.exists (ENTRIES):
859 entries = open (ENTRIES).readlines ()
860 dir_entries = filter (cvs_entry_is_dir, entries)
861 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
863 return dirs + map (cvs_dirs, dirs)
866 ENTRIES = os.path.join (dir, 'CVS/Entries')
867 entries = open (ENTRIES).readlines ()
868 file_entries = filter (cvs_entry_is_file, entries)
869 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
870 return map (lambda x: os.path.join (dir, x), files)
872 def flatten (tree, lst):
873 if type (tree) == type ([]):
875 if type (i) == type ([]):
881 if os.path.isdir ('$srcdir/CVS'):
882 subdirs = flatten (cvs_dirs ('.'), [])
885 command = 'cd %(srcdir)s \
886 && find . -name SConscript | sed s@/SConscript@@' % vars ()
887 subdirs = string.split (os.popen (command).read ())
890 and 'all' not in COMMAND_LINE_TARGETS\
891 and 'doc' not in COMMAND_LINE_TARGETS\
892 and 'web' not in COMMAND_LINE_TARGETS\
893 and 'install' not in COMMAND_LINE_TARGETS\
894 and 'clean' not in COMMAND_LINE_TARGETS:
895 subdirs = ['lily', 'lily/include',
896 'flower', 'flower/include',
902 if os.path.isdir ('$srcdir/CVS'):
903 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
905 src_files = ['foobar']
907 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
908 txt_files = map (lambda x: x + '.txt', readme_files)
912 # speeds up build by +- 5%
915 foo = map (lambda x: env.TXT (x + '.txt',
916 os.path.join ('Documentation/topdocs', x)),
918 tar_base = package.name + '-' + version
919 tar_name = tar_base + '.tar.gz'
920 ball_prefix = os.path.join (outdir, tar_base)
921 tar_ball = os.path.join (outdir, tar_name)
923 dist_files = src_files + txt_files
924 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
925 map (lambda x: env.Depends (tar_ball, x), ball_files)
926 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
927 'ln $SOURCE $TARGET'), dist_files)
928 tar = env.Command (tar_ball, src_files,
929 ['rm -f $$(find $TARGET.dir -name .sconsign)',
930 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
931 env.Alias ('tar', tar)
933 dist_ball = os.path.join (package.release_dir, tar_name)
934 env.Command (dist_ball, tar_ball,
935 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
936 + 'ln $SOURCE $TARGET')
937 env.Depends ('dist', dist_ball)
938 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
939 patch = env.PATCH (patch_name, tar_ball)
940 env.Depends (patch_name, dist_ball)
941 env.Alias ('release', patch)
945 web_base = os.path.join (outdir, 'web')
946 web_ball = web_base + '.tar.gz'
947 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
948 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
949 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
950 env['web_path'] = web_path
951 web_list = os.path.join (outdir, 'weblist')
952 # compatible make heritits
953 # fixme: generate in $outdir is cwd/builddir
954 env.Command (web_list,
955 ## Adding 'doc' dependency is correct, but takes
956 ## > 5min extra if you have a peder :-)
960 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
961 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
962 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
963 'cd $absbuild && find Documentation input $web_path \
965 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
966 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
967 'cd $absbuild && ls *.html >> $TARGET',])
968 env.Command (web_ball, web_list,
969 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
970 #env.Alias ('web', web_ball)
971 www_base = os.path.join (outdir, 'www')
972 www_ball = www_base + '.tar.gz'
973 env.Command (www_ball, web_ball,
975 'mkdir -p $absbuild/$out/tmp',
976 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
977 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
978 + ' do mv $$i $$(dirname $$i)/out-www; done',
979 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
980 env.Alias ('web', www_ball)
984 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
985 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
986 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
987 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
989 'etags $ETAGSFLAGS $SOURCES')
991 # Note: SConscripts are only needed in directories where something needs
992 # to be done, building or installing
994 if os.path.exists (os.path.join (d, 'SConscript')):
995 b = os.path.join (env['build'], d, env['out'])
996 # Support clean sourcetree build (--srcdir build)
998 if os.path.abspath (b) != os.path.abspath (d):
999 env.BuildDir (b, d, duplicate = 0)
1000 SConscript (os.path.join (b, 'SConscript'))