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 symlink_tree (target, source, env):
278 if not os.path.isdir (dir):
279 if os.path.exists (dir):
283 map (mkdir, string.split (dir, os.sep))
284 def symlink (src, dst):
286 dir = os.path.dirname (dst)
289 frm = os.path.join (srcdir, src[1:])
291 depth = len (string.split (dir, '/'))
292 if src.find ('@') > -1:
293 frm = os.path.join ('../' * depth,
294 string.replace (src, '@',
297 frm = os.path.join ('../' * depth, src,
300 frm = os.path.join (frm, os.path.basename (dst))
302 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
303 os.symlink (frm, os.path.basename (dst))
304 shutil.rmtree (run_prefix)
305 prefix = os.path.join (env['out'], 'usr')
306 map (lambda x: symlink (x[0], os.path.join (prefix,
307 x[1] % {'ver' : version})),
310 # /$ := add dst file_name
311 (('python', 'lib/lilypond/python'),
313 ('python', 'share/lilypond/%(ver)s/python'),
314 ('lily/', 'bin/lilypond'),
315 ('scripts/', 'bin/convert-ly'),
316 ('scripts/', 'bin/lilypond-book'),
317 ('scripts/', 'bin/ps2png'),
318 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
319 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
320 ('#ps/music-drawing-routines.ps',
321 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
322 ('mf', 'share/lilypond/%(ver)s/otf'),
323 ('mf', 'share/lilypond/%(ver)s/tfm'),
324 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
325 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
326 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
327 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
328 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
329 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
330 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
331 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
332 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
333 ('#ly', 'share/lilypond/%(ver)s/ly'),
334 ('#scm', 'share/lilypond/%(ver)s/scm'),
335 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
336 ('#ps', 'share/lilypond/%(ver)s/ps'),
337 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
338 ('elisp', 'share/lilypond/%(ver)s/elisp')))
340 print "FIXME: BARF BARF BARF"
344 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
346 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
347 dir = os.path.join (absbuild, prefix, ext)
348 os.system ('rm -f ' + dir)
351 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
355 def configure (target, source, env):
356 dre = re.compile ('\n(200[0-9]{5})')
357 vre = re.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
359 def get_version (program):
360 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
361 pipe = os.popen (command)
362 output = pipe.read ()
365 splits = re.sub ('^|\s', '\n', output)
366 date_hack = re.sub (dre, '\n0.0.\\1', splits)
367 m = re.match (vre, date_hack)
371 return string.split (v, '.')
373 def test_version (lst, full_name, minimal, description, package):
374 program = os.path.basename (full_name)
375 sys.stdout.write ('Checking %s version... ' % program)
376 actual = get_version (program)
379 lst.append ((description, package, minimal, program,
382 print string.join (actual, '.')
383 if map (string.atoi, actual) \
384 < map (string.atoi, string.split (minimal, '.')):
385 lst.append ((description, package, minimal, program,
386 string.join (actual, '.')))
390 def test_program (lst, program, minimal, description, package):
391 key = program.upper ()
393 key = re.sub ('\+', 'X', key)
394 key = re.sub ('-', '_', key)
395 sys.stdout.write ('Checking for %s ... ' % program)
396 if env.has_key (key):
398 sys.stdout.write ('(cached) ')
400 f = WhereIs (program)
404 lst.append ((description, package, minimal, program,
408 return test_version (lst, program, minimal, description, package)
410 def test_lib (lst, program, minimal, description, package):
411 # FIXME: test for Debian or RPM (or -foo?) based dists
412 # to guess (or get correct!: apt-cache search?)
414 #if os.system ('pkg-config --atleast-version=0 freetype2'):
416 if test_version (lst, program, minimal, description,
417 'lib%(package)s-dev or %(package)s-devel'
419 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
425 test_program (required, 'bash', '2.0', 'Bash', 'bash')
426 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
427 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
428 test_program (required, 'guile-config', '1.6', 'GUILE development',
429 'libguile-dev or guile-devel')
430 test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
431 test_program (required, 'mftrace', '1.1.9',
432 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
433 test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
434 test_program (required, 'python', '2.1', 'Python (www.python.org)',
436 test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
439 # Do not use bison 1.50 and 1.75.
440 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
441 test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
443 test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
444 test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
446 test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
448 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
449 test_program (optional, 'gs', '8.15',
450 'Ghostscript PostScript interpreter',
451 'gs or gs-afpl or gs-esp or gs-gpl')
452 test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
454 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
455 test_program (optional, 'perl', '4.0',
456 'Perl practical efficient readonly language', 'perl')
457 #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
459 def CheckYYCurrentBuffer (context):
460 context.Message ('Checking for yy_current_buffer... ')
461 ret = conf.TryCompile ("""using namespace std;
462 #include <FlexLexer.h>
463 class yy_flex_lexer: public yyFlexLexer
468 yy_current_buffer = 0;
474 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
475 : CheckYYCurrentBuffer })
478 'DIRSEP' : "'%s'" % os.sep,
479 'PATHSEP' : "'%s'" % os.pathsep,
480 'PACKAGE': '"%s"' % package.name,
481 'DATADIR' : '"%s"' % sharedir,
482 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
483 'LOCALEDIR' : '"%s"' %localedir,
485 conf.env.Append (DEFINES = defines)
487 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
488 PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
490 env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
492 env.Append (CPPPATH = [PYTHON_INCLUDE])
494 headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
495 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
497 if conf.CheckCHeader (i):
498 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
499 conf.env['DEFINES'][key] = 1
501 ccheaders = ('sstream',)
503 if conf.CheckCXXHeader (i):
504 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
505 conf.env['DEFINES'][key] = 1
507 functions = ('chroot', 'fopencookie', 'funopen',
509 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
511 if 0 or conf.CheckFunc (i):
512 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
513 conf.env['DEFINES'][key] = 1
515 if conf.CheckYYCurrentBuffer ():
516 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
518 if conf.CheckLib ('dl'):
523 if env.has_key ('CPPPATH'):
524 cpppath = env['CPPPATH']
526 ## FIXME: linkage, check for libguile.h and scm_boot_guile
527 #this could happen after flower...
528 env.ParseConfig ('guile-config compile')
530 test_program (required, 'pkg-config', '0.9.0',
531 'pkg-config library compile manager', 'pkg-config')
532 if test_lib (required, 'freetype2', '0.0',
533 'Development files for FreeType 2 font engine',
535 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
537 if test_lib (required, 'pangoft2', '1.6.0',
538 'Development files for pango, with FreeType2',
540 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
542 if test_lib (optional, 'fontconfig', '2.2.0',
543 'Development files for fontconfig', 'fontconfig1'):
544 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
546 #this could happen only for compiling pango-*
548 test_lib (required, 'gtk+-2.0', '2.4.0',
549 'Development files for GTK+', 'gtk2.0')
552 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
553 # <system-dir>] speeds up SCons
554 env['CCFLAGS'] += map (lambda x: '-I' + x,
555 env['CPPPATH'][len (cpppath):])
556 env['CPPPATH'] = cpppath
560 print '********************************'
561 print 'Please install required packages'
563 print '%s: %s-%s or newer (found: %s %s)' % i
568 print '*************************************'
569 print 'Consider installing optional packages'
571 print '%s: %s-%s or newer (found: %s %s)' % i
573 return conf.Finish ()
575 def config_header (target, source, env):
576 config = open (str (target[0]), 'w')
577 for i in list_sort (env['DEFINES'].keys ()):
578 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
580 env.Command (config_hh, config_cache, config_header)
596 if not d.has_key (lst[i]):
604 def uniquify_config_vars (env):
605 for i in config_vars:
606 if env.has_key (i) and type (env[i]) == type ([]):
607 env[i] = uniquify (env[i])
609 def save_config_cache (env):
610 ## FIXME: Is this smart, using option cache for saving
611 ## config.cache? I cannot seem to find the official method.
612 uniquify_config_vars (env)
613 opts.Save (config_cache, env)
615 if 'config' in COMMAND_LINE_TARGETS:
616 sys.stdout.write ('\n')
617 sys.stdout.write ('LilyPond configured')
618 sys.stdout.write ('\n')
619 sys.stdout.write ('Now run')
620 sys.stdout.write ('\n')
621 sys.stdout.write (' scons [TARGET|DIR]...')
622 sys.stdout.write ('\n')
623 sys.stdout.write ('\n')
624 sys.stdout.write ('Examples:')
625 sys.stdout.write ('\n')
626 sys.stdout.write (' scons lily # build lilypond')
627 sys.stdout.write ('\n')
628 sys.stdout.write (' scons all # build everything')
629 sys.stdout.write ('\n')
630 sys.stdout.write (' scons doc # build documentation')
631 sys.stdout.write ('\n')
633 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
634 ## sys.stdout.write ('\n')
636 elif not env['checksums']:
637 # When using timestams, config.hh is NEW. The next
638 # build triggers recompilation of everything. Exiting
639 # here makes SCons use the actual timestamp for config.hh
640 # and prevents recompiling everything the next run.
641 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
642 sys.stdout.write ('Running %s ... ' % command)
643 sys.stdout.write ('\n')
644 s = os.system (command)
648 # scons: *** Calling Configure from Builders is not supported.
649 # env.Command (config_cache, None, configure)
650 if not os.path.exists (config_cache) \
651 or (os.stat ('SConstruct')[stat.ST_MTIME]
652 > os.stat (config_cache)[stat.ST_MTIME]):
653 env = configure (None, None, env)
654 save_config_cache (env)
655 elif env['checksums']:
656 # just save everything
657 save_config_cache (env)
659 #urg how does #/ subst work?
661 SConscript ('buildscripts/builder.py')
663 env.PrependENVPath ('PATH',
664 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
666 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
668 if not os.path.exists (LILYPONDPREFIX):
669 os.makedirs (LILYPONDPREFIX)
671 env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
672 env.Depends ('lily', LILYPONDPREFIX)
675 'LILYPONDPREFIX' : LILYPONDPREFIX,
676 'TEXMF' : '{$LILYPONDPREFIX,'
677 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
680 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
681 BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
682 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
685 # post-option environment-update
689 lilypond_datadir = sharedir_package,
690 localedir = localedir,
691 local_lilypond_datadir = sharedir_package_version,
692 lilypondprefix = lilypondprefix,
693 sharedir_package = sharedir_package,
694 sharedir_doc_package = sharedir_doc_package,
695 sharedir_package_version = sharedir_package_version,
696 libdir_package = libdir_package,
697 libdir_package_version = libdir_package_version,
699 # global build verbosity switch
700 __verbose = ' --verbose',
702 LILYPOND = BUILD_LILYPOND,
703 ABC2LY = BUILD_ABC2LY,
704 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
705 LILYPOND_BOOK_FORMAT = 'texi-html',
706 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
707 # PYTHONPATH = ['$absbuild/python/$out'],
708 TEXI2DVI_PAPERSIZE = '@afourpaper',
709 TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
710 DVIPS_PAPERSIZE = 'a4',
711 DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
713 '-u+ec-mftrace.map'],
714 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
717 env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
719 env.Append (CCFLAGS = ['-g'])
720 if env['optimising']:
721 env.Append (CCFLAGS = '-O2')
723 env.Append (CCFLAGS = ['-W', '-Wall'])
724 env.Append (CXXFLAGS = ['-Wconversion'])
727 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
728 # FIXME: ParseConfig ignores -L flag?
729 env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
732 env['__verbose'] = ' --verbose'
733 env['set__x'] = 'set -x;'
736 ## Explicit target and dependencies
738 if 'clean' in COMMAND_LINE_TARGETS:
739 # ugh: prevent reconfigure instead of clean
740 os.system ('touch %s' % config_cache)
742 command = sys.argv[0] + ' -c .'
743 sys.stdout.write ('Running %s ... ' % command)
744 sys.stdout.write ('\n')
745 s = os.system (command)
746 if os.path.exists (config_cache):
747 os.unlink (config_cache)
750 if 'sconsclean' in COMMAND_LINE_TARGETS:
751 command = 'rm -rf scons.cache $(find . -name ".scon*")'
752 s = os.system (command)
753 if os.path.exists (config_cache):
754 os.unlink (config_cache)
757 if 'realclean' in COMMAND_LINE_TARGETS:
758 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
759 sys.stdout.write ('Running %s ... ' % command)
760 sys.stdout.write ('\n')
761 s = os.system (command)
762 if os.path.exists (config_cache):
763 os.unlink (config_cache)
770 # Declare SConscript phonies
771 env.Alias ('minimal', config_cache)
774 env.Alias ('mf-essential', config_cache)
775 env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
776 env.Alias ('all', ['minimal', 'mf', '.'])
779 env.Alias ('minimal', ['python', 'lily', 'mf'])
780 env.Alias ('all', ['minimal', '.'])
783 # Do we want the doc/web separation?
787 'Documentation/user',
788 'Documentation/topdocs',
789 'Documentation/bibliography',
792 # Without target arguments, do minimal build
793 if not COMMAND_LINE_TARGETS:
794 env.Default (['minimal'])
796 # GNU Make rerouting compat:
797 env.Alias ('web', 'doc')
800 env.Command (version_hh, '#/VERSION',
801 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
803 # post-config environment update
805 run_prefix = run_prefix,
806 LILYPONDPREFIX = LILYPONDPREFIX,
808 # FIXME: move to lily/SConscript?
809 LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
810 CPPPATH = [outdir, ],
811 LILYPOND_PATH = ['.',
813 '$srcdir/input/regression',
814 '$srcdir/input/test',
815 '$srcdir/input/tutorial',
816 '$srcdir/Documentation/user',
818 # os.path.join (absbuild, 'Documentation',
820 # os.path.join (absbuild, 'Documentation/user',
823 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
824 '$absbuild/Documentation/user/$out'],
831 def cvs_entry_is_dir (line):
832 return line[0] == 'D' and line[-2] == '/'
834 def cvs_entry_is_file (line):
835 return line[0] == '/' and line[-2] == '/'
838 entries = os.path.join (dir, 'CVS/Entries')
839 if not os.path.exists (entries):
841 entries = open (entries).readlines ()
842 dir_entries = filter (cvs_entry_is_dir, entries)
843 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
845 return dirs + map (cvs_dirs, dirs)
848 entries = os.path.join (dir, 'CVS/Entries')
849 if not os.path.exists (entries):
851 entries = open (entries).readlines ()
852 file_entries = filter (cvs_entry_is_file, entries)
853 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
854 return map (lambda x: os.path.join (dir, x), files)
856 def flatten (tree, lst):
857 if type (tree) == type ([]):
859 if type (i) == type ([]):
865 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
866 subdirs = flatten (cvs_dirs ('.'), [])
869 command = 'cd %(srcdir)s \
870 && find . -name SConscript | sed s@/SConscript@@' % vars ()
871 subdirs = string.split (os.popen (command).read ())
874 and 'all' not in COMMAND_LINE_TARGETS\
875 and 'doc' not in COMMAND_LINE_TARGETS\
876 and 'web' not in COMMAND_LINE_TARGETS\
877 and 'install' not in COMMAND_LINE_TARGETS\
878 and 'clean' not in COMMAND_LINE_TARGETS:
879 subdirs = [ 'python',
885 if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
886 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
888 src_files = ['foobar']
890 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
891 txt_files = map (lambda x: x + '.txt', readme_files)
895 # speeds up build by +- 5%
898 foo = map (lambda x: env.TXT (x + '.txt',
899 os.path.join ('Documentation/topdocs', x)),
901 tar_base = package.name + '-' + version
902 tar_name = tar_base + '.tar.gz'
903 ball_prefix = os.path.join (outdir, tar_base)
904 tar_ball = os.path.join (outdir, tar_name)
906 dist_files = src_files + txt_files
907 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
908 map (lambda x: env.Depends (tar_ball, x), ball_files)
909 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
910 'ln $SOURCE $TARGET'), dist_files)
911 tar = env.Command (tar_ball, src_files,
912 ['rm -f $$(find $TARGET.dir -name .sconsign)',
913 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
914 env.Alias ('tar', tar)
916 dist_ball = os.path.join (package.release_dir, tar_name)
917 env.Command (dist_ball, tar_ball,
918 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
919 + 'ln $SOURCE $TARGET')
920 env.Depends ('dist', dist_ball)
921 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
922 patch = env.PATCH (patch_name, tar_ball)
923 env.Depends (patch_name, dist_ball)
924 env.Alias ('release', patch)
928 web_base = os.path.join (outdir, 'web')
929 web_ball = web_base + '.tar.gz'
930 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
931 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
932 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
933 env['web_path'] = web_path
934 web_list = os.path.join (outdir, 'weblist')
935 # compatible make heritits
936 # fixme: generate in $outdir is cwd/builddir
937 env.Command (web_list,
938 ## Adding 'doc' dependency is correct, but takes
939 ## > 5min extra if you have a peder :-)
943 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
944 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
945 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
946 'cd $absbuild && find Documentation input $web_path \
948 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
949 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
950 'cd $absbuild && ls *.html >> $TARGET',])
951 env.Command (web_ball, web_list,
952 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
953 #env.Alias ('web', web_ball)
954 www_base = os.path.join (outdir, 'www')
955 www_ball = www_base + '.tar.gz'
956 env.Command (www_ball, web_ball,
958 'mkdir -p $absbuild/$out/tmp',
959 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
960 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
961 + ' do mv $$i $$(dirname $$i)/out-www; done',
962 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
963 env.Alias ('web', www_ball)
967 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
968 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
969 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
970 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
972 'etags $ETAGSFLAGS $SOURCES')
974 # Note: SConscripts are only needed in directories where something needs
975 # to be done, building or installing
977 if os.path.exists (os.path.join (d, 'SConscript')):
978 b = os.path.join (env['build'], d, env['out'])
979 # Support clean sourcetree build (--srcdir build)
981 if os.path.abspath (b) != os.path.abspath (d):
982 env.BuildDir (b, d, duplicate = 0)
983 SConscript (os.path.join (b, 'SConscript'))