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 LILYPOND_DATADIR=$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
= { 'PYTHONPATH': '' }
180 for key
in ['GUILE_LOAD_PATH', 'LD_LIBRARY_PATH', 'PATH', 'PKG_CONFIG_PATH',
181 'PYTHONPATH', 'TEXMF']:
182 if os
.environ
.has_key (key
):
183 ENV
[key
] = os
.environ
[key
]
185 ENV
['PYTHONPATH'] = os
.path
.join (srcdir
, 'python') + ':' + ENV
['PYTHONPATH']
189 BYTEORDER
= sys
.byteorder
.upper (),
192 CPPDEFINES
= '-DHAVE_CONFIG_H',
193 MAKEINFO
= 'LANG= makeinfo',
194 MF_TO_TABLE_PY
= srcdir
+ '/buildscripts/mf-to-table.py',
196 PKG_CONFIG_PATH
= [os
.path
.join (os
.environ
['HOME'],
197 'usr/pkg/gnome/lib'),
198 os
.path
.join (os
.environ
['HOME'],
199 'usr/pkg/pango/lib')],
202 TOPLEVEL_VERSION
= version
,
205 Help (usage
+ opts
.GenerateHelpText (env
))
207 # Add all config_vars to opts, so that they will be read and saved
208 # together with the other configure options.
209 map (lambda x
: opts
.AddOptions ((x
,)), config_vars
)
212 for key
in config_vars
:
213 if os
.environ
.has_key (key
):
214 env
[key
] = os
.environ
[key
]
217 # Usability switch (Anthony Roach).
218 # See http://www.scons.org/cgi-bin/wiki/GoFastButton
219 # First do: scons realclean .
221 SetOption ('max_drift', 1)
222 SetOption ('implicit_cache', 1)
223 elif env
['checksums']:
224 # Always use checksums (makes more sense than timestamps).
225 SetOption ('max_drift', 0)
226 # Using *content* checksums prevents rebuilds after
227 # [re]configure if config.hh has not changed. Too bad that it
229 TargetSignatures ('content')
231 absbuild
= Dir (env
['build']).abspath
232 outdir
= os
.path
.join (Dir (env
['build']).abspath
, env
['out'])
233 run_prefix
= os
.path
.join (absbuild
, os
.path
.join (env
['out'], 'usr'))
236 config_hh
= os
.path
.join (outdir
, 'config.hh')
237 version_hh
= os
.path
.join (outdir
, 'version.hh')
239 env
.Alias ('config', config_cache
)
241 cachedir
= os
.path
.join (outdir
, 'build-cache')
243 if not os
.path
.exists (cachedir
):
244 os
.makedirs (cachedir
)
248 # No need to set $LILYPOND_DATADIR to run lily, but cannot install...
249 if env
['debugging'] and not 'install' in COMMAND_LINE_TARGETS
:
250 env
['prefix'] = run_prefix
252 prefix
= env
['prefix']
253 bindir
= os
.path
.join (prefix
, 'bin')
254 sharedir
= os
.path
.join (prefix
, 'share')
255 libdir
= os
.path
.join (prefix
, 'lib')
256 libdir_package
= os
.path
.join (libdir
, package
.name
)
257 libdir_package_version
= os
.path
.join (libdir_package
, version
)
258 localedir
= os
.path
.join (sharedir
, 'locale')
259 sharedir_doc_package
= os
.path
.join (sharedir
, 'doc', package
.name
)
260 sharedir_package
= os
.path
.join (sharedir
, package
.name
)
261 sharedir_package_version
= os
.path
.join (sharedir_package
, version
)
262 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/music-drawing-routines.ps',
320 'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
321 ('mf', 'share/lilypond/%(ver)s/otf'),
322 ('mf', 'share/lilypond/%(ver)s/tfm'),
323 ('tex', 'share/lilypond/%(ver)s/tex/enc'),
324 ('#mf', 'share/lilypond/%(ver)s/fonts/mf'),
325 ('mf', 'share/lilypond/%(ver)s/fonts/map'),
326 ('mf', 'share/lilypond/%(ver)s/fonts/otf'),
327 ('mf', 'share/lilypond/%(ver)s/fonts/tfm'),
328 ('mf', 'share/lilypond/%(ver)s/fonts/type1'),
329 ('#tex', 'share/lilypond/%(ver)s/tex/source'),
330 ('tex', 'share/lilypond/%(ver)s/tex/tex-out'),
331 ('mf', 'share/lilypond/%(ver)s/tex/mf-out'),
332 ('#ly', 'share/lilypond/%(ver)s/ly'),
333 ('#scm', 'share/lilypond/%(ver)s/scm'),
334 ('#scripts', 'share/lilypond/%(ver)s/scripts'),
335 ('#ps', 'share/lilypond/%(ver)s/ps'),
336 ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
337 ('elisp', 'share/lilypond/%(ver)s/elisp')))
339 print "FIXME: BARF BARF BARF"
343 prefix
= os
.path
.join (env
['out'], 'usr/share/lilypond/%(ver)s/fonts'
345 for ext
in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
346 dir = os
.path
.join (absbuild
, prefix
, ext
)
347 os
.system ('rm -f ' + dir)
350 os
.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
354 def configure (target
, source
, env
):
355 dre
= re
.compile ('\n(200[0-9]{5})')
356 vre
= re
.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
358 def get_version (program
):
359 command
= '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
360 pipe
= os
.popen (command
)
361 output
= pipe
.read ()
364 splits
= re
.sub ('^|\s', '\n', output
)
365 date_hack
= re
.sub (dre
, '\n0.0.\\1', splits
)
366 m
= re
.match (vre
, date_hack
)
370 return string
.split (v
, '.')
372 def test_version (lst
, full_name
, minimal
, description
, package
):
373 program
= os
.path
.basename (full_name
)
374 sys
.stdout
.write ('Checking %s version... ' % program
)
375 actual
= get_version (program
)
378 lst
.append ((description
, package
, minimal
, program
,
381 print string
.join (actual
, '.')
382 if map (string
.atoi
, actual
) \
383 < map (string
.atoi
, string
.split (minimal
, '.')):
384 lst
.append ((description
, package
, minimal
, program
,
385 string
.join (actual
, '.')))
389 def test_program (lst
, program
, minimal
, description
, package
):
390 key
= program
.upper ()
392 key
= re
.sub ('\+', 'X', key
)
393 key
= re
.sub ('-', '_', key
)
394 sys
.stdout
.write ('Checking for %s ... ' % program
)
395 if env
.has_key (key
):
397 sys
.stdout
.write ('(cached) ')
399 f
= WhereIs (program
)
403 lst
.append ((description
, package
, minimal
, program
,
407 return test_version (lst
, program
, minimal
, description
, package
)
409 def test_lib (lst
, program
, minimal
, description
, package
):
410 # FIXME: test for Debian or RPM (or -foo?) based dists
411 # to guess (or get correct!: apt-cache search?)
413 #if os.system ('pkg-config --atleast-version=0 freetype2'):
415 if test_version (lst
, program
, minimal
, description
,
416 'lib%(package)s-dev or %(package)s-devel'
418 env
.ParseConfig ('pkg-config --cflags --libs %(program)s'
424 test_program (required
, 'bash', '2.0', 'Bash', 'bash')
425 test_program (required
, 'gcc', '4.0', 'GNU C compiler', 'gcc')
426 test_program (required
, 'g++', '4.0.5', 'GNU C++ compiler', 'g++')
427 test_program (required
, 'guile-config', '1.8', 'GUILE development',
428 'libguile-dev or guile-devel')
429 test_program (required
, 'mf', '0.0', 'Metafont', 'tetex-bin')
430 test_program (required
, 'mftrace', '1.1.19',
431 'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
432 test_program (required
, 'python', '2.1', 'Python (www.python.org)',
434 # Silly, and breaks with /bin/sh == dash
435 #test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
438 # Do not use bison 1.50 and 1.75.
439 #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
440 test_program (optional
, 'bison', '1.25', 'Bison -- parser generator',
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.8', '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
, 'makeinfo', '4.8', 'Makeinfo tool', 'texinfo')
451 test_program (optional
, 'perl', '4.0',
452 'Perl practical efficient readonly language', 'perl')
454 def CheckYYCurrentBuffer (context
):
455 context
.Message ('Checking for yy_current_buffer... ')
456 ret
= conf
.TryCompile ("""using namespace std;
457 #include <FlexLexer.h>
458 class yy_flex_lexer: public yyFlexLexer
463 yy_current_buffer = 0;
469 conf
= Configure (env
, custom_tests
= { 'CheckYYCurrentBuffer'
470 : CheckYYCurrentBuffer
})
473 'DIRSEP' : "'%s'" % os
.sep
,
474 'PATHSEP' : "'%s'" % os
.pathsep
,
475 'PACKAGE': '"%s"' % package
.name
,
476 'DATADIR' : '"%s"' % sharedir
,
477 'PACKAGE_DATADIR' : '"%s"' % sharedir_package
,
478 'LOCALEDIR' : '"%s"' %localedir
,
480 conf
.env
.Append (DEFINES
= defines
)
482 command
= r
"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
483 PYTHON_INCLUDE
= os
.popen (command
).read ()#[:-1]
485 env
.Append (CCFLAGS
= ['-I%s' % PYTHON_INCLUDE
])
487 env
.Append (CPPPATH
= [PYTHON_INCLUDE
])
489 headers
= ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
490 'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
492 if conf
.CheckCHeader (i
):
493 key
= re
.sub ('[./]', '_', 'HAVE_' + string
.upper (i
))
494 conf
.env
['DEFINES'][key
] = 1
496 ccheaders
= ('sstream',)
498 if conf
.CheckCXXHeader (i
):
499 key
= re
.sub ('[./]', '_', 'HAVE_' + string
.upper (i
))
500 conf
.env
['DEFINES'][key
] = 1
502 functions
= ('chroot', 'fopencookie', 'funopen',
504 'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
506 if 0 or conf
.CheckFunc (i
):
507 key
= re
.sub ('[./]', '_', 'HAVE_' + string
.upper (i
))
508 conf
.env
['DEFINES'][key
] = 1
510 if conf
.CheckYYCurrentBuffer ():
511 conf
.env
['DEFINES']['HAVE_FLEXLEXER_YY_CURRENT_BUFFER'] = 1
513 if conf
.CheckLib ('dl'):
518 if env
.has_key ('CPPPATH'):
519 cpppath
= env
['CPPPATH']
521 ## FIXME: linkage, check for libguile.h and scm_boot_guile
522 #this could happen after flower...
523 env
.ParseConfig ('guile-config compile')
525 test_program (required
, 'pkg-config', '0.9.0',
526 'pkg-config library compile manager', 'pkg-config')
527 if test_lib (required
, 'freetype2', '0.0',
528 'Development files for FreeType 2 font engine',
530 conf
.env
['DEFINES']['HAVE_FREETYPE2'] = '1'
532 if test_lib (required
, 'pangoft2', '1.6.0',
533 'Development files for pango, with FreeType2',
535 conf
.env
['DEFINES']['HAVE_PANGO_FT2'] = '1'
537 if test_lib (optional
, 'fontconfig', '2.2.0',
538 'Development files for fontconfig', 'fontconfig1'):
539 conf
.env
['DEFINES']['HAVE_FONTCONFIG'] = '1'
541 #this could happen only for compiling pango-*
543 test_lib (required
, 'gtk+-2.0', '2.4.0',
544 'Development files for GTK+', 'gtk2.0')
547 # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
548 # <system-dir>] speeds up SCons
549 env
['CCFLAGS'] += map (lambda x
: '-I' + x
,
550 env
['CPPPATH'][len (cpppath
):])
551 env
['CPPPATH'] = cpppath
555 print '********************************'
556 print 'Please install required packages'
558 print '%s: %s-%s or newer (found: %s %s)' % i
563 print '*************************************'
564 print 'Consider installing optional packages'
566 print '%s: %s-%s or newer (found: %s %s)' % i
568 return conf
.Finish ()
570 def config_header (target
, source
, env
):
571 config
= open (str (target
[0]), 'w')
572 for i
in sorted (env
['DEFINES'].keys ()):
573 config
.write ('#define %s %s\n' % (i
, env
['DEFINES'][i
]))
575 env
.Command (config_hh
, config_cache
, config_header
)
591 if not d
.has_key (lst
[i
]):
599 def uniquify_config_vars (env
):
600 for i
in config_vars
:
601 if env
.has_key (i
) and type (env
[i
]) == type ([]):
602 env
[i
] = uniquify (env
[i
])
604 def save_config_cache (env
):
605 ## FIXME: Is this smart, using option cache for saving
606 ## config.cache? I cannot seem to find the official method.
607 uniquify_config_vars (env
)
608 opts
.Save (config_cache
, env
)
610 if 'config' in COMMAND_LINE_TARGETS
:
611 sys
.stdout
.write ('\n')
612 sys
.stdout
.write ('LilyPond configured')
613 sys
.stdout
.write ('\n')
614 sys
.stdout
.write ('Now run')
615 sys
.stdout
.write ('\n')
616 sys
.stdout
.write (' scons [TARGET|DIR]...')
617 sys
.stdout
.write ('\n')
618 sys
.stdout
.write ('\n')
619 sys
.stdout
.write ('Examples:')
620 sys
.stdout
.write ('\n')
621 sys
.stdout
.write (' scons lily # build lilypond')
622 sys
.stdout
.write ('\n')
623 sys
.stdout
.write (' scons all # build everything')
624 sys
.stdout
.write ('\n')
625 sys
.stdout
.write (' scons doc # build documentation')
626 sys
.stdout
.write ('\n')
628 ## sys.stdout.write (' scons prefix=/usr DESTDIR=/tmp/pkg all install')
629 ## sys.stdout.write ('\n')
631 elif not env
['checksums']:
632 # When using timestams, config.hh is NEW. The next
633 # build triggers recompilation of everything. Exiting
634 # here makes SCons use the actual timestamp for config.hh
635 # and prevents recompiling everything the next run.
636 command
= sys
.argv
[0] + ' ' + string
.join (COMMAND_LINE_TARGETS
)
637 sys
.stdout
.write ('Running %s ... ' % command
)
638 sys
.stdout
.write ('\n')
639 s
= os
.system (command
)
643 # scons: *** Calling Configure from Builders is not supported.
644 # env.Command (config_cache, None, configure)
645 if not os
.path
.exists (config_cache
) \
646 or (os
.stat ('SConstruct')[stat
.ST_MTIME
]
647 > os
.stat (config_cache
)[stat
.ST_MTIME
]):
648 env
= configure (None, None, env
)
649 save_config_cache (env
)
650 elif env
['checksums']:
651 # just save everything
652 save_config_cache (env
)
654 #urg how does #/ subst work?
656 SConscript ('buildscripts/builder.py')
658 env
.PrependENVPath ('PATH',
659 os
.path
.join (env
['absbuild'], env
['out'], 'usr/bin'))
661 LILYPOND_DATADIR
= os
.path
.join (run_prefix
, 'share/lilypond/', version
)
663 if not os
.path
.exists (LILYPOND_DATADIR
):
664 os
.makedirs (LILYPOND_DATADIR
)
666 env
.Command (LILYPOND_DATADIR
, ['#/SConstruct', '#/VERSION'], symlink_tree
)
667 env
.Depends ('lily', LILYPOND_DATADIR
)
670 'LILYPOND_DATADIR' : LILYPOND_DATADIR
,
671 'TEXMF' : '{$LILYPOND_DATADIR,'
672 + os
.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
675 BUILD_ABC2LY
= '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
676 BUILD_LILYPOND
= '$absbuild/lily/$out/lilypond ${__verbose}'
677 BUILD_LILYPOND_BOOK
= '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
679 if env
['verbose'] and env
['verbose'] != '0':
680 env
['__verbose'] = ' --verbose'
681 env
['set__x'] = 'set -x;'
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 LILYPOND
= BUILD_LILYPOND
,
698 ABC2LY
= BUILD_ABC2LY
,
699 LILYPOND_BOOK
= BUILD_LILYPOND_BOOK
,
700 LILYPOND_BOOK_FORMAT
= 'texi-html',
701 MAKEINFO_FLAGS
= '--css-include=$srcdir/Documentation/texinfo.css',
704 env
.Append (CCFLAGS
= ['-pipe', '-Wno-pmf-conversions'])
706 env
.Append (CCFLAGS
= ['-g'])
707 if env
['optimising']:
708 env
.Append (CCFLAGS
= '-O2')
710 env
.Append (CCFLAGS
= ['-W', '-Wall'])
711 env
.Append (CXXFLAGS
= ['-Wconversion'])
714 env
.Append (LINKFLAGS
= ['-Wl,--export-dynamic'])
715 # FIXME: ParseConfig ignores -L flag?
716 env
.Append (LINKFLAGS
= ['-L/usr/X11R6/lib'])
718 ## Explicit target and dependencies
720 if 'clean' in COMMAND_LINE_TARGETS
:
721 # ugh: prevent reconfigure instead of clean
722 os
.system ('touch %s' % config_cache
)
724 command
= sys
.argv
[0] + ' -c .'
725 sys
.stdout
.write ('Running %s ... ' % command
)
726 sys
.stdout
.write ('\n')
727 s
= os
.system (command
)
728 if os
.path
.exists (config_cache
):
729 os
.unlink (config_cache
)
732 if 'sconsclean' in COMMAND_LINE_TARGETS
:
733 command
= 'rm -rf scons.cache $(find . -name ".scon*")'
734 s
= os
.system (command
)
735 if os
.path
.exists (config_cache
):
736 os
.unlink (config_cache
)
739 if 'realclean' in COMMAND_LINE_TARGETS
:
740 command
= 'rm -rf $(find . -name "out-scons" -o -name ".scon*")'
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 # Declare SConscript phonies
749 env
.Alias ('minimal', config_cache
)
752 env
.Alias ('mf-essential', config_cache
)
753 env
.Alias ('minimal', ['python', 'lily', 'mf-essential'])
754 env
.Alias ('all', ['minimal', 'mf', '.'])
757 env
.Alias ('minimal', ['python', 'lily', 'mf'])
758 env
.Alias ('all', ['minimal', '.'])
761 # Do we want the doc/web separation?
765 'Documentation/user',
766 'Documentation/topdocs',
767 'Documentation/bibliography',
770 # Without target arguments, do minimal build
771 if not COMMAND_LINE_TARGETS
:
772 env
.Default (['minimal'])
774 # GNU Make rerouting compat:
775 env
.Alias ('web', 'doc')
778 env
.Command (version_hh
, '#/VERSION',
779 '$PYTHON ./stepmake/bin/make-version.py VERSION > $TARGET')
781 # post-config environment update
783 run_prefix
= run_prefix
,
784 LILYPOND_DATADIR
= LILYPOND_DATADIR
,
786 # FIXME: move to lily/SConscript?
787 LIBPATH
= [os
.path
.join (absbuild
, 'flower', env
['out'])],
788 CPPPATH
= [outdir
, ],
789 LILYPOND_PATH
= ['.',
791 '$srcdir/input/regression',
792 '$srcdir/input/test',
793 '$srcdir/input/tutorial',
794 '$srcdir/Documentation/user',
796 # os.path.join (absbuild, 'Documentation',
798 # os.path.join (absbuild, 'Documentation/user',
801 MAKEINFO_PATH
= ['.', '$srcdir/Documentation/user',
802 '$absbuild/Documentation/user/$out'],
809 def cvs_entry_is_dir (line
):
810 return line
[0] == 'D' and line
[-2] == '/'
812 def cvs_entry_is_file (line
):
813 return line
[0] == '/' and line
[-2] == '/'
816 entries
= os
.path
.join (dir, 'CVS/Entries')
817 if not os
.path
.exists (entries
):
819 entries
= open (entries
).readlines ()
820 dir_entries
= filter (cvs_entry_is_dir
, entries
)
821 dirs
= map (lambda x
: os
.path
.join (dir, x
[2:x
[2:].index ('/')+3]),
823 return dirs
+ map (cvs_dirs
, dirs
)
826 entries
= os
.path
.join (dir, 'CVS/Entries')
827 if not os
.path
.exists (entries
):
829 entries
= open (entries
).readlines ()
830 file_entries
= filter (cvs_entry_is_file
, entries
)
831 files
= map (lambda x
: x
[1:x
[1:].index ('/')+1], file_entries
)
832 return map (lambda x
: os
.path
.join (dir, x
), files
)
834 def flatten (tree
, lst
):
835 if type (tree
) == type ([]):
837 if type (i
) == type ([]):
843 if os
.path
.isdir ('%(srcdir)s/CVS' % vars ()):
844 subdirs
= flatten (cvs_dirs ('.'), [])
847 command
= 'cd %(srcdir)s \
848 && find . -name SConscript | sed s@/SConscript@@' % vars ()
849 subdirs
= string
.split (os
.popen (command
).read ())
852 and 'all' not in COMMAND_LINE_TARGETS\
853 and 'doc' not in COMMAND_LINE_TARGETS\
854 and 'web' not in COMMAND_LINE_TARGETS\
855 and 'install' not in COMMAND_LINE_TARGETS\
856 and 'clean' not in COMMAND_LINE_TARGETS
:
857 subdirs
= [ 'python',
863 if os
.path
.isdir ('%(srcdir)s/CVS' % vars ()):
864 src_files
= reduce (lambda x
, y
: x
+ y
, map (cvs_files
, subdirs
))
866 src_files
= ['foobar']
868 readme_files
= ['AUTHORS', 'README', 'INSTALL', 'NEWS']
869 txt_files
= map (lambda x
: x
+ '.txt', readme_files
)
873 # speeds up build by +- 5%
876 foo
= map (lambda x
: env
.TXT (x
+ '.txt',
877 os
.path
.join ('Documentation/topdocs', x
)),
879 tar_base
= package
.name
+ '-' + version
880 tar_name
= tar_base
+ '.tar.gz'
881 ball_prefix
= os
.path
.join (outdir
, tar_base
)
882 tar_ball
= os
.path
.join (outdir
, tar_name
)
884 dist_files
= src_files
+ txt_files
885 ball_files
= map (lambda x
: os
.path
.join (ball_prefix
, x
), dist_files
)
886 map (lambda x
: env
.Depends (tar_ball
, x
), ball_files
)
887 map (lambda x
: env
.Command (os
.path
.join (ball_prefix
, x
), x
,
888 'ln $SOURCE $TARGET'), dist_files
)
889 tar
= env
.Command (tar_ball
, src_files
,
890 ['rm -f $$(find $TARGET.dir -name .sconsign)',
891 'tar czf $TARGET -C $TARGET.dir %s' % tar_base
,])
892 env
.Alias ('tar', tar
)
894 dist_ball
= os
.path
.join (package
.release_dir
, tar_name
)
895 env
.Command (dist_ball
, tar_ball
,
896 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
897 + 'ln $SOURCE $TARGET')
898 env
.Depends ('dist', dist_ball
)
899 patch_name
= os
.path
.join (outdir
, tar_base
+ '.diff.gz')
900 patch
= env
.PATCH (patch_name
, tar_ball
)
901 env
.Depends (patch_name
, dist_ball
)
902 env
.Alias ('release', patch
)
906 web_base
= os
.path
.join (outdir
, 'web')
907 web_ball
= web_base
+ '.tar.gz'
908 env
['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
909 web_ext
= ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
910 web_path
= '-path "*/$out/*"' + string
.join (web_ext
, ' -or -path "*/$out/*"') + '-or -type l'
911 env
['web_path'] = web_path
912 web_list
= os
.path
.join (outdir
, 'weblist')
913 # compatible make heritits
914 # fixme: generate in $outdir is cwd/builddir
915 env
.Command (web_list
,
916 ## Adding 'doc' dependency is correct, but takes
917 ## > 5min extra if you have a peder :-)
921 ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
922 'cd $absbuild && $footify $$(find . -name "*.html" -print)',
923 'cd $absbuild && rm -f $$(find . -name "*.html~" -print)',
924 'cd $absbuild && find Documentation input $web_path \
926 '''echo '<META HTTP-EQUIV="refresh" content="0;URL=Documentation/out-www/index.html">' > $absbuild/index.html''',
927 '''echo '<html><body>Redirecting to the documentation index...</body></html>' >> $absbuild/index.html''',
928 'cd $absbuild && ls *.html >> $TARGET',])
929 env
.Command (web_ball
, web_list
,
930 ['cat $SOURCE | tar -C $absbuild -czf $TARGET -T -',])
931 #env.Alias ('web', web_ball)
932 www_base
= os
.path
.join (outdir
, 'www')
933 www_ball
= www_base
+ '.tar.gz'
934 env
.Command (www_ball
, web_ball
,
936 'mkdir -p $absbuild/$out/tmp',
937 'tar -C $absbuild/$out/tmp -xzf $SOURCE',
938 'cd $absbuild/$out/tmp && for i in $$(find . -name "$out"); '
939 + ' do mv $$i $$(dirname $$i)/out-www; done',
940 'tar -C $absbuild/$out/tmp -czf $TARGET .'])
941 env
.Alias ('web', www_ball
)
945 ETAGSFLAGS
= """--regex='{c++}/^LY_DEFINE *(\([^,]+\)/\\1/' \
946 --regex='{c++}/^LY_DEFINE *([^"]*"\([^"]+\)"/\\1/'""")
947 code_ext
= ['.cc', '.hh', '.scm', '.tcc',]
948 env
.Command ('TAGS', filter (lambda x
: os
.path
.splitext (x
)[1] in code_ext
,
950 'etags $ETAGSFLAGS $SOURCES')
952 # Note: SConscripts are only needed in directories where something needs
953 # to be done, building or installing
955 if os
.path
.exists (os
.path
.join (d
, 'SConscript')):
956 b
= os
.path
.join (env
['build'], d
, env
['out'])
957 # Support clean sourcetree build (--srcdir build)
959 if os
.path
.abspath (b
) != os
.path
.abspath (d
):
960 env
.BuildDir (b
, d
, duplicate
= 0)
961 SConscript (os
.path
.join (b
, 'SConscript'))
963 env
.Command ('tree', ['#/VERSION', '#/SConstruct'], symlink_tree
)