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
27 lilypond-bin input/simple
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 # * more program configure tests (mfont, ...?)
69 # * split doc target: doc input examples mutopia?
71 # * grep FIXME $(find . -name 'S*t')
83 EnsureSConsVersion (0, 95)
86 scons [KEY=VALUE].. [TARGET|DIR]..
88 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
89 realclean, release, sconsclean, tar, TAGS
94 config_cache = 'scons.cache'
110 # Put your favourite stuff in custom.py
111 opts = Options ([config_cache, 'custom.py'], ARGUMENTS)
112 opts.Add ('prefix', 'Install prefix', '/usr/')
113 opts.Add ('out', 'Output directory', 'out-scons')
114 opts.Add ('build', 'Build directory', '.')
115 opts.Add ('DESTDIR', 'DESTDIR prepended to prefix', '')
117 BoolOption ('warnings', 'compile with -Wall and similiar',
119 BoolOption ('debugging', 'compile with debugging symbols',
121 BoolOption ('optimising', 'compile with optimising',
123 BoolOption ('shared', 'build shared libraries',
125 BoolOption ('static', 'build static libraries',
127 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
129 BoolOption ('verbose', 'run commands with verbose flag',
131 BoolOption ('checksums', 'use checksums instead of timestamps',
133 BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
137 srcdir = Dir ('.').srcnode ().abspath
139 sys.path.append (os.path.join (srcdir, 'stepmake', 'bin'))
141 package = packagepython.Package (srcdir)
142 version = packagepython.version_tuple_to_str (package.version)
144 ENV = { 'PATH' : os.environ['PATH'] }
145 for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH']:
146 if os.environ.has_key (key):
147 ENV[key] = os.environ[key]
153 CPPDEFINES = '-DHAVE_CONFIG_H',
154 PERL = '/usr/bin/perl',
155 PYTHON = '/usr/bin/python',
158 MAKEINFO = 'LANG= makeinfo',
159 MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
161 PKG_CONFIG_PATH = [os.path.join (os.environ['HOME'],
162 'usr/pkg/gnome/lib'),
163 os.path.join (os.environ['HOME'],
164 'usr/pkg/pango/lib')],
167 TOPLEVEL_VERSION = version,
170 # Add all config_vars to opts, so that they will be read and saved
171 # together with the other configure options.
172 map (lambda x: opts.AddOptions ((x,)), config_vars)
174 Help (usage + opts.GenerateHelpText (env))
179 # Usability switch (Anthony Roach).
180 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
181 # First do: scons realclean .
183 SetOption ('max_drift', 1)
184 SetOption ('implicit_cache', 1)
185 elif env['checksums']:
186 # Always use checksums (makes more sense than timestamps).
187 SetOption ('max_drift', 0)
188 # Using *content* checksums prevents rebuilds after
189 # [re]configure if config.hh has not changed. Too bad that it
191 TargetSignatures ('content')
193 absbuild = Dir (env['build']).abspath
194 outdir = os.path.join (Dir (env['build']).abspath, env['out'])
195 run_prefix = os.path.join (absbuild, os.path.join (env['out'], 'usr'))
198 config_hh = os.path.join (outdir, 'config.hh')
199 version_hh = os.path.join (outdir, 'version.hh')
201 env.Alias ('config', config_cache)
203 cachedir = os.path.join (outdir, 'build-cache')
205 if not os.path.exists (cachedir):
206 os.makedirs (cachedir)
210 # No need to set $LILYPONDPREFIX to run lily, but cannot install...
211 if env['debugging'] and not 'install' in COMMAND_LINE_TARGETS:
212 env['prefix'] = run_prefix
214 prefix = env['prefix']
215 bindir = os.path.join (prefix, 'bin')
216 sharedir = os.path.join (prefix, 'share')
217 libdir = os.path.join (prefix, 'lib')
218 localedir = os.path.join (sharedir, 'locale')
219 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
220 sharedir_package = os.path.join (sharedir, package.name)
221 sharedir_package_version = os.path.join (sharedir_package, version)
222 lilypondprefix = sharedir_package_version
237 def configure (target, source, env):
238 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$',
240 def get_version (program):
241 command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
242 pipe = os.popen (command)
243 output = pipe.read ()
246 v = re.sub (vre, '\\1', output)
249 return string.split (v, '.')
251 def get_fullname (program):
252 command = 'type -p "%s" 2>/dev/null' % program
253 pipe = os.popen (command)
254 output = pipe.readlines ()
260 return string.split (o)[-1]
262 def test_version (lst, program, minimal, description, package):
263 sys.stdout.write ('Checking %s version... ' % program)
264 actual = get_version (program)
267 lst.append ((description, package, minimal, program,
270 print string.join (actual, '.')
271 if map (string.atoi, actual) \
272 < map (string.atoi, string.split (minimal, '.')):
273 lst.append ((description, package, minimal, program,
274 string.join (actual, '.')))
278 def test_program (lst, program, minimal, description, package):
279 sys.stdout.write ('Checking for %s ... ' % program)
280 f = get_fullname (program)
283 lst.append ((description, package, minimal, program,
287 return test_version (lst, program, minimal, description, package)
289 def test_lib (lst, program, minimal, description):
290 # FIXME: test for Debian or RPM (or -foo?) based dists
291 # to guess (or get correct!: apt-cache search?)
293 #if os.system ('pkg-config --atleast-version=0 freetype2'):
295 if test_version (lst, program, minimal, description,
296 'lib%(program)s-dev or %(program)s-devel'
298 env.ParseConfig ('pkg-config --cflags --libs %(program)s'
303 for i in ['bash', 'perl', 'python', 'sh']:
304 sys.stdout.write ('Checking for %s... ' % i)
306 key = string.upper (i)
311 sys.stdout.write ('not found: %s (using: %s)' \
314 sys.stdout.write ('\n')
317 test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
318 test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
319 test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
320 test_program (required, 'guile-config', '1.6', 'GUILE development',
321 'libguile-dev or guile-devel')
322 # Do not use bison 1.50 and 1.75.
323 test_program (required, 'bison', '1.25', 'Bison -- parser generator',
325 test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
328 test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
329 test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
330 test_program (optional, 'gs', '8.14', 'Ghostscript PostScript interpreter', 'gs or gs-afpl or gs-esp or gs-gpl')
331 test_program (optional, 'mftrace', '1.1.0', 'Metafont tracing Type1',
333 test_program (optional, 'perl', '4.0',
334 'Perl practical efficient readonly language', 'perl')
335 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
336 test_program (optional, 'fontforge', '20041224.0', 'FontForge', 'fontforge')
338 def CheckYYCurrentBuffer (context):
339 context.Message ('Checking for yy_current_buffer... ')
340 ret = conf.TryCompile ("""using namespace std;
341 #include <FlexLexer.h>
342 class yy_flex_lexer: public yyFlexLexer
347 yy_current_buffer = 0;
353 conf = Configure (env, custom_tests = { 'CheckYYCurrentBuffer'
354 : CheckYYCurrentBuffer })
357 'DIRSEP' : "'%s'" % os.sep,
358 'PATHSEP' : "'%s'" % os.pathsep,
359 'PACKAGE': '"%s"' % package.name,
360 'DATADIR' : '"%s"' % sharedir,
361 'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
362 'LOCALEDIR' : '"%s"' %localedir,
364 conf.env.Append (DEFINES = defines)
366 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
367 PYTHON_INCLUDE = os.popen (command).read ()
369 env.Append (CCFLAGS = ['-I%s ' % PYTHON_INCLUDE])
371 env.Append (CPPPATH = PYTHON_INCLUDE)
373 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
376 if conf.CheckCHeader (i):
377 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
378 conf.env['DEFINES'][key] = 1
380 ccheaders = ('sstream',)
382 if conf.CheckCXXHeader (i):
383 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
384 conf.env['DEFINES'][key] = 1
386 functions = ('fopencookie', 'funopen',
387 'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
389 if 0 or conf.CheckFunc (i):
390 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
391 conf.env['DEFINES'][key] = 1
393 if conf.CheckYYCurrentBuffer ():
394 conf.env['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
396 if conf.CheckLib ('dl'):
399 if conf.CheckLib ('kpathsea'):
400 conf.env['DEFINES']['KPATHSEA'] = 1
403 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
404 conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
405 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
406 conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
408 # FIXME fc3 - move to kpath-guile/SConscript?
409 conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
413 if env.has_key ('CPPPATH'):
414 cpppath = env['CPPPATH']
416 ## FIXME: linkage, check for libguile.h and scm_boot_guile
417 #this could happen after flower...
418 env.ParseConfig ('guile-config compile')
420 test_program (required, 'pkg-config', '0.9.0',
421 'pkg-config library compile manager', 'pkg-config')
422 if test_lib (required, 'freetype2', '0.0',
423 'Development files for FreeType 2 font engine'):
424 conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
426 if test_lib (required, 'pangoft2', '1.6.0',
427 'Development files for pango, with fontconfig2'):
428 conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
429 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
431 if test_lib (optional, 'fontconfig', '2.2.0',
432 'Development files for fontconfig'):
433 conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
435 #this could happen only for compiling pango-*
437 test_lib (required, 'gtk+-2.0', '2.4.0',
438 'Development files for GTK+')
439 if test_lib (required, 'pango', '1.6.0',
440 'Development files for pango'):
441 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
443 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
444 conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
445 if conf.CheckLib ('pango-1.0',
446 'pango_fc_font_map_add_decoder_find_func'):
447 conf.env['DEFINES']['HAVE_PANGO16'] = '1'
448 conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
451 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
452 # <system-dir>] speeds up SCons
453 env['CCFLAGS'] += map (lambda x: '-I' + x,
454 env['CPPPATH'][len (cpppath):])
455 env['CPPPATH'] = cpppath
459 print '********************************'
460 print 'Please install required packages'
462 print '%s: %s-%s or newer (found: %s %s)' % i
467 print '*************************************'
468 print 'Consider installing optional packages'
470 print '%s: %s-%s or newer (found: %s %s)' % i
472 return conf.Finish ()
474 def config_header (target, source, env):
475 config = open (str (target[0]), 'w')
476 for i in list_sort (env['DEFINES'].keys ()):
477 config.write ('#define %s %s\n' % (i, env['DEFINES'][i]))
479 env.Command (config_hh, config_cache, config_header)
495 if not d.has_key (lst[i]):
503 def uniquify_config_vars (env):
504 for i in config_vars:
505 if env.has_key (i) and type (env[i]) == type ([]):
506 env[i] = uniquify (env[i])
508 def save_config_cache (env):
509 ## FIXME: Is this smart, using option cache for saving
510 ## config.cache? I cannot seem to find the official method.
511 uniquify_config_vars (env)
512 opts.Save (config_cache, env)
514 if 'config' in COMMAND_LINE_TARGETS:
515 sys.stdout.write ('\n')
516 sys.stdout.write ('LilyPond configured')
517 sys.stdout.write ('\n')
518 sys.stdout.write ('now run')
519 sys.stdout.write ('\n')
520 sys.stdout.write (' scons [TARGET|DIR]...')
521 sys.stdout.write ('\n')
523 elif not env['checksums']:
524 # When using timestams, config.hh is NEW. The next
525 # build triggers recompilation of everything. Exiting
526 # here makes SCons use the actual timestamp for config.hh
527 # and prevents recompiling everything the next run.
528 command = sys.argv[0] + ' ' + string.join (COMMAND_LINE_TARGETS)
529 sys.stdout.write ('Running %s ... ' % command)
530 sys.stdout.write ('\n')
531 s = os.system (command)
535 if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
536 os.unlink (config_cache)
538 # scons: *** Calling Configure from Builders is not supported.
539 # env.Command (config_cache, None, configure)
540 if not os.path.exists (config_cache) \
541 or (os.stat ('SConstruct')[stat.ST_MTIME]
542 > os.stat (config_cache)[stat.ST_MTIME]):
543 env = configure (None, None, env)
544 save_config_cache (env)
545 elif env['checksums']:
546 # just save everything
547 save_config_cache (env)
549 #urg how does #/ subst work?
551 SConscript ('buildscripts/builder.py')
553 env.PrependENVPath ('PATH',
554 os.path.join (env['absbuild'], env['out'], 'usr/bin'))
556 if os.environ.has_key ('TEXMF'):
557 env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
559 'TEXMF' : '{$LILYPONDPREFIX,' \
560 + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
561 'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
564 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
565 BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
566 BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
567 BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
570 # post-option environment-update
574 lilypond_datadir = sharedir_package,
575 localedir = localedir,
576 local_lilypond_datadir = sharedir_package_version,
577 lilypondprefix = lilypondprefix,
578 sharedir_package = sharedir_package,
579 sharedir_doc_package = sharedir_doc_package,
580 sharedir_package_version = sharedir_package_version,
582 LILYPOND = BUILD_LILYPOND,
583 ABC2LY = BUILD_ABC2LY,
584 LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
585 LILYPOND_BOOK_FORMAT = 'texi-html',
586 MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
588 TEXI2DVI_PAPERSIZE = '@afourpaper',
589 TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
590 DVIPS_PAPERSIZE = 'a4',
591 DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
593 '-u+ec-mftrace.map'],
594 PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
598 env.Append (CCFLAGS = ['-g', '-pipe'])
599 if env['optimising']:
600 env.Append (CCFLAGS = '-O2')
601 env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
603 env.Append (CCFLAGS = ['-W', '-Wall'])
604 env.Append (CXXFLAGS = ['-Wconversion'])
607 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
610 env['__verbose'] = ' --verbose'
611 env['set__x'] = 'set -x;'
614 ## Explicit target and dependencies
616 if 'clean' in COMMAND_LINE_TARGETS:
617 # ugh: prevent reconfigure instead of clean
618 os.system ('touch %s' % config_cache)
620 command = sys.argv[0] + ' -c .'
621 sys.stdout.write ('Running %s ... ' % command)
622 sys.stdout.write ('\n')
623 s = os.system (command)
624 if os.path.exists (config_cache):
625 os.unlink (config_cache)
628 if 'sconsclean' in COMMAND_LINE_TARGETS:
629 command = 'rm -rf scons.cache $(find . -name ".scon*")'
630 s = os.system (command)
631 if os.path.exists (config_cache):
632 os.unlink (config_cache)
635 if 'realclean' in COMMAND_LINE_TARGETS:
636 command = 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
637 sys.stdout.write ('Running %s ... ' % command)
638 sys.stdout.write ('\n')
639 s = os.system (command)
640 if os.path.exists (config_cache):
641 os.unlink (config_cache)
644 # Declare SConscript phonies
645 env.Alias ('minimal', config_cache)
646 env.Alias ('mf-essential', config_cache)
648 env.Alias ('minimal', ['lily', 'mf-essential'])
649 env.Alias ('all', ['minimal', 'mf', '.'])
650 # Do we want the doc/web separation?
653 'Documentation/user',
654 'Documentation/topdocs',
655 'Documentation/bibliography',
658 # Without target arguments, do minimal build
659 if not COMMAND_LINE_TARGETS:
660 env.Default (['minimal'])
662 # GNU Make rerouting compat:
663 env.Alias ('web', 'doc')
666 env.Command (version_hh, '#/VERSION',
667 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
669 # post-config environment update
671 run_prefix = run_prefix,
672 LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
674 # FIXME: move to lily/SConscript?
675 LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
676 os.path.join (absbuild, 'kpath-guile', env['out']),
677 os.path.join (absbuild, 'ttftool', env['out']),],
678 CPPPATH = [outdir, ],
679 LILYPOND_PATH = ['.', '$srcdir/input',
680 '$srcdir/input/regression',
681 '$srcdir/input/test',
682 '$srcdir/input/tutorial',
683 '$srcdir/Documentation/user',
685 # os.path.join (absbuild, 'Documentation',
687 # os.path.join (absbuild, 'Documentation/user',
690 MAKEINFO_PATH = ['.', '$srcdir/Documentation/user',
691 '$absbuild/Documentation/user/$out'],
694 def symlink_tree (target, source, env):
700 if not os.path.isdir (dir):
701 if os.path.exists (dir):
705 map (mkdir, string.split (dir, os.sep))
706 def symlink (src, dst):
708 dir = os.path.dirname (dst)
711 frm = os.path.join (srcdir, src[1:])
713 depth = len (string.split (dir, '/'))
714 if src.find ('@') > -1:
715 frm = os.path.join ('../' * depth,
716 string.replace (src, '@',
719 frm = os.path.join ('../' * depth, src,
722 frm = os.path.join (frm, os.path.basename (dst))
724 print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
725 os.symlink (frm, os.path.basename (dst))
726 shutil.rmtree (run_prefix)
727 prefix = os.path.join (env['out'], 'usr')
728 map (lambda x: symlink (x[0], os.path.join (prefix,
729 x[1] % {'ver' : version})),
732 # /$ := add dst file_name
733 (('python', 'lib/lilypond/python'),
734 ('lily/', 'bin/lilypond'),
735 ('scripts/', 'bin/convert-ly'),
736 ('scripts/', 'bin/lilypond-book'),
737 ('scripts/', 'bin/ps2png'),
738 ('mf', 'share/lilypond/%(ver)s/dvips/mf-out'),
739 ('#ps', 'share/lilypond/%(ver)s/dvips/ps'),
740 ('#ps', 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
741 ('mf', 'share/lilypond/%(ver)s/otf'),
742 ('mf', 'share/lilypond/%(ver)s/tfm'),
743 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
744 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
745 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
746 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
747 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
748 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
749 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
750 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
751 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
752 ('#ly', 'share/lilypond/%(ver)s/ly'),
753 ('#scm', 'share/lilypond/%(ver)s/scm'),
754 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
755 ('#ps', 'share/lilypond/%(ver)s/ps'),
756 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
757 ('elisp', 'share/lilypond/%(ver)s/elisp')))
759 print "FIXME: BARF BARF BARF"
763 prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
765 for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
766 dir = os.path.join (absbuild, prefix, ext)
767 os.system ('rm -f ' + dir)
770 os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
775 stamp = os.path.join (run_prefix, 'stamp')
776 env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
777 env.Depends ('lily', stamp)
783 def cvs_entry_is_dir (line):
784 return line[0] == 'D' and line[-2] == '/'
786 def cvs_entry_is_file (line):
787 return line[0] == '/' and line[-2] == '/'
790 ENTRIES = os.path.join (dir, 'CVS/Entries')
791 if not os.path.exists (ENTRIES):
793 entries = open (ENTRIES).readlines ()
794 dir_entries = filter (cvs_entry_is_dir, entries)
795 dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
797 return dirs + map (cvs_dirs, dirs)
800 ENTRIES = os.path.join (dir, 'CVS/Entries')
801 entries = open (ENTRIES).readlines ()
802 file_entries = filter (cvs_entry_is_file, entries)
803 files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
804 return map (lambda x: os.path.join (dir, x), files)
806 def flatten (tree, lst):
807 if type (tree) == type ([]):
809 if type (i) == type ([]):
816 and 'all' not in COMMAND_LINE_TARGETS\
817 and 'doc' not in COMMAND_LINE_TARGETS\
818 and 'web' not in COMMAND_LINE_TARGETS\
819 and 'install' not in COMMAND_LINE_TARGETS\
820 and 'clean' not in COMMAND_LINE_TARGETS:
821 subdirs = ['lily', 'lily/include',
822 'flower', 'flower/include',
828 subdirs = flatten (cvs_dirs ('.'), [])
830 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
831 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
832 txt_files = map (lambda x: x + '.txt', readme_files)
836 # speeds up build by +- 5%
839 foo = map (lambda x: env.TXT (x + '.txt',
840 os.path.join ('Documentation/topdocs', x)),
842 tar_base = package.name + '-' + version
843 tar_name = tar_base + '.tar.gz'
844 ball_prefix = os.path.join (outdir, tar_base)
845 tar_ball = os.path.join (outdir, tar_name)
847 dist_files = src_files + txt_files
848 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
849 map (lambda x: env.Depends (tar_ball, x), ball_files)
850 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
851 'ln $SOURCE $TARGET'), dist_files)
852 tar = env.Command (tar_ball, src_files,
853 ['rm -f $$(find $TARGET.dir -name .sconsign)',
854 'tar czf $TARGET -C $TARGET.dir %s' % tar_base,])
855 env.Alias ('tar', tar)
857 dist_ball = os.path.join (package.release_dir, tar_name)
858 env.Command (dist_ball, tar_ball,
859 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
860 + 'ln $SOURCE $TARGET')
861 env.Depends ('dist', dist_ball)
862 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
863 patch = env.PATCH (patch_name, tar_ball)
864 env.Depends (patch_name, dist_ball)
865 env.Alias ('release', patch)
869 web_base = os.path.join (outdir, 'web')
870 web_ball = web_base + '.tar.gz'
871 env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
872 web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
873 web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
874 env['web_path'] = web_path
875 web_list = os.path.join (outdir, 'weblist')
876 # compatible make heritits
877 # fixme: generate in $outdir is cwd/builddir
878 env.Command (web_list,
879 ## this is correct, but takes > 5min if you have a peder :-)
882 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
883 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
884 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
885 'cd $absbuild && find Documentation input $web_path \
887 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
888 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
889 'cd $absbuild && ls *.html >> $TARGET',])
890 env.Command (web_ball, web_list,
891 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
892 #env.Alias ('web', web_ball)
893 www_base = os.path.join (outdir, 'www')
894 www_ball = www_base + '.tar.gz'
895 env.Command (www_ball, web_ball,
897 'mkdir -p $absbuild/$out/tmp',
898 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
899 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
900 + ' do mv $$i $$(dirname $$i)/out-www; done',
901 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
902 env.Alias ('web', www_ball)
906 ETAGSFLAGS = """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
907 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
908 code_ext = ['.cc', '.hh', '.scm', '.tcc',]
909 env.Command ('TAGS', filter (lambda x: os.path.splitext (x)[1] in code_ext,
911 'etags $ETAGSFLAGS $SOURCES')
913 # Note: SConscripts are only needed in directories where something needs
914 # to be done, building or installing
916 if os.path.exists (os.path.join (d, 'SConscript')):
917 b = os.path.join (env['build'], d, env['out'])
918 # Support clean sourcetree build (--srcdir build)
920 if os.path.abspath (b) != os.path.abspath (d):
921 env.BuildDir (b, d, duplicate = 0)
922 SConscript (os.path.join (b, 'SConscript'))