Usage:
scons
+ scons lily # build lily
+
+ LILYPONDPREFIX=out-scons/usr/share/lilypond lily/out-scons/lilypond-bin
+ scons doc # build web doc
+
+ scons fonts # build all font stuff (split this? )
+
+ scons config # reconfigure
+
+ scons / # builds all possible targets
+
scons install
scons -c # clean
scons -h # help
debugging=1
gui=1
os.path.join (os.getcwd (), '=install')
+prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
'''
# TODO:
-# * running from build-dir, without installing?
-# - scons will not install, if PREFIX lives outside of CWD
-# - build symlink tree
-# + mimicking regular installation setup?
-# + use tweaked scons 'install' target?
+# * add missing dirs
+# * cleanup
+
+# * separate environments?
+# - compile environment checks headers and libraries
+# - doc environment checks doc stuff
+
# * commandline targets:
-# - clean => -c
-# - dist, tar => env.Tar
-# * Documentation, scripts
-# * env.Tar
+# - clean => -c ?
# * more fine-grained config.h -- move lilypondprefix to version.hh?
# - config.h: changes after system upgrades, affects all files
# - version.hh: prefix, version etc? affects few
import sys
import string
+subdirs = ['flower', 'lily', 'mf', 'scm', 'ly', 'Documentation',
+ 'Documentation/user', 'input']
+
+usage = r'''Usage:
+scons [KEY=VALUE].. [TARGET]..
+
+where TARGET is config|lily|all|fonts|doc|tar|dist|release
+'''
+
env = Environment ()
-# put your favourite stuff in custom.py
-opts = Options ('custom.py', ARGUMENTS)
+# Without target arguments, build lily only
+if not COMMAND_LINE_TARGETS:
+ env.Default ('lily')
+
+# All builds everything (all directories)
+env.Alias ('all', ['lily', 'mf', 'input', 'Documentation'])
+
+
+## FIXME: opts in function
+
+# Put your favourite stuff in custom.py
+opts = Options (['config.cache', 'custom.py'], ARGUMENTS)
opts.Add ('prefix', 'Install prefix', '/usr/')
opts.Add ('out', 'Output directory', 'out-scons')
opts.Add ('build', 'Build directory', '.')
0),
)
-Help (opts.GenerateHelpText (env))
+Help (usage + opts.GenerateHelpText (env))
env = Environment (options = opts)
+opts.Update (env)
+opts.Save ('config.cache', env)
+
env.CacheDir (os.path.join (env['build'], '=build-cache'))
#ugh
env.Append (CXXFLAGS = '-Wall')
env.Append (CXXFLAGS = '-Wconversion')
-env['MFMODE'] = 'ljfour'
-conf = Configure (env)
-
-
-vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
-def get_version (program):
- command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
- pipe = os.popen (command)
- output = pipe.read ()
- if pipe.close ():
- return None
- v = re.sub (vre, '\\1', output)
- return string.split (v, '.')
-
-def assert_version (lst, program, minimal, description, package):
- global required
- sys.stdout.write ('Checking %s version... ' % program)
- actual = get_version (program)
- if not actual:
- print 'not found'
- lst.append ((description, package, minimal, program,
- 'not installed'))
- return
- sys.stdout.write (string.join (actual, '.'))
- sys.stdout.write ('\n')
- if actual < string.split (minimal, '.'):
- lst.append ((description, package, minimal, program,
- string.join (actual, '.')))
-
-required = []
-assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
-assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
-assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
-assert_version (required, 'guile-config', '1.6', 'GUILE development',
- 'libguile-dev or guile-devel')
-# Do not use bison 1.50 and 1.75.
-assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
- 'bison')
-assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
-
-
-optional = []
-assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
-assert_version (optional, 'guile', '1.6', 'GUILE scheme',
- 'libguile-dev or guile-devel')
-assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
- 'mftrace')
-assert_version (optional, 'perl', '4.0',
- 'Perl practical efficient readonly language', 'perl')
-#assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
-
-
-defines = {
- 'DIRSEP' : "'/'",
- 'PATHSEP' : "':'",
- 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
- 'PACKAGE': '"' + package.name + '"',
- 'DATADIR' : '"' + env['sharedir'] + '"',
- 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
- 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
- 'LOCALEDIR' : '"' + env['localedir'] + '"',
-}
-
-
-command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
-PYTHON_INCLUDE = os.popen (command).read ()
-env.Append (CPPPATH = PYTHON_INCLUDE)
-
-
-headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
-for i in headers:
- if conf.CheckCHeader (i):
- key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
- defines[key] = '1'
-
-ccheaders = ('sstream',)
-for i in ccheaders:
- if conf.CheckCXXHeader (i):
- key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
- defines[key] = '1'
-
-functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
-for i in functions:
- if 0 or conf.CheckFunc (i):
- key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
- defines[key] = '1'
-
-
-key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
-defines[key] = conf.TryCompile ("""using namespace std;
-#include <FlexLexer.h>
-class yy_flex_lexer: public yyFlexLexer
-{
- public:
- yy_flex_lexer ()
- {
- yy_current_buffer = 0;
- }
-};""", 'cc')
-
-if conf.CheckLib ('dl'):
- pass
-
-if conf.CheckLib ('kpathsea'):
- defines['KPATHSEA'] = '1'
-
-# huh?
-if conf.CheckLib ('kpathsea', 'kpse_find_file'):
- defines['HAVE_KPSE_FIND_FILE'] = '1'
-if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
- defines['HAVE_KPSE_FIND_TFM'] = '1'
-
-#this could happen after flower...
-env.ParseConfig ('guile-config compile')
-
-#this could happen only for compiling pango-*
-if env['gui']:
- env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
- env.ParseConfig ('pkg-config --cflags --libs pango')
- if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
- defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
-
- if conf.CheckLib ('pango-1.0',
- 'pango_fc_font_map_add_decoder_find_func'):
- defines['HAVE_PANGO_CVS'] = '1'
- defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
-
-env = conf.Finish ()
+##Import ('env')
+here = os.getcwd ()
+reldir = str (Dir ('.').srcnode ())
+os.chdir (reldir)
+srcdir = os.getcwd ()
+os.chdir (here)
+##outdir = os.path.join (env['build'], reldir, env['out'])
+outdir = os.path.join (env['build'], env['out'])
+env['srcdir'] = srcdir
build = env['build']
out = env['out']
-##reldir = str (Dir ('.').srcnode ())
-reldir = os.getcwd ()
-outdir = os.path.join (env['build'], reldir, env['out'])
-if not os.path.exists (outdir):
- os.mkdir (outdir)
+
def list_sort (lst):
sorted = lst
sorted.sort ()
return sorted
-
-config = open (os.path.join (outdir, 'config.h'), 'w')
-for i in list_sort (defines.keys ()):
- config.write ('#define %s %s\n' % (i, defines[i]))
-config.close ()
-os.system (sys.executable \
- + ' ./stepmake/bin/make-version.py VERSION > '\
- + os.path.join (outdir, 'version.hh'))
+env['MFMODE'] = 'ljfour'
+config_h = os.path.join (outdir, 'config.h')
+env.Alias ('config', config_h)
+
+def configure (env):
+ conf = Configure (env)
+
+ vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
+ def get_version (program):
+ command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
+ pipe = os.popen (command)
+ output = pipe.read ()
+ if pipe.close ():
+ return None
+ v = re.sub (vre, '\\1', output)
+ return string.split (v, '.')
+
+ def assert_version (lst, program, minimal, description, package):
+ global required
+ sys.stdout.write ('Checking %s version... ' % program)
+ actual = get_version (program)
+ if not actual:
+ print 'not found'
+ lst.append ((description, package, minimal, program,
+ 'not installed'))
+ return
+ sys.stdout.write (string.join (actual, '.'))
+ sys.stdout.write ('\n')
+ if actual < string.split (minimal, '.'):
+ lst.append ((description, package, minimal, program,
+ string.join (actual, '.')))
+
+ required = []
+ assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
+ assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
+ assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
+ assert_version (required, 'guile-config', '1.6', 'GUILE development',
+ 'libguile-dev or guile-devel')
+ # Do not use bison 1.50 and 1.75.
+ assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
+ 'bison')
+ assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
+
+
+ optional = []
+ assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
+ assert_version (optional, 'guile', '1.6', 'GUILE scheme',
+ 'libguile-dev or guile-devel')
+ assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
+ 'mftrace')
+ assert_version (optional, 'perl', '4.0',
+ 'Perl practical efficient readonly language', 'perl')
+ #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
+
+
+ defines = {
+ 'DIRSEP' : "'/'",
+ 'PATHSEP' : "':'",
+ 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
+ 'PACKAGE': '"' + package.name + '"',
+ 'DATADIR' : '"' + env['sharedir'] + '"',
+ 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
+ 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
+ 'LOCALEDIR' : '"' + env['localedir'] + '"',
+ }
+
+
+ command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
+ PYTHON_INCLUDE = os.popen (command).read ()
+ env.Append (CPPPATH = PYTHON_INCLUDE)
+
+ headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
+ for i in headers:
+ if conf.CheckCHeader (i):
+ key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
+ defines[key] = '1'
+
+ ccheaders = ('sstream',)
+ for i in ccheaders:
+ if conf.CheckCXXHeader (i):
+ key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
+ defines[key] = '1'
+
+ functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
+ for i in functions:
+ if 0 or conf.CheckFunc (i):
+ key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
+ defines[key] = '1'
+
+ key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
+
+ sys.stdout.write('Checking for yy_current_buffer ... ')
+ sys.stdout.flush()
+ res = conf.TryCompile ("""using namespace std;
+ #include <FlexLexer.h>
+ class yy_flex_lexer: public yyFlexLexer
+ {
+ public:
+ yy_flex_lexer ()
+ {
+ yy_current_buffer = 0;
+ }
+ };""", '.cc')
+ if res:
+ defines[key] = '1'
+ sys.stdout.write('yes\n')
+ else:
+ sys.stdout.write('no\n')
+
+
+ if conf.CheckLib ('dl'):
+ pass
+
+ if conf.CheckLib ('kpathsea'):
+ defines['KPATHSEA'] = '1'
+
+ # huh?
+ if conf.CheckLib ('kpathsea', 'kpse_find_file'):
+ defines['HAVE_KPSE_FIND_FILE'] = '1'
+ if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
+ defines['HAVE_KPSE_FIND_TFM'] = '1'
+
+ #this could happen after flower...
+ env.ParseConfig ('guile-config compile')
+
+ #this could happen only for compiling pango-*
+ if env['gui']:
+ env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
+ env.ParseConfig ('pkg-config --cflags --libs pango')
+ if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
+ defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
+
+ if conf.CheckLib ('pango-1.0',
+ 'pango_fc_font_map_add_decoder_find_func'):
+ defines['HAVE_PANGO_CVS'] = '1'
+ defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
+
+ # ugh - needed at all? make Builder/Command for config.h!
+ if not os.path.exists (outdir):
+ os.mkdir (outdir)
+
+ config = open (config_h, 'w')
+ for i in list_sort (defines.keys ()):
+ config.write ('#define %s %s\n' % (i, defines[i]))
+ config.close ()
+
+
+ os.system (sys.executable \
+ + ' ./stepmake/bin/make-version.py VERSION > '\
+ + os.path.join (outdir, 'version.hh'))
+
+ if required:
+ print
+ print '********************************'
+ print 'Please install required packages'
+ for i in required:
+ print '%s: %s-%s or newer (found: %s %s)' % i
+ sys.exit (1)
+
+ if optional:
+ print
+ print '*************************************'
+ print 'Consider installing optional packages'
+ for i in optional:
+ print '%s: %s-%s or newer (found: %s %s)' % i
+
+ return conf.Finish ()
+
+# Hmm. Must configure when building lily, to get compiler and linker
+# flags set-up.
+# FIXME
+if not os.path.exists (config_h) or 'config' in COMMAND_LINE_TARGETS\
+ or 'lily' in BUILD_TARGETS or 'all' in BUILD_TARGETS:
+ env = configure (env)
if os.path.exists ('parser'):
env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
env.Append (LIBPATH = ['#/flower/' + out,],
CPPPATH = [outdir, '#',])
-if required:
- print
- print '********************************'
- print 'Please install required packages'
- for i in required:
- print '%s: %s-%s or newer (found: %s %s)' % i
- sys.exit (1)
-
-if optional:
- print
- print '*************************************'
- print 'Consider installing optional packages'
- for i in optional:
- print '%s: %s-%s or newer (found: %s %s)' % i
-
-#env['tarball'] = os.path.join (outdir,
-# package.name + '-' + env['version'] + '.tar.gz')
-
-env['tarball'] = os.path.join ('~/tmp',
- package.name + '-' + env['version'] + '.tar.gz')
-
Export ('env')
-#subdirs = ['mf',]
-#subdirs = ['flower', 'lily', 'parser', 'gui', 'main',]
-subdirs = ['flower', 'lily', 'mf', 'scm', 'ly']
+#ugr
+if build == '.':
+ absbuild = os.getcwd ()
+else:
+ absbuild = build
+env['absbuild'] = absbuild
+
+# duh
+env['MAKEINFO'] = 'LANG= makeinfo'
+env['PYTHON'] = 'python'
+env['LILYPOND_BIN'] = os.path.join (absbuild, 'lily', out, 'lilypond-bin')
+env['LILYPONDPREFIX'] = os.path.join (outdir, 'usr/share/lilypond')
+env['LILYPOND_BOOK'] = srcdir + '/scripts/lilypond-book.py'
+env['ABC2LY_PY'] = srcdir + '/scripts/abc2ly.py'
+env['MF_TO_TABLE_PY'] = srcdir + '/buildscripts/mf-to-table.py'
+env['LILYPOND_PY'] = srcdir + '/scripts/lilypond.py'
+env['LILYPOND_BOOK_FLAGS'] = ''
+env['LILYPOND_BOOK_FORMAT'] = 'texi-html'
+# ugh?
+env['LILYPOND_BOOK_PATH'] = ['.', '#/input', '#/input/regression',
+ '#/input/test', '#/input/tutorial',
+ os.path.join (absbuild, 'mf', out),
+ '#/Documentation/user',
+ os.path.join (absbuild, 'Documentation', out),
+ os.path.join (absbuild, 'Documentation/user', out),
+ ]
+
+env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
+ os.path.join (absbuild, 'Documentation/user', out)]
+
+## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
+env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
+
+SConscript ('buildscripts/builder.py')
+
for d in subdirs:
b = os.path.join (build, d, out)
# Support clean sourctree build (srcdir build)
env.BuildDir (b, d, duplicate=0)
SConscript (os.path.join (b, 'SConscript'))
+# as a builder?
+def symlink_tree (prefix):
+ def mkdirs (dir):
+ def mkdir (dir):
+ if not dir:
+ os.chdir (os.sep)
+ return
+ if not os.path.isdir (dir):
+ if os.path.exists (dir):
+ os.unlink (dir)
+ os.mkdir (dir)
+ os.chdir (dir)
+ map (mkdir, string.split (dir, os.sep))
+ def symlink (src, dst):
+ os.chdir (absbuild)
+ dir = os.path.dirname (dst)
+ mkdirs (dir)
+ if src[0] == '#':
+ frm = os.path.join (srcdir, src[1:])
+ else:
+ depth = len (string.split (dir, '/'))
+ frm = os.path.join ('../' * depth, src, out)
+ os.symlink (frm, os.path.basename (dst))
+ map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
+ (('python', 'lib/lilypond/python'),
+ # UGHR, lilypond.py uses lilypond-bin from PATH
+ ('lily', 'bin'),
+ ('#mf', 'share/lilypond/fonts/mf'),
+ ('mf', 'share/lilypond/fonts/afm'),
+ ('mf', 'share/lilypond/fonts/tfm'),
+ ('mf', 'share/lilypond/fonts/type1'),
+ ('#tex', 'share/lilypond/tex/source'),
+ ('mf', 'share/lilypond/tex/generate'),
+ ('#ly', 'share/lilypond/ly'),
+ ('#scm', 'share/lilypond/scm'),
+ ('#ps', 'share/lilypond/ps'),
+ ('elisp', 'share/lilypond/elisp')))
+ os.chdir (srcdir)
-readmes = ['AUTHORS.txt', 'ChangeLog', 'NEWS.txt']
-
-#testing
-env.Append (TARFLAGS = '-z --owner=0 --group=0')
-env.Append (GZIPFLAGS = '-9')
-all_sources = ['SConstruct',] + readmes + subdirs
-x = env.Tar (env['tarball'], all_sources)
-
+if env['debugging']:
+ prefix = os.path.join (out, 'usr')
+ if not os.path.exists (prefix):
+ symlink_tree (prefix)
+
+#### dist, tar
+src_files = ['ChangeLog', '.cvsignore', 'Documentation/index.html.in',
+ 'lily/beam.cc']
+
+def cvs_files (dir):
+ entries = open (os.path.join (dir, 'CVS/Entries')).readlines ()
+ files = filter (lambda x: x[0] != 'D', entries)
+ return map (lambda x: os.path.join (dir, x[1:x[1:].index ('/')+1]),
+ files)
+
+readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
+foo = map (lambda x: env.Texi2txt (x + '.txt',
+ os.path.join ('Documentation/topdocs',
+ x)),
+ readme_files)
+txt_files = map (lambda x: x + '.txt', readme_files)
+src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
+tar_base = package.name + '-' + env['version']
+tar_name = tar_base + '.tar.gz'
+ball_prefix = os.path.join (outdir, tar_base)
+tar_ball = os.path.join (outdir, tar_name)
+
+dist_files = src_files + txt_files
+ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
+map (lambda x: env.Depends (tar_ball, x), ball_files)
+map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
+ 'ln $SOURCE $TARGET'), dist_files)
+tar = env.Command (tar_ball, src_files,
+ 'tar czf $TARGET -C $TARGET.dir %s' % tar_base)
+env.Alias ('tar', tar)
+
+dist_ball = os.path.join (package.release_dir, tar_name)
+env.Command (dist_ball, tar_ball,
+ 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
+ + 'ln $SOURCE $TARGET')
+env.Depends ('dist', dist_ball)
+patch_name = os.path.join (outdir, tar_base + '.diff.gz')
+patch = env.PATCH (patch_name, tar_ball)
+env.Depends (patch_name, dist_ball)
+env.Alias ('release', patch)