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 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*).*$',
275 def get_version (program):
276 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
277 pipe = os.popen (command)
278 output = pipe.read ()
281 v = re.sub (vre, '\\1', output)
284 return string.split (v, '.')
286 def test_version (lst, full_name, minimal, description, package):
287 program = os.path.basename (full_name)
288 sys.stdout.write ('Checking %s version... ' % program)
289 actual = get_version (program)
292 lst.append ((description, package, minimal, program,
295 print string.join (actual, '.')
296 if map (string.atoi, actual) \
297 < map (string.atoi, string.split (minimal, '.')):
298 lst.append ((description, package, minimal, program,
299 string.join (actual, '.')))
303 def test_program (lst, program, minimal, description, package):
304 key = program.upper ()
306 key = re.sub ('\+', 'X', key)
307 key = re.sub ('-', '_', key)
308 sys.stdout.write ('Checking for %s ... ' % program)
309 if env.has_key (key):
311 sys.stdout.write ('(cached) ')
313 f = WhereIs (program)
317 lst.append ((description, package, minimal, program,
321 return test_version (lst, program, minimal, description, package)
323 def test_lib (lst, program, minimal, description, package):
324 # FIXME: test for Debian or RPM (or -foo?) based dists
325 # to guess (or get correct!: apt-cache search?)
327 #if os.system ('pkg-config --atleast-version=0 freetype2'):
329 if test_version (lst, program, minimal, description,
330 'lib%(package)s-dev or %(package)s-devel'
332 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
338 test_program (required, 'bash', '2.0', 'Bash', 'bash')
339 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
340 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
341 test_program (required, 'guile-config', '1.6', 'GUILE development',
342 'libguile-dev or guile-devel')
343 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
344 test_program (required, 'mftrace', '1.1.9',
345 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
346 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
347 test_program (required, 'python', '2.1', 'Python (www.python.org)',
349 test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
352 # Do not use bison 1.50 and 1.75.
353 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
354 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
356 test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
357 # test_program (optional, 'fontforge', '0.0.20041224', 'FontForge',
359 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
361 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
362 test_program (optional, 'gs', '8.14',
363 'Ghostscript PostScript interpreter',
364 'gs or gs-afpl or gs-esp or gs-gpl')
365 test_program (optional, 'mftrace', '1.1.0', 'Metafont tracing Type1',
367 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
368 test_program (optional, 'perl', '4.0',
369 'Perl practical efficient readonly language', 'perl')
370 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
372 def CheckYYCurrentBuffer (context):
373 context.Message ('Checking for yy_current_buffer... ')
374 ret = conf.TryCompile ("""using namespace std;
375 #include <FlexLexer.h>
376 class yy_flex_lexer: public yyFlexLexer
381 yy_current_buffer = 0;
387 def CheckLibkpathseaSo (context):
389 if context.env.has_key ('CFLAGS'):
390 saveCFLAGS = context.env['CFLAGS']
391 CFLAGS_shared_no_debugging = filter (lambda x: x != '-g',
394 # FIXME: how does this work, with scons
395 context.env.Replace (CFLAGS = CFLAGS_shared_no_debugging)
396 #context.env.Replace (CFLAGS = '')
397 #context.env.Append (CFLAGS = ['-shared'])
398 context.Message ('Checking for libkpathsea... ')
399 ret = conf.TryLink ('''#include <kpathsea/kpathsea.h>
402 kpse_var_expand ("\$TEXMF");
406 context.env.Replace (CFLAGS = saveCFLAGS)
407 # FIXME: this prints 'ok' already
412 sys.stdout.write ('Checking for libkpathsea.so... ')
413 testfile = str (context.sconf.lastTarget)
414 shared_size = os.path.getsize (testfile)
415 ret = shared_size < 40000
422 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
423 : CheckYYCurrentBuffer,
425 : CheckLibkpathseaSo })
428 'DIRSEP' : "'%s'" % os.sep,
429 'PATHSEP' : "'%s'" % os.pathsep,
430 'PACKAGE': '"%s"' % package.name,
431 'DATADIR' : '"%s"' % sharedir,
432 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
433 'LOCALEDIR' : '"%s"' %localedir,
435 conf.env.Append (DEFINES = defines)
437 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
438 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
440 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
442 env.Append (CPPPATH = [PYTHON_INCLUDE])
444 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
447 if conf.CheckCHeader (i):
448 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
449 conf.env['DEFINES'][key] = 1
451 ccheaders = ('sstream',)
453 if conf.CheckCXXHeader (i):
454 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
455 conf.env['DEFINES'][key] = 1
457 functions = ('fopencookie', 'funopen',
458 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
460 if 0 or conf.CheckFunc (i):
461 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
462 conf.env['DEFINES'][key] = 1
464 if conf.CheckYYCurrentBuffer ():
465 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
467 if conf.CheckLibkpathseaSo ():
468 conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
470 if conf.CheckLib ('dl'):
473 if conf.CheckLib ('kpathsea'):
474 conf.env['DEFINES']['KPATHSEA'] = 1
477 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
478 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
479 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
480 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
484 if env.has_key ('CPPPATH'):
485 cpppath = env['CPPPATH']
487 ## FIXME: linkage, check for libguile.h and scm_boot_guile
488 #this could happen after flower...
489 env.ParseConfig ('guile-config compile')
491 test_program (required, 'pkg-config', '0.9.0',
492 'pkg-config library compile manager', 'pkg-config')
493 if test_lib (required, 'freetype2', '0.0',
494 'Development files for FreeType 2 font engine',
496 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
498 if test_lib (required, 'pangoft2', '1.6.0',
499 'Development files for pango, with FreeType2',
501 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
502 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
504 if test_lib (optional, 'fontconfig', '2.2.0',
505 'Development files for fontconfig', 'fontconfig1'):
506 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
508 #this could happen only for compiling pango-*
510 test_lib (required, 'gtk+-2.0', '2.4.0',
511 'Development files for GTK+', 'gtk2.0')
512 if test_lib (required, 'pango', '1.6.0',
513 'Development files for pango', 'pango1.0'):
514 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
516 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
517 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
519 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
520 # <system-dir>] speeds up SCons
521 env['CCFLAGS'] += map (lambda x: '-I' + x,
522 env['CPPPATH'][len (cpppath):])
523 env['CPPPATH'] = cpppath
527 print '********************************'
528 print 'Please install required packages'
530 print '%s: %s-%s or newer (found: %s %s)' % i
535 print '*************************************'
536 print 'Consider installing optional packages'
538 print '%s: %s-%s or newer (found: %s %s)' % i
540 return conf.Finish ()
542 def config_header (target, source, env):
543 config = open (str (target[0]), 'w')
544 for i in list_sort (env['DEFINES'].keys ()):
545 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
547 env.Command (config_hh, config_cache, config_header)
563 if not d.has_key (lst[i]):
571 def uniquify_config_vars (env):
572 for i in config_vars:
573 if env.has_key (i) and type (env[i]) == type ([]):
574 env[i] = uniquify (env[i])
576 def save_config_cache (env):
577 ## FIXME: Is this smart, using option cache for saving
578 ## config.cache? I cannot seem to find the official method.
579 uniquify_config_vars (env)
580 opts.Save (config_cache, env)
582 if 'config' in COMMAND_LINE_TARGETS:
583 sys.stdout.write ('\n')
584 sys.stdout.write ('LilyPond configured')
585 sys.stdout.write ('\n')
586 sys.stdout.write ('Now run')
587 sys.stdout.write ('\n')
588 sys.stdout.write (' scons [TARGET|DIR]...')
589 sys.stdout.write ('\n')
590 sys.stdout.write ('\n')
591 sys.stdout.write ('Examples:')
592 sys.stdout.write ('\n')
593 sys.stdout.write (' scons lily # build lilypond')
594 sys.stdout.write ('\n')
595 sys.stdout.write (' scons all # build everything')
596 sys.stdout.write ('\n')
597 sys.stdout.write (' scons doc # build documentation')
598 sys.stdout.write ('\n')
600 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
601 ## sys.stdout.write ('\n')
603 elif not env['checksums']:
604 # When using timestams, config.hh is NEW. The next
605 # build triggers recompilation of everything. Exiting
606 # here makes SCons use the actual timestamp for config.hh
607 # and prevents recompiling everything the next run.
608 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
609 sys.stdout.write ('Running %s ... ' % command)
610 sys.stdout.write ('\n')
611 s = os.system (command)
615 # scons: *** Calling Configure from Builders is not supported.
616 # env.Command (config_cache, None, configure)
617 if not os.path.exists (config_cache) \
618 or (os.stat ('SConstruct')[stat.ST_MTIME]
619 > os.stat (config_cache)[stat.ST_MTIME]):
620 env = configure (None, None, env)
621 save_config_cache (env)
622 elif env['checksums']:
623 # just save everything
624 save_config_cache (env)
626 #urg how does #/ subst work?
628 SConscript ('buildscripts/builder.py')
630 env.PrependENVPath ('PATH',
631 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
633 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
636 #'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond/', version),
637 'LILYPONDPREFIX' : LILYPONDPREFIX,
638 # ugh, can't use LILYPONDPREFIX here
639 #'TEXMF' : '{' + os.path.join (run_prefix, 'share/lilypond/', version)\
641 'TEXMF' : '{$LILYPONDPREFIX,'
642 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
645 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
646 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
647 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
650 # post-option environment-update
654 lilypond_datadir = sharedir_package,
655 localedir = localedir,
656 local_lilypond_datadir = sharedir_package_version,
657 lilypondprefix = lilypondprefix,
658 sharedir_package = sharedir_package,
659 sharedir_doc_package = sharedir_doc_package,
660 sharedir_package_version = sharedir_package_version,
661 libdir_package = libdir_package,
662 libdir_package_version = libdir_package_version,
664 # global build verbosity switch
665 __verbose = ' --verbose',
667 LILYPOND = BUILD_LILYPOND,
668 ABC2LY = BUILD_ABC2LY,
669 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
670 LILYPOND_BOOK_FORMAT = 'texi-html',
671 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
672 # should not be necessary
673 # PYTHONPATH = ['$absbuild/python/$out'],
674 TEXI2DVI_PAPERSIZE = '@afourpaper',
675 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
676 DVIPS_PAPERSIZE = 'a4',
677 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
679 '-u+ec-mftrace.map'],
680 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
683 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
685 env.Append (CCFLAGS = ['-g'])
686 if env['optimising']:
687 env.Append (CCFLAGS = '-O2')
688 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
690 env.Append (CCFLAGS = ['-W', '-Wall'])
691 env.Append (CXXFLAGS = ['-Wconversion'])
694 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
695 # FIXME: ParseConfig ignores -L flag?
696 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
699 env['__verbose'] = ' --verbose'
700 env['set__x'] = 'set -x;'
703 ## Explicit target and dependencies
705 if 'clean' in COMMAND_LINE_TARGETS:
706 # ugh: prevent reconfigure instead of clean
707 os.system ('touch %s' % config_cache)
709 command = sys.argv[0] + ' -c .'
710 sys.stdout.write ('Running %s ... ' % command)
711 sys.stdout.write ('\n')
712 s = os.system (command)
713 if os.path.exists (config_cache):
714 os.unlink (config_cache)
717 if 'sconsclean' in COMMAND_LINE_TARGETS:
718 command = 'rm -rf scons.cache $(find . -name ".scon*")'
719 s = os.system (command)
720 if os.path.exists (config_cache):
721 os.unlink (config_cache)
724 if 'realclean' in COMMAND_LINE_TARGETS:
725 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
726 sys.stdout.write ('Running %s ... ' % command)
727 sys.stdout.write ('\n')
728 s = os.system (command)
729 if os.path.exists (config_cache):
730 os.unlink (config_cache)
733 # Declare SConscript phonies
734 env.Alias ('minimal', config_cache)
735 env.Alias ('mf-essential', config_cache)
737 env.Alias ('minimal', ['lily', 'mf-essential'])
738 env.Alias ('all', ['minimal', 'mf', '.'])
739 # Do we want the doc/web separation?
742 'Documentation/user',
743 'Documentation/topdocs',
744 'Documentation/bibliography',
747 # Without target arguments, do minimal build
748 if not COMMAND_LINE_TARGETS:
749 env.Default (['minimal'])
751 # GNU Make rerouting compat:
752 env.Alias ('web', 'doc')
755 env.Command (version_hh, '#/VERSION',
756 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
758 # post-config environment update
760 run_prefix = run_prefix,
761 LILYPONDPREFIX = LILYPONDPREFIX,
763 # FIXME: move to lily/SConscript?
764 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
765 os.path.join (absbuild, 'kpath-guile', env['out']),],
766 CPPPATH = [outdir, ],
767 LILYPOND_PATH = ['.',
769 '$srcdir/input/regression',
770 '$srcdir/input/test',
771 '$srcdir/input/tutorial',
772 '$srcdir/Documentation/user',
774 # os.path.join (absbuild, 'Documentation',
776 # os.path.join (absbuild, 'Documentation/user',
779 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
780 '$absbuild/Documentation/user/$out'],
783 def symlink_tree (target, source, env):
789 if not os.path.isdir (dir):
790 if os.path.exists (dir):
794 map (mkdir, string.split (dir, os.sep))
795 def symlink (src, dst):
797 dir = os.path.dirname (dst)
800 frm = os.path.join (srcdir, src[1:])
802 depth = len (string.split (dir, '/'))
803 if src.find ('@') > -1:
804 frm = os.path.join ('../' * depth,
805 string.replace (src, '@',
808 frm = os.path.join ('../' * depth, src,
811 frm = os.path.join (frm, os.path.basename (dst))
813 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
814 os.symlink (frm, os.path.basename (dst))
815 shutil.rmtree (run_prefix)
816 prefix = os.path.join (env['out'], 'usr')
817 map (lambda x: symlink (x[0], os.path.join (prefix,
818 x[1] % {'ver' : version})),
821 # /$ := add dst file_name
822 (('python', 'lib/lilypond/python'),
824 ('python', 'share/lilypond/%(ver)s/python'),
825 ('lily/', 'bin/lilypond'),
826 ('scripts/', 'bin/convert-ly'),
827 ('scripts/', 'bin/lilypond-book'),
828 ('scripts/', 'bin/ps2png'),
829 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
830 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
831 ('#ps/music-drawing-routines.ps',
832 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
833 ('mf', 'share/lilypond/%(ver)s/otf'),
834 ('mf', 'share/lilypond/%(ver)s/tfm'),
835 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
836 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
837 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
838 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
839 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
840 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
841 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
842 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
843 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
844 ('#ly', 'share/lilypond/%(ver)s/ly'),
845 ('#scm', 'share/lilypond/%(ver)s/scm'),
846 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
847 ('#ps', 'share/lilypond/%(ver)s/ps'),
848 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
849 ('elisp', 'share/lilypond/%(ver)s/elisp')))
851 print "FIXME: BARF BARF BARF"
855 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
857 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
858 dir = os.path.join (absbuild, prefix, ext)
859 os.system ('rm -f ' + dir)
862 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
866 if 1: #env['debugging']:
867 stamp = os.path.join (run_prefix, 'stamp')
868 env.Command (stamp, ['#/SConstruct', '#/VERSION'],
869 [symlink_tree, 'touch $TARGET'])
870 env.Depends ('lily', stamp)
876 def cvs_entry_is_dir (line):
877 return line[0] == 'D' and line[-2] == '/'
879 def cvs_entry_is_file (line):
880 return line[0] == '/' and line[-2] == '/'
883 entries = os.path.join (dir, 'CVS/Entries')
884 if not os.path.exists (entries):
886 entries = open (entries).readlines ()
887 dir_entries = filter (cvs_entry_is_dir, entries)
888 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
890 return dirs + map (cvs_dirs, dirs)
893 entries = os.path.join (dir, 'CVS/Entries')
894 if not os.path.exists (entries):
896 entries = open (entries).readlines ()
897 file_entries = filter (cvs_entry_is_file, entries)
898 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
899 return map (lambda x: os.path.join (dir, x), files)
901 def flatten (tree, lst):
902 if type (tree) == type ([]):
904 if type (i) == type ([]):
910 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
911 subdirs = flatten (cvs_dirs ('.'), [])
914 command = 'cd %(srcdir)s \
915 && find . -name SConscript | sed s@/SConscript@@' % vars ()
916 subdirs = string.split (os.popen (command).read ())
919 and 'all' not in COMMAND_LINE_TARGETS\
920 and 'doc' not in COMMAND_LINE_TARGETS\
921 and 'web' not in COMMAND_LINE_TARGETS\
922 and 'install' not in COMMAND_LINE_TARGETS\
923 and 'clean' not in COMMAND_LINE_TARGETS:
931 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
932 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
934 src_files = ['foobar']
936 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
937 txt_files = map (lambda x: x + '.txt', readme_files)
941 # speeds up build by +- 5%
944 foo = map (lambda x: env.TXT (x + '.txt',
945 os.path.join ('Documentation/topdocs', x)),
947 tar_base = package.name + '-' + version
948 tar_name = tar_base + '.tar.gz'
949 ball_prefix = os.path.join (outdir, tar_base)
950 tar_ball = os.path.join (outdir, tar_name)
952 dist_files = src_files + txt_files
953 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
954 map (lambda x: env.Depends (tar_ball, x), ball_files)
955 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
956 'ln $SOURCE $TARGET'), dist_files)
957 tar = env.Command (tar_ball, src_files,
958 ['rm -f $$(find $TARGET.dir -name .sconsign)',
959 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
960 env.Alias ('tar', tar)
962 dist_ball = os.path.join (package.release_dir, tar_name)
963 env.Command (dist_ball, tar_ball,
964 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
965 + 'ln $SOURCE $TARGET')
966 env.Depends ('dist', dist_ball)
967 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
968 patch = env.PATCH (patch_name, tar_ball)
969 env.Depends (patch_name, dist_ball)
970 env.Alias ('release', patch)
974 web_base = os.path.join (outdir, 'web')
975 web_ball = web_base + '.tar.gz'
976 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
977 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
978 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
979 env['web_path'] = web_path
980 web_list = os.path.join (outdir, 'weblist')
981 # compatible make heritits
982 # fixme: generate in $outdir is cwd/builddir
983 env.Command (web_list,
984 ## Adding 'doc' dependency is correct, but takes
985 ## > 5min extra if you have a peder :-)
989 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
990 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
991 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
992 'cd $absbuild && find Documentation input $web_path \
994 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
995 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
996 'cd $absbuild && ls *.html >> $TARGET',])
997 env.Command (web_ball, web_list,
998 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
999 #env.Alias ('web', web_ball)
1000 www_base = os.path.join (outdir, 'www')
1001 www_ball = www_base + '.tar.gz'
1002 env.Command (www_ball, web_ball,
1004 'mkdir -p $absbuild/$out/tmp',
1005 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
1006 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
1007 + ' do mv $$i $$(dirname $$i)/out-www; done',
1008 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
1009 env.Alias ('web', www_ball)
1013 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
1014 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
1015 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
1016 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
1018 'etags $ETAGSFLAGS $SOURCES')
1020 # Note: SConscripts are only needed in directories where something needs
1021 # to be done, building or installing
1023 if os.path.exists (os.path.join (d, 'SConscript')):
1024 b = os.path.join (env['build'], d, env['out'])
1025 # Support clean sourcetree build (--srcdir build)
1027 if os.path.abspath (b) != os.path.abspath (d):
1028 env.BuildDir (b, d, duplicate = 0)
1029 SConscript (os.path.join (b, 'SConscript'))