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 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, 'dvips', '0.0', 'Dvips', 'tetex-bin')
441 test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
443 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
445 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
446 test_program (optional, 'gs', '8.15',
447 'Ghostscript PostScript interpreter',
448 'gs or gs-afpl or gs-esp or gs-gpl')
449 test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
451 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
452 test_program (optional, 'perl', '4.0',
453 'Perl practical efficient readonly language', 'perl')
454 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
456 def CheckYYCurrentBuffer (context):
457 context.Message ('Checking for yy_current_buffer... ')
458 ret = conf.TryCompile ("""using namespace std;
459 #include <FlexLexer.h>
460 class yy_flex_lexer: public yyFlexLexer
465 yy_current_buffer = 0;
471 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
472 : CheckYYCurrentBuffer })
475 'DIRSEP' : "'%s'" % os.sep,
476 'PATHSEP' : "'%s'" % os.pathsep,
477 'PACKAGE': '"%s"' % package.name,
478 'DATADIR' : '"%s"' % sharedir,
479 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
480 'LOCALEDIR' : '"%s"' %localedir,
482 conf.env.Append (DEFINES = defines)
484 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
485 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
487 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
489 env.Append (CPPPATH = [PYTHON_INCLUDE])
491 headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
492 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
494 if conf.CheckCHeader (i):
495 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
496 conf.env['DEFINES'][key] = 1
498 ccheaders = ('sstream',)
500 if conf.CheckCXXHeader (i):
501 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
502 conf.env['DEFINES'][key] = 1
504 functions = ('chroot', 'fopencookie', 'funopen',
506 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
508 if 0 or conf.CheckFunc (i):
509 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
510 conf.env['DEFINES'][key] = 1
512 if conf.CheckYYCurrentBuffer ():
513 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
515 if conf.CheckLib ('dl'):
520 if env.has_key ('CPPPATH'):
521 cpppath = env['CPPPATH']
523 ## FIXME: linkage, check for libguile.h and scm_boot_guile
524 #this could happen after flower...
525 env.ParseConfig ('guile-config compile')
527 test_program (required, 'pkg-config', '0.9.0',
528 'pkg-config library compile manager', 'pkg-config')
529 if test_lib (required, 'freetype2', '0.0',
530 'Development files for FreeType 2 font engine',
532 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
534 if test_lib (required, 'pangoft2', '1.6.0',
535 'Development files for pango, with FreeType2',
537 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
539 if test_lib (optional, 'fontconfig', '2.2.0',
540 'Development files for fontconfig', 'fontconfig1'):
541 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
543 #this could happen only for compiling pango-*
545 test_lib (required, 'gtk+-2.0', '2.4.0',
546 'Development files for GTK+', 'gtk2.0')
549 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
550 # <system-dir>] speeds up SCons
551 env['CCFLAGS'] += map (lambda x: '-I' + x,
552 env['CPPPATH'][len (cpppath):])
553 env['CPPPATH'] = cpppath
557 print '********************************'
558 print 'Please install required packages'
560 print '%s: %s-%s or newer (found: %s %s)' % i
565 print '*************************************'
566 print 'Consider installing optional packages'
568 print '%s: %s-%s or newer (found: %s %s)' % i
570 return conf.Finish ()
572 def config_header (target, source, env):
573 config = open (str (target[0]), 'w')
574 for i in sorted (env['DEFINES'].keys ()):
575 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
577 env.Command (config_hh, config_cache, config_header)
593 if not d.has_key (lst[i]):
601 def uniquify_config_vars (env):
602 for i in config_vars:
603 if env.has_key (i) and type (env[i]) == type ([]):
604 env[i] = uniquify (env[i])
606 def save_config_cache (env):
607 ## FIXME: Is this smart, using option cache for saving
608 ## config.cache? I cannot seem to find the official method.
609 uniquify_config_vars (env)
610 opts.Save (config_cache, env)
612 if 'config' in COMMAND_LINE_TARGETS:
613 sys.stdout.write ('\n')
614 sys.stdout.write ('LilyPond configured')
615 sys.stdout.write ('\n')
616 sys.stdout.write ('Now run')
617 sys.stdout.write ('\n')
618 sys.stdout.write (' scons [TARGET|DIR]...')
619 sys.stdout.write ('\n')
620 sys.stdout.write ('\n')
621 sys.stdout.write ('Examples:')
622 sys.stdout.write ('\n')
623 sys.stdout.write (' scons lily # build lilypond')
624 sys.stdout.write ('\n')
625 sys.stdout.write (' scons all # build everything')
626 sys.stdout.write ('\n')
627 sys.stdout.write (' scons doc # build documentation')
628 sys.stdout.write ('\n')
630 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
631 ## sys.stdout.write ('\n')
633 elif not env['checksums']:
634 # When using timestams, config.hh is NEW. The next
635 # build triggers recompilation of everything. Exiting
636 # here makes SCons use the actual timestamp for config.hh
637 # and prevents recompiling everything the next run.
638 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
639 sys.stdout.write ('Running %s ... ' % command)
640 sys.stdout.write ('\n')
641 s = os.system (command)
645 # scons: *** Calling Configure from Builders is not supported.
646 # env.Command (config_cache, None, configure)
647 if not os.path.exists (config_cache) \
648 or (os.stat ('SConstruct')[stat.ST_MTIME]
649 > os.stat (config_cache)[stat.ST_MTIME]):
650 env = configure (None, None, env)
651 save_config_cache (env)
652 elif env['checksums']:
653 # just save everything
654 save_config_cache (env)
656 #urg how does #/ subst work?
658 SConscript ('buildscripts/builder.py')
660 env.PrependENVPath ('PATH',
661 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
663 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
665 if not os.path.exists (LILYPONDPREFIX):
666 os.makedirs (LILYPONDPREFIX)
668 env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
669 env.Depends ('lily', LILYPONDPREFIX)
672 'LILYPONDPREFIX' : LILYPONDPREFIX,
673 'TEXMF' : '{$LILYPONDPREFIX,'
674 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
677 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
678 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
679 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
682 # post-option environment-update
686 lilypond_datadir = sharedir_package,
687 localedir = localedir,
688 local_lilypond_datadir = sharedir_package_version,
689 lilypondprefix = lilypondprefix,
690 sharedir_package = sharedir_package,
691 sharedir_doc_package = sharedir_doc_package,
692 sharedir_package_version = sharedir_package_version,
693 libdir_package = libdir_package,
694 libdir_package_version = libdir_package_version,
696 # global build verbosity switch
697 __verbose = ' --verbose',
699 LILYPOND = BUILD_LILYPOND,
700 ABC2LY = BUILD_ABC2LY,
701 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
702 LILYPOND_BOOK_FORMAT = 'texi-html',
703 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
704 # PYTHONPATH = ['$absbuild/python/$out'],
705 TEXI2DVI_PAPERSIZE = '@afourpaper',
706 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
707 DVIPS_PAPERSIZE = 'a4',
708 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
710 '-u+ec-mftrace.map'],
711 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
714 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
716 env.Append (CCFLAGS = ['-g'])
717 if env['optimising']:
718 env.Append (CCFLAGS = '-O2')
720 env.Append (CCFLAGS = ['-W', '-Wall'])
721 env.Append (CXXFLAGS = ['-Wconversion'])
724 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
725 # FIXME: ParseConfig ignores -L flag?
726 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
729 env['__verbose'] = ' --verbose'
730 env['set__x'] = 'set -x;'
733 ## Explicit target and dependencies
735 if 'clean' in COMMAND_LINE_TARGETS:
736 # ugh: prevent reconfigure instead of clean
737 os.system ('touch %s' % config_cache)
739 command = sys.argv[0] + ' -c .'
740 sys.stdout.write ('Running %s ... ' % command)
741 sys.stdout.write ('\n')
742 s = os.system (command)
743 if os.path.exists (config_cache):
744 os.unlink (config_cache)
747 if 'sconsclean' in COMMAND_LINE_TARGETS:
748 command = 'rm -rf scons.cache $(find . -name ".scon*")'
749 s = os.system (command)
750 if os.path.exists (config_cache):
751 os.unlink (config_cache)
754 if 'realclean' in COMMAND_LINE_TARGETS:
755 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
756 sys.stdout.write ('Running %s ... ' % command)
757 sys.stdout.write ('\n')
758 s = os.system (command)
759 if os.path.exists (config_cache):
760 os.unlink (config_cache)
767 # Declare SConscript phonies
768 env.Alias ('minimal', config_cache)
771 env.Alias ('mf-essential', config_cache)
772 env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
773 env.Alias ('all', ['minimal', 'mf', '.'])
776 env.Alias ('minimal', ['python', 'lily', 'mf'])
777 env.Alias ('all', ['minimal', '.'])
780 # Do we want the doc/web separation?
784 'Documentation/user',
785 'Documentation/topdocs',
786 'Documentation/bibliography',
789 # Without target arguments, do minimal build
790 if not COMMAND_LINE_TARGETS:
791 env.Default (['minimal'])
793 # GNU Make rerouting compat:
794 env.Alias ('web', 'doc')
797 env.Command (version_hh, '#/VERSION',
798 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
800 # post-config environment update
802 run_prefix = run_prefix,
803 LILYPONDPREFIX = LILYPONDPREFIX,
805 # FIXME: move to lily/SConscript?
806 LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
807 CPPPATH = [outdir, ],
808 LILYPOND_PATH = ['.',
810 '$srcdir/input/regression',
811 '$srcdir/input/test',
812 '$srcdir/input/tutorial',
813 '$srcdir/Documentation/user',
815 # os.path.join (absbuild, 'Documentation',
817 # os.path.join (absbuild, 'Documentation/user',
820 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
821 '$absbuild/Documentation/user/$out'],
828 def cvs_entry_is_dir (line):
829 return line[0] == 'D' and line[-2] == '/'
831 def cvs_entry_is_file (line):
832 return line[0] == '/' and line[-2] == '/'
835 entries = os.path.join (dir, 'CVS/Entries')
836 if not os.path.exists (entries):
838 entries = open (entries).readlines ()
839 dir_entries = filter (cvs_entry_is_dir, entries)
840 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
842 return dirs + map (cvs_dirs, dirs)
845 entries = os.path.join (dir, 'CVS/Entries')
846 if not os.path.exists (entries):
848 entries = open (entries).readlines ()
849 file_entries = filter (cvs_entry_is_file, entries)
850 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
851 return map (lambda x: os.path.join (dir, x), files)
853 def flatten (tree, lst):
854 if type (tree) == type ([]):
856 if type (i) == type ([]):
862 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
863 subdirs = flatten (cvs_dirs ('.'), [])
866 command = 'cd %(srcdir)s \
867 && find . -name SConscript | sed s@/SConscript@@' % vars ()
868 subdirs = string.split (os.popen (command).read ())
871 and 'all' not in COMMAND_LINE_TARGETS\
872 and 'doc' not in COMMAND_LINE_TARGETS\
873 and 'web' not in COMMAND_LINE_TARGETS\
874 and 'install' not in COMMAND_LINE_TARGETS\
875 and 'clean' not in COMMAND_LINE_TARGETS:
876 subdirs = [ 'python',
882 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
883 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
885 src_files = ['foobar']
887 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
888 txt_files = map (lambda x: x + '.txt', readme_files)
892 # speeds up build by +- 5%
895 foo = map (lambda x: env.TXT (x + '.txt',
896 os.path.join ('Documentation/topdocs', x)),
898 tar_base = package.name + '-' + version
899 tar_name = tar_base + '.tar.gz'
900 ball_prefix = os.path.join (outdir, tar_base)
901 tar_ball = os.path.join (outdir, tar_name)
903 dist_files = src_files + txt_files
904 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
905 map (lambda x: env.Depends (tar_ball, x), ball_files)
906 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
907 'ln $SOURCE $TARGET'), dist_files)
908 tar = env.Command (tar_ball, src_files,
909 ['rm -f $$(find $TARGET.dir -name .sconsign)',
910 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
911 env.Alias ('tar', tar)
913 dist_ball = os.path.join (package.release_dir, tar_name)
914 env.Command (dist_ball, tar_ball,
915 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
916 + 'ln $SOURCE $TARGET')
917 env.Depends ('dist', dist_ball)
918 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
919 patch = env.PATCH (patch_name, tar_ball)
920 env.Depends (patch_name, dist_ball)
921 env.Alias ('release', patch)
925 web_base = os.path.join (outdir, 'web')
926 web_ball = web_base + '.tar.gz'
927 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
928 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
929 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
930 env['web_path'] = web_path
931 web_list = os.path.join (outdir, 'weblist')
932 # compatible make heritits
933 # fixme: generate in $outdir is cwd/builddir
934 env.Command (web_list,
935 ## Adding 'doc' dependency is correct, but takes
936 ## > 5min extra if you have a peder :-)
940 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
941 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
942 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
943 'cd $absbuild && find Documentation input $web_path \
945 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
946 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
947 'cd $absbuild && ls *.html >> $TARGET',])
948 env.Command (web_ball, web_list,
949 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
950 #env.Alias ('web', web_ball)
951 www_base = os.path.join (outdir, 'www')
952 www_ball = www_base + '.tar.gz'
953 env.Command (www_ball, web_ball,
955 'mkdir -p $absbuild/$out/tmp',
956 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
957 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
958 + ' do mv $$i $$(dirname $$i)/out-www; done',
959 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
960 env.Alias ('web', www_ball)
964 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
965 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
966 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
967 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
969 'etags $ETAGSFLAGS $SOURCES')
971 # Note: SConscripts are only needed in directories where something needs
972 # to be done, building or installing
974 if os.path.exists (os.path.join (d, 'SConscript')):
975 b = os.path.join (env['build'], d, env['out'])
976 # Support clean sourcetree build (--srcdir build)
978 if os.path.abspath (b) != os.path.abspath (d):
979 env.BuildDir (b, d, duplicate = 0)
980 SConscript (os.path.join (b, 'SConscript'))