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, 96, 92)
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'))
176 package = packagepython.Package (srcdir)
177 version = packagepython.version_tuple_to_str (package.version)
179 ENV = { 'PATH' : os.environ['PATH'] }
180 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH', 'TEXMF']:
181 if os.environ.has_key (key):
182 ENV[key] = os.environ[key]
186 BYTEORDER = sys.byteorder.upper (),
189 CPPDEFINES = '-DHAVE_CONFIG_H',
190 MAKEINFO = 'LANG= makeinfo',
191 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
193 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
194 'usr/pkg/gnome/lib'),
195 os.path.join (os.environ['HOME'],
196 'usr/pkg/pango/lib')],
199 TOPLEVEL_VERSION = version,
202 Help (usage + opts.GenerateHelpText (env))
204 # Add all config_vars to opts, so that they will be read and saved
205 # together with the other configure options.
206 map (lambda x: opts.AddOptions ((x,)), config_vars)
209 for key in config_vars:
210 if os.environ.has_key (key):
211 env[key] = os.environ[key]
214 # Usability switch (Anthony Roach).
215 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
216 # First do: scons realclean .
218 SetOption ('max_drift', 1)
219 SetOption ('implicit_cache', 1)
220 elif env['checksums']:
221 # Always use checksums (makes more sense than timestamps).
222 SetOption ('max_drift', 0)
223 # Using *content* checksums prevents rebuilds after
224 # [re]configure if config.hh has not changed. Too bad that it
226 TargetSignatures ('content')
228 absbuild = Dir (env['build']).abspath
229 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
230 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
233 config_hh = os.path.join (outdir, 'config.hh')
234 version_hh = os.path.join (outdir, 'version.hh')
236 env.Alias ('config', config_cache)
238 cachedir = os.path.join (outdir, 'build-cache')
240 if not os.path.exists (cachedir):
241 os.makedirs (cachedir)
245 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
246 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
247 env['prefix'] = run_prefix
249 prefix = env['prefix']
250 bindir = os.path.join (prefix, 'bin')
251 sharedir = os.path.join (prefix, 'share')
252 libdir = os.path.join (prefix, 'lib')
253 libdir_package = os.path.join (libdir, package.name)
254 libdir_package_version = os.path.join (libdir_package, version)
255 localedir = os.path.join (sharedir, 'locale')
256 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
257 sharedir_package = os.path.join (sharedir, package.name)
258 sharedir_package_version = os.path.join (sharedir_package, version)
259 lilypondprefix = sharedir_package_version
269 def symlink_tree (target, source, env):
275 if not os.path.isdir (dir):
276 if os.path.exists (dir):
280 map (mkdir, string.split (dir, os.sep))
281 def symlink (src, dst):
283 dir = os.path.dirname (dst)
286 frm = os.path.join (srcdir, src[1:])
288 depth = len (string.split (dir, '/'))
289 if src.find ('@') > -1:
290 frm = os.path.join ('../' * depth,
291 string.replace (src, '@',
294 frm = os.path.join ('../' * depth, src,
297 frm = os.path.join (frm, os.path.basename (dst))
299 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
300 os.symlink (frm, os.path.basename (dst))
301 shutil.rmtree (run_prefix)
302 prefix = os.path.join (env['out'], 'usr')
303 map (lambda x: symlink (x[0], os.path.join (prefix,
304 x[1] % {'ver' : version})),
307 # /$ := add dst file_name
308 (('python', 'lib/lilypond/python'),
310 ('python', 'share/lilypond/%(ver)s/python'),
311 ('lily/', 'bin/lilypond'),
312 ('scripts/', 'bin/convert-ly'),
313 ('scripts/', 'bin/lilypond-book'),
314 ('scripts/', 'bin/ps2png'),
315 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
316 ('#ps/music-drawing-routines.ps',
317 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
318 ('mf', 'share/lilypond/%(ver)s/otf'),
319 ('mf', 'share/lilypond/%(ver)s/tfm'),
320 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
321 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
322 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
323 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
324 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
325 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
326 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
327 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
328 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
329 ('#ly', 'share/lilypond/%(ver)s/ly'),
330 ('#scm', 'share/lilypond/%(ver)s/scm'),
331 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
332 ('#ps', 'share/lilypond/%(ver)s/ps'),
333 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
334 ('elisp', 'share/lilypond/%(ver)s/elisp')))
336 print "FIXME: BARF BARF BARF"
340 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
342 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
343 dir = os.path.join (absbuild, prefix, ext)
344 os.system ('rm -f ' + dir)
347 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
351 def configure (target, source, env):
352 dre = re.compile ('\n(200[0-9]{5})')
353 vre = re.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
355 def get_version (program):
356 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
357 pipe = os.popen (command)
358 output = pipe.read ()
361 splits = re.sub ('^|\s', '\n', output)
362 date_hack = re.sub (dre, '\n0.0.\\1', splits)
363 m = re.match (vre, date_hack)
367 return string.split (v, '.')
369 def test_version (lst, full_name, minimal, description, package):
370 program = os.path.basename (full_name)
371 sys.stdout.write ('Checking %s version... ' % program)
372 actual = get_version (program)
375 lst.append ((description, package, minimal, program,
378 print string.join (actual, '.')
379 if map (string.atoi, actual) \
380 < map (string.atoi, string.split (minimal, '.')):
381 lst.append ((description, package, minimal, program,
382 string.join (actual, '.')))
386 def test_program (lst, program, minimal, description, package):
387 key = program.upper ()
389 key = re.sub ('\+', 'X', key)
390 key = re.sub ('-', '_', key)
391 sys.stdout.write ('Checking for %s ... ' % program)
392 if env.has_key (key):
394 sys.stdout.write ('(cached) ')
396 f = WhereIs (program)
400 lst.append ((description, package, minimal, program,
404 return test_version (lst, program, minimal, description, package)
406 def test_lib (lst, program, minimal, description, package):
407 # FIXME: test for Debian or RPM (or -foo?) based dists
408 # to guess (or get correct!: apt-cache search?)
410 #if os.system ('pkg-config --atleast-version=0 freetype2'):
412 if test_version (lst, program, minimal, description,
413 'lib%(package)s-dev or %(package)s-devel'
415 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
421 test_program (required, 'bash', '2.0', 'Bash', 'bash')
422 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
423 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
424 test_program (required, 'guile-config', '1.6', 'GUILE development',
425 'libguile-dev or guile-devel')
426 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
427 test_program (required, 'mftrace', '1.1.9',
428 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
429 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
430 test_program (required, 'python', '2.1', 'Python (www.python.org)',
432 # Silly, and breaks with /bin/sh == dash
433 #test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
436 # Do not use bison 1.50 and 1.75.
437 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
438 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
440 test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
442 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
444 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
445 test_program (optional, 'gs', '8.15',
446 'Ghostscript PostScript interpreter',
447 'gs or gs-afpl or gs-esp or gs-gpl')
448 test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
450 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
451 test_program (optional, 'perl', '4.0',
452 'Perl practical efficient readonly language', 'perl')
453 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
455 def CheckYYCurrentBuffer (context):
456 context.Message ('Checking for yy_current_buffer... ')
457 ret = conf.TryCompile ("""using namespace std;
458 #include <FlexLexer.h>
459 class yy_flex_lexer: public yyFlexLexer
464 yy_current_buffer = 0;
470 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
471 : CheckYYCurrentBuffer })
474 'DIRSEP' : "'%s'" % os.sep,
475 'PATHSEP' : "'%s'" % os.pathsep,
476 'PACKAGE': '"%s"' % package.name,
477 'DATADIR' : '"%s"' % sharedir,
478 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
479 'LOCALEDIR' : '"%s"' %localedir,
481 conf.env.Append (DEFINES = defines)
483 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
484 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
486 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
488 env.Append (CPPPATH = [PYTHON_INCLUDE])
490 headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
491 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
493 if conf.CheckCHeader (i):
494 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
495 conf.env['DEFINES'][key] = 1
497 ccheaders = ('sstream',)
499 if conf.CheckCXXHeader (i):
500 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
501 conf.env['DEFINES'][key] = 1
503 functions = ('chroot', 'fopencookie', 'funopen',
505 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
507 if 0 or conf.CheckFunc (i):
508 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
509 conf.env['DEFINES'][key] = 1
511 if conf.CheckYYCurrentBuffer ():
512 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
514 if conf.CheckLib ('dl'):
519 if env.has_key ('CPPPATH'):
520 cpppath = env['CPPPATH']
522 ## FIXME: linkage, check for libguile.h and scm_boot_guile
523 #this could happen after flower...
524 env.ParseConfig ('guile-config compile')
526 test_program (required, 'pkg-config', '0.9.0',
527 'pkg-config library compile manager', 'pkg-config')
528 if test_lib (required, 'freetype2', '0.0',
529 'Development files for FreeType 2 font engine',
531 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
533 if test_lib (required, 'pangoft2', '1.6.0',
534 'Development files for pango, with FreeType2',
536 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
538 if test_lib (optional, 'fontconfig', '2.2.0',
539 'Development files for fontconfig', 'fontconfig1'):
540 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
542 #this could happen only for compiling pango-*
544 test_lib (required, 'gtk+-2.0', '2.4.0',
545 'Development files for GTK+', 'gtk2.0')
548 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
549 # <system-dir>] speeds up SCons
550 env['CCFLAGS'] += map (lambda x: '-I' + x,
551 env['CPPPATH'][len (cpppath):])
552 env['CPPPATH'] = cpppath
556 print '********************************'
557 print 'Please install required packages'
559 print '%s: %s-%s or newer (found: %s %s)' % i
564 print '*************************************'
565 print 'Consider installing optional packages'
567 print '%s: %s-%s or newer (found: %s %s)' % i
569 return conf.Finish ()
571 def config_header (target, source, env):
572 config = open (str (target[0]), 'w')
573 for i in sorted (env['DEFINES'].keys ()):
574 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
576 env.Command (config_hh, config_cache, config_header)
592 if not d.has_key (lst[i]):
600 def uniquify_config_vars (env):
601 for i in config_vars:
602 if env.has_key (i) and type (env[i]) == type ([]):
603 env[i] = uniquify (env[i])
605 def save_config_cache (env):
606 ## FIXME: Is this smart, using option cache for saving
607 ## config.cache? I cannot seem to find the official method.
608 uniquify_config_vars (env)
609 opts.Save (config_cache, env)
611 if 'config' in COMMAND_LINE_TARGETS:
612 sys.stdout.write ('\n')
613 sys.stdout.write ('LilyPond configured')
614 sys.stdout.write ('\n')
615 sys.stdout.write ('Now run')
616 sys.stdout.write ('\n')
617 sys.stdout.write (' scons [TARGET|DIR]...')
618 sys.stdout.write ('\n')
619 sys.stdout.write ('\n')
620 sys.stdout.write ('Examples:')
621 sys.stdout.write ('\n')
622 sys.stdout.write (' scons lily # build lilypond')
623 sys.stdout.write ('\n')
624 sys.stdout.write (' scons all # build everything')
625 sys.stdout.write ('\n')
626 sys.stdout.write (' scons doc # build documentation')
627 sys.stdout.write ('\n')
629 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
630 ## sys.stdout.write ('\n')
632 elif not env['checksums']:
633 # When using timestams, config.hh is NEW. The next
634 # build triggers recompilation of everything. Exiting
635 # here makes SCons use the actual timestamp for config.hh
636 # and prevents recompiling everything the next run.
637 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
638 sys.stdout.write ('Running %s ... ' % command)
639 sys.stdout.write ('\n')
640 s = os.system (command)
644 # scons: *** Calling Configure from Builders is not supported.
645 # env.Command (config_cache, None, configure)
646 if not os.path.exists (config_cache) \
647 or (os.stat ('SConstruct')[stat.ST_MTIME]
648 > os.stat (config_cache)[stat.ST_MTIME]):
649 env = configure (None, None, env)
650 save_config_cache (env)
651 elif env['checksums']:
652 # just save everything
653 save_config_cache (env)
655 #urg how does #/ subst work?
657 SConscript ('buildscripts/builder.py')
659 env.PrependENVPath ('PATH',
660 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
662 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
664 if not os.path.exists (LILYPONDPREFIX):
665 os.makedirs (LILYPONDPREFIX)
667 env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
668 env.Depends ('lily', LILYPONDPREFIX)
671 'LILYPONDPREFIX' : LILYPONDPREFIX,
672 'TEXMF' : '{$LILYPONDPREFIX,'
673 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
676 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
677 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
678 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
681 # post-option environment-update
685 lilypond_datadir = sharedir_package,
686 localedir = localedir,
687 local_lilypond_datadir = sharedir_package_version,
688 lilypondprefix = lilypondprefix,
689 sharedir_package = sharedir_package,
690 sharedir_doc_package = sharedir_doc_package,
691 sharedir_package_version = sharedir_package_version,
692 libdir_package = libdir_package,
693 libdir_package_version = libdir_package_version,
695 # global build verbosity switch
696 __verbose = ' --verbose',
698 LILYPOND = BUILD_LILYPOND,
699 ABC2LY = BUILD_ABC2LY,
700 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
701 LILYPOND_BOOK_FORMAT = 'texi-html',
702 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
703 # PYTHONPATH = ['$absbuild/python/$out'],
704 TEXI2DVI_PAPERSIZE = '@afourpaper',
705 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
706 DVIPS_PAPERSIZE = 'a4',
707 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
709 '-u+ec-mftrace.map'],
710 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
713 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
715 env.Append (CCFLAGS = ['-g'])
716 if env['optimising']:
717 env.Append (CCFLAGS = '-O2')
719 env.Append (CCFLAGS = ['-W', '-Wall'])
720 env.Append (CXXFLAGS = ['-Wconversion'])
723 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
724 # FIXME: ParseConfig ignores -L flag?
725 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
728 env['__verbose'] = ' --verbose'
729 env['set__x'] = 'set -x;'
732 ## Explicit target and dependencies
734 if 'clean' in COMMAND_LINE_TARGETS:
735 # ugh: prevent reconfigure instead of clean
736 os.system ('touch %s' % config_cache)
738 command = sys.argv[0] + ' -c .'
739 sys.stdout.write ('Running %s ... ' % command)
740 sys.stdout.write ('\n')
741 s = os.system (command)
742 if os.path.exists (config_cache):
743 os.unlink (config_cache)
746 if 'sconsclean' in COMMAND_LINE_TARGETS:
747 command = 'rm -rf scons.cache $(find . -name ".scon*")'
748 s = os.system (command)
749 if os.path.exists (config_cache):
750 os.unlink (config_cache)
753 if 'realclean' in COMMAND_LINE_TARGETS:
754 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
755 sys.stdout.write ('Running %s ... ' % command)
756 sys.stdout.write ('\n')
757 s = os.system (command)
758 if os.path.exists (config_cache):
759 os.unlink (config_cache)
766 # Declare SConscript phonies
767 env.Alias ('minimal', config_cache)
770 env.Alias ('mf-essential', config_cache)
771 env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
772 env.Alias ('all', ['minimal', 'mf', '.'])
775 env.Alias ('minimal', ['python', 'lily', 'mf'])
776 env.Alias ('all', ['minimal', '.'])
779 # Do we want the doc/web separation?
783 'Documentation/user',
784 'Documentation/topdocs',
785 'Documentation/bibliography',
788 # Without target arguments, do minimal build
789 if not COMMAND_LINE_TARGETS:
790 env.Default (['minimal'])
792 # GNU Make rerouting compat:
793 env.Alias ('web', 'doc')
796 env.Command (version_hh, '#/VERSION',
797 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
799 # post-config environment update
801 run_prefix = run_prefix,
802 LILYPONDPREFIX = LILYPONDPREFIX,
804 # FIXME: move to lily/SConscript?
805 LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
806 CPPPATH = [outdir, ],
807 LILYPOND_PATH = ['.',
809 '$srcdir/input/regression',
810 '$srcdir/input/test',
811 '$srcdir/input/tutorial',
812 '$srcdir/Documentation/user',
814 # os.path.join (absbuild, 'Documentation',
816 # os.path.join (absbuild, 'Documentation/user',
819 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
820 '$absbuild/Documentation/user/$out'],
827 def cvs_entry_is_dir (line):
828 return line[0] == 'D' and line[-2] == '/'
830 def cvs_entry_is_file (line):
831 return line[0] == '/' and line[-2] == '/'
834 entries = os.path.join (dir, 'CVS/Entries')
835 if not os.path.exists (entries):
837 entries = open (entries).readlines ()
838 dir_entries = filter (cvs_entry_is_dir, entries)
839 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
841 return dirs + map (cvs_dirs, dirs)
844 entries = os.path.join (dir, 'CVS/Entries')
845 if not os.path.exists (entries):
847 entries = open (entries).readlines ()
848 file_entries = filter (cvs_entry_is_file, entries)
849 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
850 return map (lambda x: os.path.join (dir, x), files)
852 def flatten (tree, lst):
853 if type (tree) == type ([]):
855 if type (i) == type ([]):
861 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
862 subdirs = flatten (cvs_dirs ('.'), [])
865 command = 'cd %(srcdir)s \
866 && find . -name SConscript | sed s@/SConscript@@' % vars ()
867 subdirs = string.split (os.popen (command).read ())
870 and 'all' not in COMMAND_LINE_TARGETS\
871 and 'doc' not in COMMAND_LINE_TARGETS\
872 and 'web' not in COMMAND_LINE_TARGETS\
873 and 'install' not in COMMAND_LINE_TARGETS\
874 and 'clean' not in COMMAND_LINE_TARGETS:
875 subdirs = [ 'python',
881 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
882 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
884 src_files = ['foobar']
886 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
887 txt_files = map (lambda x: x + '.txt', readme_files)
891 # speeds up build by +- 5%
894 foo = map (lambda x: env.TXT (x + '.txt',
895 os.path.join ('Documentation/topdocs', x)),
897 tar_base = package.name + '-' + version
898 tar_name = tar_base + '.tar.gz'
899 ball_prefix = os.path.join (outdir, tar_base)
900 tar_ball = os.path.join (outdir, tar_name)
902 dist_files = src_files + txt_files
903 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
904 map (lambda x: env.Depends (tar_ball, x), ball_files)
905 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
906 'ln $SOURCE $TARGET'), dist_files)
907 tar = env.Command (tar_ball, src_files,
908 ['rm -f $$(find $TARGET.dir -name .sconsign)',
909 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
910 env.Alias ('tar', tar)
912 dist_ball = os.path.join (package.release_dir, tar_name)
913 env.Command (dist_ball, tar_ball,
914 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
915 + 'ln $SOURCE $TARGET')
916 env.Depends ('dist', dist_ball)
917 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
918 patch = env.PATCH (patch_name, tar_ball)
919 env.Depends (patch_name, dist_ball)
920 env.Alias ('release', patch)
924 web_base = os.path.join (outdir, 'web')
925 web_ball = web_base + '.tar.gz'
926 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
927 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
928 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
929 env['web_path'] = web_path
930 web_list = os.path.join (outdir, 'weblist')
931 # compatible make heritits
932 # fixme: generate in $outdir is cwd/builddir
933 env.Command (web_list,
934 ## Adding 'doc' dependency is correct, but takes
935 ## > 5min extra if you have a peder :-)
939 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
940 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
941 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
942 'cd $absbuild && find Documentation input $web_path \
944 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
945 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
946 'cd $absbuild && ls *.html >> $TARGET',])
947 env.Command (web_ball, web_list,
948 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
949 #env.Alias ('web', web_ball)
950 www_base = os.path.join (outdir, 'www')
951 www_ball = www_base + '.tar.gz'
952 env.Command (www_ball, web_ball,
954 'mkdir -p $absbuild/$out/tmp',
955 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
956 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
957 + ' do mv $$i $$(dirname $$i)/out-www; done',
958 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
959 env.Alias ('web', www_ball)
963 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
964 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
965 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
966 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
968 'etags $ETAGSFLAGS $SOURCES')
970 # Note: SConscripts are only needed in directories where something needs
971 # to be done, building or installing
973 if os.path.exists (os.path.join (d, 'SConscript')):
974 b = os.path.join (env['build'], d, env['out'])
975 # Support clean sourcetree build (--srcdir build)
977 if os.path.abspath (b) != os.path.abspath (d):
978 env.BuildDir (b, d, duplicate = 0)
979 SConscript (os.path.join (b, 'SConscript'))