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', 'share/lilypond/%(ver)s/dvips/ps'),
317 ('#ps/music-drawing-routines.ps',
318 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
319 ('mf', 'share/lilypond/%(ver)s/otf'),
320 ('mf', 'share/lilypond/%(ver)s/tfm'),
321 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
322 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
323 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
324 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
325 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
326 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
327 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
328 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
329 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
330 ('#ly', 'share/lilypond/%(ver)s/ly'),
331 ('#scm', 'share/lilypond/%(ver)s/scm'),
332 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
333 ('#ps', 'share/lilypond/%(ver)s/ps'),
334 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
335 ('elisp', 'share/lilypond/%(ver)s/elisp')))
337 print "FIXME: BARF BARF BARF"
341 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
343 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
344 dir = os.path.join (absbuild, prefix, ext)
345 os.system ('rm -f ' + dir)
348 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
352 def configure (target, source, env):
353 dre = re.compile ('\n(200[0-9]{5})')
354 vre = re.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
356 def get_version (program):
357 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
358 pipe = os.popen (command)
359 output = pipe.read ()
362 splits = re.sub ('^|\s', '\n', output)
363 date_hack = re.sub (dre, '\n0.0.\\1', splits)
364 m = re.match (vre, date_hack)
368 return string.split (v, '.')
370 def test_version (lst, full_name, minimal, description, package):
371 program = os.path.basename (full_name)
372 sys.stdout.write ('Checking %s version... ' % program)
373 actual = get_version (program)
376 lst.append ((description, package, minimal, program,
379 print string.join (actual, '.')
380 if map (string.atoi, actual) \
381 < map (string.atoi, string.split (minimal, '.')):
382 lst.append ((description, package, minimal, program,
383 string.join (actual, '.')))
387 def test_program (lst, program, minimal, description, package):
388 key = program.upper ()
390 key = re.sub ('\+', 'X', key)
391 key = re.sub ('-', '_', key)
392 sys.stdout.write ('Checking for %s ... ' % program)
393 if env.has_key (key):
395 sys.stdout.write ('(cached) ')
397 f = WhereIs (program)
401 lst.append ((description, package, minimal, program,
405 return test_version (lst, program, minimal, description, package)
407 def test_lib (lst, program, minimal, description, package):
408 # FIXME: test for Debian or RPM (or -foo?) based dists
409 # to guess (or get correct!: apt-cache search?)
411 #if os.system ('pkg-config --atleast-version=0 freetype2'):
413 if test_version (lst, program, minimal, description,
414 'lib%(package)s-dev or %(package)s-devel'
416 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
422 test_program (required, 'bash', '2.0', 'Bash', 'bash')
423 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
424 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
425 test_program (required, 'guile-config', '1.6', 'GUILE development',
426 'libguile-dev or guile-devel')
427 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
428 test_program (required, 'mftrace', '1.1.9',
429 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
430 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
431 test_program (required, 'python', '2.1', 'Python (www.python.org)',
433 # Silly, and breaks with /bin/sh == dash
434 #test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
437 # Do not use bison 1.50 and 1.75.
438 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
439 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
441 test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
442 test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
444 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
446 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
447 test_program (optional, 'gs', '8.15',
448 'Ghostscript PostScript interpreter',
449 'gs or gs-afpl or gs-esp or gs-gpl')
450 test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
452 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
453 test_program (optional, 'perl', '4.0',
454 'Perl practical efficient readonly language', 'perl')
455 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
457 def CheckYYCurrentBuffer (context):
458 context.Message ('Checking for yy_current_buffer... ')
459 ret = conf.TryCompile ("""using namespace std;
460 #include <FlexLexer.h>
461 class yy_flex_lexer: public yyFlexLexer
466 yy_current_buffer = 0;
472 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
473 : CheckYYCurrentBuffer })
476 'DIRSEP' : "'%s'" % os.sep,
477 'PATHSEP' : "'%s'" % os.pathsep,
478 'PACKAGE': '"%s"' % package.name,
479 'DATADIR' : '"%s"' % sharedir,
480 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
481 'LOCALEDIR' : '"%s"' %localedir,
483 conf.env.Append (DEFINES = defines)
485 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
486 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
488 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
490 env.Append (CPPPATH = [PYTHON_INCLUDE])
492 headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
493 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
495 if conf.CheckCHeader (i):
496 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
497 conf.env['DEFINES'][key] = 1
499 ccheaders = ('sstream',)
501 if conf.CheckCXXHeader (i):
502 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
503 conf.env['DEFINES'][key] = 1
505 functions = ('chroot', 'fopencookie', 'funopen',
507 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
509 if 0 or conf.CheckFunc (i):
510 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
511 conf.env['DEFINES'][key] = 1
513 if conf.CheckYYCurrentBuffer ():
514 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
516 if conf.CheckLib ('dl'):
521 if env.has_key ('CPPPATH'):
522 cpppath = env['CPPPATH']
524 ## FIXME: linkage, check for libguile.h and scm_boot_guile
525 #this could happen after flower...
526 env.ParseConfig ('guile-config compile')
528 test_program (required, 'pkg-config', '0.9.0',
529 'pkg-config library compile manager', 'pkg-config')
530 if test_lib (required, 'freetype2', '0.0',
531 'Development files for FreeType 2 font engine',
533 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
535 if test_lib (required, 'pangoft2', '1.6.0',
536 'Development files for pango, with FreeType2',
538 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
540 if test_lib (optional, 'fontconfig', '2.2.0',
541 'Development files for fontconfig', 'fontconfig1'):
542 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
544 #this could happen only for compiling pango-*
546 test_lib (required, 'gtk+-2.0', '2.4.0',
547 'Development files for GTK+', 'gtk2.0')
550 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
551 # <system-dir>] speeds up SCons
552 env['CCFLAGS'] += map (lambda x: '-I' + x,
553 env['CPPPATH'][len (cpppath):])
554 env['CPPPATH'] = cpppath
558 print '********************************'
559 print 'Please install required packages'
561 print '%s: %s-%s or newer (found: %s %s)' % i
566 print '*************************************'
567 print 'Consider installing optional packages'
569 print '%s: %s-%s or newer (found: %s %s)' % i
571 return conf.Finish ()
573 def config_header (target, source, env):
574 config = open (str (target[0]), 'w')
575 for i in sorted (env['DEFINES'].keys ()):
576 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
578 env.Command (config_hh, config_cache, config_header)
594 if not d.has_key (lst[i]):
602 def uniquify_config_vars (env):
603 for i in config_vars:
604 if env.has_key (i) and type (env[i]) == type ([]):
605 env[i] = uniquify (env[i])
607 def save_config_cache (env):
608 ## FIXME: Is this smart, using option cache for saving
609 ## config.cache? I cannot seem to find the official method.
610 uniquify_config_vars (env)
611 opts.Save (config_cache, env)
613 if 'config' in COMMAND_LINE_TARGETS:
614 sys.stdout.write ('\n')
615 sys.stdout.write ('LilyPond configured')
616 sys.stdout.write ('\n')
617 sys.stdout.write ('Now run')
618 sys.stdout.write ('\n')
619 sys.stdout.write (' scons [TARGET|DIR]...')
620 sys.stdout.write ('\n')
621 sys.stdout.write ('\n')
622 sys.stdout.write ('Examples:')
623 sys.stdout.write ('\n')
624 sys.stdout.write (' scons lily # build lilypond')
625 sys.stdout.write ('\n')
626 sys.stdout.write (' scons all # build everything')
627 sys.stdout.write ('\n')
628 sys.stdout.write (' scons doc # build documentation')
629 sys.stdout.write ('\n')
631 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
632 ## sys.stdout.write ('\n')
634 elif not env['checksums']:
635 # When using timestams, config.hh is NEW. The next
636 # build triggers recompilation of everything. Exiting
637 # here makes SCons use the actual timestamp for config.hh
638 # and prevents recompiling everything the next run.
639 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
640 sys.stdout.write ('Running %s ... ' % command)
641 sys.stdout.write ('\n')
642 s = os.system (command)
646 # scons: *** Calling Configure from Builders is not supported.
647 # env.Command (config_cache, None, configure)
648 if not os.path.exists (config_cache) \
649 or (os.stat ('SConstruct')[stat.ST_MTIME]
650 > os.stat (config_cache)[stat.ST_MTIME]):
651 env = configure (None, None, env)
652 save_config_cache (env)
653 elif env['checksums']:
654 # just save everything
655 save_config_cache (env)
657 #urg how does #/ subst work?
659 SConscript ('buildscripts/builder.py')
661 env.PrependENVPath ('PATH',
662 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
664 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
666 if not os.path.exists (LILYPONDPREFIX):
667 os.makedirs (LILYPONDPREFIX)
669 env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
670 env.Depends ('lily', LILYPONDPREFIX)
673 'LILYPONDPREFIX' : LILYPONDPREFIX,
674 'TEXMF' : '{$LILYPONDPREFIX,'
675 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
678 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
679 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
680 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
683 # post-option environment-update
687 lilypond_datadir = sharedir_package,
688 localedir = localedir,
689 local_lilypond_datadir = sharedir_package_version,
690 lilypondprefix = lilypondprefix,
691 sharedir_package = sharedir_package,
692 sharedir_doc_package = sharedir_doc_package,
693 sharedir_package_version = sharedir_package_version,
694 libdir_package = libdir_package,
695 libdir_package_version = libdir_package_version,
697 # global build verbosity switch
698 __verbose = ' --verbose',
700 LILYPOND = BUILD_LILYPOND,
701 ABC2LY = BUILD_ABC2LY,
702 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
703 LILYPOND_BOOK_FORMAT = 'texi-html',
704 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
705 # PYTHONPATH = ['$absbuild/python/$out'],
706 TEXI2DVI_PAPERSIZE = '@afourpaper',
707 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
708 DVIPS_PAPERSIZE = 'a4',
709 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
711 '-u+ec-mftrace.map'],
712 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
715 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
717 env.Append (CCFLAGS = ['-g'])
718 if env['optimising']:
719 env.Append (CCFLAGS = '-O2')
721 env.Append (CCFLAGS = ['-W', '-Wall'])
722 env.Append (CXXFLAGS = ['-Wconversion'])
725 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
726 # FIXME: ParseConfig ignores -L flag?
727 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
730 env['__verbose'] = ' --verbose'
731 env['set__x'] = 'set -x;'
734 ## Explicit target and dependencies
736 if 'clean' in COMMAND_LINE_TARGETS:
737 # ugh: prevent reconfigure instead of clean
738 os.system ('touch %s' % config_cache)
740 command = sys.argv[0] + ' -c .'
741 sys.stdout.write ('Running %s ... ' % command)
742 sys.stdout.write ('\n')
743 s = os.system (command)
744 if os.path.exists (config_cache):
745 os.unlink (config_cache)
748 if 'sconsclean' in COMMAND_LINE_TARGETS:
749 command = 'rm -rf scons.cache $(find . -name ".scon*")'
750 s = os.system (command)
751 if os.path.exists (config_cache):
752 os.unlink (config_cache)
755 if 'realclean' in COMMAND_LINE_TARGETS:
756 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
757 sys.stdout.write ('Running %s ... ' % command)
758 sys.stdout.write ('\n')
759 s = os.system (command)
760 if os.path.exists (config_cache):
761 os.unlink (config_cache)
768 # Declare SConscript phonies
769 env.Alias ('minimal', config_cache)
772 env.Alias ('mf-essential', config_cache)
773 env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
774 env.Alias ('all', ['minimal', 'mf', '.'])
777 env.Alias ('minimal', ['python', 'lily', 'mf'])
778 env.Alias ('all', ['minimal', '.'])
781 # Do we want the doc/web separation?
785 'Documentation/user',
786 'Documentation/topdocs',
787 'Documentation/bibliography',
790 # Without target arguments, do minimal build
791 if not COMMAND_LINE_TARGETS:
792 env.Default (['minimal'])
794 # GNU Make rerouting compat:
795 env.Alias ('web', 'doc')
798 env.Command (version_hh, '#/VERSION',
799 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
801 # post-config environment update
803 run_prefix = run_prefix,
804 LILYPONDPREFIX = LILYPONDPREFIX,
806 # FIXME: move to lily/SConscript?
807 LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
808 CPPPATH = [outdir, ],
809 LILYPOND_PATH = ['.',
811 '$srcdir/input/regression',
812 '$srcdir/input/test',
813 '$srcdir/input/tutorial',
814 '$srcdir/Documentation/user',
816 # os.path.join (absbuild, 'Documentation',
818 # os.path.join (absbuild, 'Documentation/user',
821 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
822 '$absbuild/Documentation/user/$out'],
829 def cvs_entry_is_dir (line):
830 return line[0] == 'D' and line[-2] == '/'
832 def cvs_entry_is_file (line):
833 return line[0] == '/' and line[-2] == '/'
836 entries = os.path.join (dir, 'CVS/Entries')
837 if not os.path.exists (entries):
839 entries = open (entries).readlines ()
840 dir_entries = filter (cvs_entry_is_dir, entries)
841 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
843 return dirs + map (cvs_dirs, dirs)
846 entries = os.path.join (dir, 'CVS/Entries')
847 if not os.path.exists (entries):
849 entries = open (entries).readlines ()
850 file_entries = filter (cvs_entry_is_file, entries)
851 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
852 return map (lambda x: os.path.join (dir, x), files)
854 def flatten (tree, lst):
855 if type (tree) == type ([]):
857 if type (i) == type ([]):
863 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
864 subdirs = flatten (cvs_dirs ('.'), [])
867 command = 'cd %(srcdir)s \
868 && find . -name SConscript | sed s@/SConscript@@' % vars ()
869 subdirs = string.split (os.popen (command).read ())
872 and 'all' not in COMMAND_LINE_TARGETS\
873 and 'doc' not in COMMAND_LINE_TARGETS\
874 and 'web' not in COMMAND_LINE_TARGETS\
875 and 'install' not in COMMAND_LINE_TARGETS\
876 and 'clean' not in COMMAND_LINE_TARGETS:
877 subdirs = [ 'python',
883 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
884 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
886 src_files = ['foobar']
888 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
889 txt_files = map (lambda x: x + '.txt', readme_files)
893 # speeds up build by +- 5%
896 foo = map (lambda x: env.TXT (x + '.txt',
897 os.path.join ('Documentation/topdocs', x)),
899 tar_base = package.name + '-' + version
900 tar_name = tar_base + '.tar.gz'
901 ball_prefix = os.path.join (outdir, tar_base)
902 tar_ball = os.path.join (outdir, tar_name)
904 dist_files = src_files + txt_files
905 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
906 map (lambda x: env.Depends (tar_ball, x), ball_files)
907 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
908 'ln $SOURCE $TARGET'), dist_files)
909 tar = env.Command (tar_ball, src_files,
910 ['rm -f $$(find $TARGET.dir -name .sconsign)',
911 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
912 env.Alias ('tar', tar)
914 dist_ball = os.path.join (package.release_dir, tar_name)
915 env.Command (dist_ball, tar_ball,
916 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
917 + 'ln $SOURCE $TARGET')
918 env.Depends ('dist', dist_ball)
919 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
920 patch = env.PATCH (patch_name, tar_ball)
921 env.Depends (patch_name, dist_ball)
922 env.Alias ('release', patch)
926 web_base = os.path.join (outdir, 'web')
927 web_ball = web_base + '.tar.gz'
928 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
929 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
930 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
931 env['web_path'] = web_path
932 web_list = os.path.join (outdir, 'weblist')
933 # compatible make heritits
934 # fixme: generate in $outdir is cwd/builddir
935 env.Command (web_list,
936 ## Adding 'doc' dependency is correct, but takes
937 ## > 5min extra if you have a peder :-)
941 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
942 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
943 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
944 'cd $absbuild && find Documentation input $web_path \
946 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
947 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
948 'cd $absbuild && ls *.html >> $TARGET',])
949 env.Command (web_ball, web_list,
950 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
951 #env.Alias ('web', web_ball)
952 www_base = os.path.join (outdir, 'www')
953 www_ball = www_base + '.tar.gz'
954 env.Command (www_ball, web_ball,
956 'mkdir -p $absbuild/$out/tmp',
957 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
958 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
959 + ' do mv $$i $$(dirname $$i)/out-www; done',
960 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
961 env.Alias ('web', www_ball)
965 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
966 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
967 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
968 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
970 'etags $ETAGSFLAGS $SOURCES')
972 # Note: SConscripts are only needed in directories where something needs
973 # to be done, building or installing
975 if os.path.exists (os.path.join (d, 'SConscript')):
976 b = os.path.join (env['build'], d, env['out'])
977 # Support clean sourcetree build (--srcdir build)
979 if os.path.abspath (b) != os.path.abspath (d):
980 env.BuildDir (b, d, duplicate = 0)
981 SConscript (os.path.join (b, 'SConscript'))