]> git.donarmstrong.com Git - lilypond.git/blobdiff - SConstruct
*** empty log message ***
[lilypond.git] / SConstruct
index 6246d5268ef9cdb61336fdb5db4ff3c14d808d64..3700c74e23535493efa4504a1306fdbbf5c7b8c3 100644 (file)
@@ -22,9 +22,9 @@ Run from build tree
     PATH=$run/bin:$PATH
 
     #optionally, if you do not use custom.py below
     PATH=$run/bin:$PATH
 
     #optionally, if you do not use custom.py below
-    #export LILYPONDPREFIX=$run/share/lilypond
+    #export LILYPONDPREFIX=$run/share/lilypond/<VERSION>
 
 
-    lilypond-bin input/simple
+    lilypond input/simple
 
 Other targets
     scons mf-essential         # build minimal mf stuff
 
 Other targets
     scons mf-essential         # build minimal mf stuff
@@ -60,9 +60,20 @@ prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
 
 
 # TODO:
 
 
 # TODO:
-#  * usability
 
 
-#  * more program configure tests (mfont, ...?)
+#  * reality check:
+#     - too many stages in Environments setup
+#       (see also buildscripts/builders.py)
+#     - Home-brew scons.cach configuration caching
+#     - Home-brew source tarball generating -- [why] isn't that in SCons?
+
+#  * usability and documentation for "./configure; make" users
+
+#  * too much cruft in toplevel SConstruct
+
+#  * (optional) operation without CVS directories, from tarball
+
+#  * more program configure tests, actually use full executable name
 
 #  * install doc
 
 
 #  * install doc
 
@@ -70,6 +81,7 @@ prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
 
 #  * grep FIXME $(find . -name 'S*t')
 
 
 #  * grep FIXME $(find . -name 'S*t')
 
+#  * drop "fast"
 
 import re
 import glob
 
 import re
 import glob
@@ -83,28 +95,49 @@ import shutil
 EnsureSConsVersion (0, 95)
 
 usage = r'''Usage:
 EnsureSConsVersion (0, 95)
 
 usage = r'''Usage:
-scons [KEY=VALUE].. [TARGET|DIR]..
+[ENVVAR=VALUE]... scons [OPTION=VALUE]... [TARGET|DIR]...
 
 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
          realclean, release, sconsclean, tar, TAGS
 
 
 TARGETS: clean, config, doc, dist, install, mf-essential, po-update,
          realclean, release, sconsclean, tar, TAGS
 
+ENVVARS: BASH, CCFLAGS, CC, CXX, LIBS, PYTHON, SH...
+         (see SConstruct:config_vars)
+
+OPTIONS:
 '''
       
 
 config_cache = 'scons.cache'
 '''
       
 
 config_cache = 'scons.cache'
+if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
+       os.unlink (config_cache)
 
 
+# All config_vars can be set as ENVVAR, eg:
+#
+#    CXX=g++-4.0 GS=~/usr/pkg/gs/bin/gs scons config
+#
+# append test_program variables automagically?
 config_vars = [
        'BASH',
 config_vars = [
        'BASH',
+       'BYTEORDER',
+       'CC',
        'CCFLAGS',
        'CPPPATH',
        'CPPDEFINES',
        'CCFLAGS',
        'CPPPATH',
        'CPPDEFINES',
+       'CXX',
        'CXXFLAGS',
        'DEFINES',
        'CXXFLAGS',
        'DEFINES',
+       'DVIPS',
+       'FONTFORGE',
+       'GCC',
+       'GXX',
+       'GS',
        'LIBS',
        'LINKFLAGS',
        'LIBS',
        'LINKFLAGS',
-       'METAFONT',
+       'MF',
+       'MFTRACE',
        'PERL',
        'PYTHON',
        'PERL',
        'PYTHON',
+       'SH',
        ]
 
 # Put your favourite stuff in custom.py
        ]
 
 # Put your favourite stuff in custom.py
@@ -125,13 +158,13 @@ opts.AddOptions (
        BoolOption ('static', 'build static libraries',
                    1),
        BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
        BoolOption ('static', 'build static libraries',
                    1),
        BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
-                   1),
+                   0),
        BoolOption ('verbose', 'run commands with verbose flag',
                    0),
        BoolOption ('checksums', 'use checksums instead of timestamps',
                    0),
        BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
        BoolOption ('verbose', 'run commands with verbose flag',
                    0),
        BoolOption ('checksums', 'use checksums instead of timestamps',
                    0),
        BoolOption ('fast', 'use timestamps, implicit cache, prune CPPPATH',
-                   1),
+                   0),
        )
 
 srcdir = Dir ('.').srcnode ().abspath
        )
 
 srcdir = Dir ('.').srcnode ().abspath
@@ -142,19 +175,16 @@ package = packagepython.Package (srcdir)
 version = packagepython.version_tuple_to_str (package.version)
 
 ENV = { 'PATH' : os.environ['PATH'] }
 version = packagepython.version_tuple_to_str (package.version)
 
 ENV = { 'PATH' : os.environ['PATH'] }
-for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH']:
+for key in ['LD_LIBRARY_PATH', 'GUILE_LOAD_PATH', 'PKG_CONFIG_PATH', 'TEXMF']:
        if os.environ.has_key (key):
                ENV[key] = os.environ[key]
 
 env = Environment (
        ENV = ENV,
        if os.environ.has_key (key):
                ENV[key] = os.environ[key]
 
 env = Environment (
        ENV = ENV,
-
-       BASH = '/bin/bash',
+       BYTEORDER = sys.byteorder.upper (),
+       CC = '$GCC',
+       CXX = '$GXX',
        CPPDEFINES = '-DHAVE_CONFIG_H',
        CPPDEFINES = '-DHAVE_CONFIG_H',
-       PERL = '/usr/bin/perl',
-       PYTHON = '/usr/bin/python',
-       SH = '/bin/sh',
-
        MAKEINFO = 'LANG= makeinfo',
        MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
        
        MAKEINFO = 'LANG= makeinfo',
        MF_TO_TABLE_PY = srcdir + '/buildscripts/mf-to-table.py',
        
@@ -167,14 +197,17 @@ env = Environment (
        TOPLEVEL_VERSION = version,
        )
 
        TOPLEVEL_VERSION = version,
        )
 
+Help (usage + opts.GenerateHelpText (env))
+
 # Add all config_vars to opts, so that they will be read and saved
 # together with the other configure options.
 map (lambda x: opts.AddOptions ((x,)), config_vars)
 # Add all config_vars to opts, so that they will be read and saved
 # together with the other configure options.
 map (lambda x: opts.AddOptions ((x,)), config_vars)
-
-Help (usage + opts.GenerateHelpText (env))
-
 opts.Update (env)
 
 opts.Update (env)
 
+for key in config_vars:
+       if os.environ.has_key (key):
+               env[key] = os.environ[key]
+
 if env['fast']:
        # Usability switch (Anthony Roach).
        # See http://www.scons.org/cgi-bin/wiki/GoFastButton
 if env['fast']:
        # Usability switch (Anthony Roach).
        # See http://www.scons.org/cgi-bin/wiki/GoFastButton
@@ -215,6 +248,8 @@ prefix = env['prefix']
 bindir = os.path.join (prefix, 'bin')
 sharedir = os.path.join (prefix, 'share')
 libdir = os.path.join (prefix, 'lib')
 bindir = os.path.join (prefix, 'bin')
 sharedir = os.path.join (prefix, 'share')
 libdir = os.path.join (prefix, 'lib')
+libdir_package = os.path.join (libdir, package.name)
+libdir_package_version = os.path.join (libdir_package, version)
 localedir = os.path.join (sharedir, 'locale')
 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
 sharedir_package = os.path.join (sharedir, package.name)
 localedir = os.path.join (sharedir, 'locale')
 sharedir_doc_package = os.path.join (sharedir, 'doc', package.name)
 sharedir_package = os.path.join (sharedir, package.name)
@@ -234,65 +269,192 @@ def list_sort (lst):
        return sorted
 
 
        return sorted
 
 
+def symlink_tree (target, source, env):
+       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, '/'))
+                       if src.find ('@') > -1:
+                               frm = os.path.join ('../' * depth,
+                                                   string.replace (src, '@',
+                                                                   env['out']))
+                       else:
+                               frm = os.path.join ('../' * depth, src,
+                                                   env['out'])
+               if src[-1] == '/':
+                       frm = os.path.join (frm, os.path.basename (dst))
+               if env['verbose']:
+                       print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
+               os.symlink (frm, os.path.basename (dst))
+       shutil.rmtree (run_prefix)
+       prefix = os.path.join (env['out'], 'usr')
+       map (lambda x: symlink (x[0], os.path.join (prefix,
+                                                   x[1] % {'ver' : version})),
+            # ^# := source dir
+            # @  := out
+            # /$ := add dst file_name
+            (('python',     'lib/lilypond/python'),
+             # ugh
+             ('python',     'share/lilypond/%(ver)s/python'),
+             ('lily/',      'bin/lilypond'),
+             ('scripts/',   'bin/convert-ly'),
+             ('scripts/',   'bin/lilypond-book'),
+             ('scripts/',   'bin/ps2png'),
+             ('mf',         'share/lilypond/%(ver)s/dvips/mf-out'),
+             ('#ps',        'share/lilypond/%(ver)s/dvips/ps'),
+             ('#ps/music-drawing-routines.ps',
+              'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
+             ('mf',         'share/lilypond/%(ver)s/otf'),
+             ('mf',         'share/lilypond/%(ver)s/tfm'),
+             ('tex',        'share/lilypond/%(ver)s/tex/enc'),
+             ('#mf',        'share/lilypond/%(ver)s/fonts/mf'),
+             ('mf',         'share/lilypond/%(ver)s/fonts/map'),
+             ('mf',         'share/lilypond/%(ver)s/fonts/otf'),
+             ('mf',         'share/lilypond/%(ver)s/fonts/tfm'),
+             ('mf',         'share/lilypond/%(ver)s/fonts/type1'),
+             ('#tex',       'share/lilypond/%(ver)s/tex/source'),
+             ('tex',        'share/lilypond/%(ver)s/tex/tex-out'),
+             ('mf',         'share/lilypond/%(ver)s/tex/mf-out'),
+             ('#ly',        'share/lilypond/%(ver)s/ly'),
+             ('#scm',       'share/lilypond/%(ver)s/scm'),
+             ('#scripts',   'share/lilypond/%(ver)s/scripts'),
+             ('#ps',        'share/lilypond/%(ver)s/ps'),
+             ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
+             ('elisp',      'share/lilypond/%(ver)s/elisp')))
+
+       print "FIXME: BARF BARF BARF"
+       os.chdir (absbuild)
+       out = env['out']
+       ver = version
+       prefix = os.path.join (env['out'], 'usr/share/lilypond/%(ver)s/fonts'
+                              % vars ())
+       for ext in ('enc', 'map', 'otf', 'svg', 'tfm', 'pfa'):
+               dir = os.path.join (absbuild, prefix, ext)
+               os.system ('rm -f ' + dir)
+               mkdirs (dir)
+               os.chdir (dir)
+               os.system ('ln -s ../../../../../../../mf/%(out)s/*.%(ext)s .'
+                          % vars ())
+       os.chdir (srcdir)
+
 def configure (target, source, env):
 def configure (target, source, env):
-       vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
+       dre = re.compile ('\n(200[0-9]{5})')
+       vre = re.compile ('.*?\n[^-.0-9]*([0-9][0-9]*\.[0-9]([.0-9]*[0-9])*)',
+                         re.DOTALL)
        def get_version (program):
        def get_version (program):
-               command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
+               command = '(pkg-config --modversion %(program)s || %(program)s --version || %(program)s -V) 2>&1' % vars ()
                pipe = os.popen (command)
                output = pipe.read ()
                if pipe.close ():
                        return None
                pipe = os.popen (command)
                output = pipe.read ()
                if pipe.close ():
                        return None
-               v = re.sub (vre, '\\1', output)
+               splits = re.sub ('^|\s', '\n', output)
+               date_hack = re.sub (dre, '\n0.0.\\1', splits)
+               m = re.match (vre, date_hack)
+               v = m.group (1)
+               if v[-1] == '\n':
+                       v = v[:-1]
                return string.split (v, '.')
 
                return string.split (v, '.')
 
-       def test_program (lst, program, minimal, description, package):
+       def test_version (lst, full_name, minimal, description, package):
+               program = os.path.basename (full_name)
                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'))
                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, '.'):
+                       return 0
+               print string.join (actual, '.')
+               if map (string.atoi, actual) \
+                  < map (string.atoi, string.split (minimal, '.')):
                        lst.append ((description, package, minimal, program,
                                     string.join (actual, '.')))
                        lst.append ((description, package, minimal, program,
                                     string.join (actual, '.')))
+                       return 0
+               return 1
 
 
-       for i in ['bash', 'perl', 'python', 'sh']:
-               sys.stdout.write ('Checking for %s... ' % i)
-               c = WhereIs (i)
-               key = string.upper (i)
-               if c:
-                       env[key] = c
-                       sys.stdout.write (c)
+       def test_program (lst, program, minimal, description, package):
+               key = program.upper ()
+               if key.find ('+-'):
+                       key = re.sub ('\+', 'X', key)
+                       key = re.sub ('-', '_', key)
+               sys.stdout.write ('Checking for %s ... ' % program)
+               if env.has_key (key):
+                       f = env[key]
+                       sys.stdout.write ('(cached) ')
                else:
                else:
-                       sys.stdout.write ('not found: %s (using: %s)' \
-                                         % (c, env[key]))
-                       # Hmm? abort?
-               sys.stdout.write ('\n')
+                       f = WhereIs (program)
+                       env[key] = f
+               if not f:
+                       print 'not found'
+                       lst.append ((description, package, minimal, program,
+                                    'not installed'))
+                       return 0
+               print f
+               return test_version (lst, program, minimal, description, package)
+
+       def test_lib (lst, program, minimal, description, package):
+               # FIXME: test for Debian or RPM (or -foo?) based dists
+               # to guess (or get correct!: apt-cache search?)
+               # package name.
+               #if os.system ('pkg-config --atleast-version=0 freetype2'):
+               # barf
+               if test_version (lst, program, minimal, description,
+                                'lib%(package)s-dev or %(package)s-devel'
+                                % vars ()):
+                       env.ParseConfig ('pkg-config --cflags --libs %(program)s'
+                                        % vars ())
+                       return 1
+               return 0
 
        required = []
 
        required = []
+       test_program (required, 'bash', '2.0', 'Bash', 'bash')
        test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
        test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
        test_program (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
        test_program (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
-       test_program (required, 'python', '2.1', 'Python (www.python.org)', 'python')
        test_program (required, 'guile-config', '1.6', 'GUILE development',
                        'libguile-dev or guile-devel')
        test_program (required, 'guile-config', '1.6', 'GUILE development',
                        'libguile-dev or guile-devel')
-       # Do not use bison 1.50 and 1.75.
-       test_program (required, 'bison', '1.25', 'Bison -- parser generator',
-                       'bison')
-       test_program (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
-
+       test_program (required, 'mf', '0.0', 'Metafont', 'tetex-bin')
+       test_program (required, 'mftrace', '1.1.9',
+                     'mftrace (http://xs4all.nl/~hanwen/mftrace)', 'mftrace')
+       test_program (required, 'potrace', '0.0', 'Potrace', 'potrace')
+       test_program (required, 'python', '2.1', 'Python (www.python.org)',
+                     'python')
+       test_program (required, 'sh', '0.0', 'Bourne shell', 'sh')
 
        optional = []
 
        optional = []
-       test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
-       test_program (optional, 'guile', '1.6', 'GUILE scheme',
-                       'libguile-dev or guile-devel')
-       test_program (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
+       # Do not use bison 1.50 and 1.75.
+       #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
+       test_program (optional, 'bison', '1.25', 'Bison -- parser generator',
+                       'bison')
+       test_program (optional, 'dvips', '0.0', 'Dvips', 'tetex-bin')
+       test_program (optional, 'fontforge', '0.0.20050624', 'FontForge',
+                     'fontforge')
+       test_program (optional, 'flex', '0.0', 'Flex -- lexer generator',
+                     'flex')
+       test_program (optional, 'guile', '1.6', 'GUILE scheme', 'guile')
+       test_program (optional, 'gs', '8.15',
+                     'Ghostscript PostScript interpreter',
+                     'gs or gs-afpl or gs-esp or gs-gpl')
+       test_program (optional, 'mftrace', '1.1.19', 'Metafont tracing Type1',
                        'mftrace')
                        'mftrace')
+       test_program (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
        test_program (optional, 'perl', '4.0',
        test_program (optional, 'perl', '4.0',
-                       'Perl practical efficient readonly language', 'perl')
-       #test_program (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
+                     'Perl practical efficient readonly language', 'perl')
+       #test_program (optional, 'ps2pdf', '0.0', 'Ps2pdf', 'gs')
 
        def CheckYYCurrentBuffer (context):
                context.Message ('Checking for yy_current_buffer... ')
 
        def CheckYYCurrentBuffer (context):
                context.Message ('Checking for yy_current_buffer... ')
@@ -315,24 +477,22 @@ def configure (target, source, env):
        defines = {
           'DIRSEP' : "'%s'" % os.sep,
           'PATHSEP' : "'%s'" % os.pathsep,
        defines = {
           'DIRSEP' : "'%s'" % os.sep,
           'PATHSEP' : "'%s'" % os.pathsep,
-          'TOPLEVEL_VERSION' : '"' + version + '"',
-          'PACKAGE': '"' + package.name + '"',
-          'DATADIR' : '"' + sharedir + '"',
-          'LILYPOND_DATADIR' : '"' + sharedir_package + '"',
-          'LOCAL_LILYPOND_DATADIR' : '"' + sharedir_package_version + '"',
-          'LOCALEDIR' : '"' + localedir + '"',
+          'PACKAGE': '"%s"' % package.name,
+          'DATADIR' : '"%s"' % sharedir,
+          'PACKAGE_DATADIR' : '"%s"' % sharedir_package,
+          'LOCALEDIR' : '"%s"' %localedir,
        }
        conf.env.Append (DEFINES = defines)
 
        command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
        }
        conf.env.Append (DEFINES = defines)
 
        command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
-       PYTHON_INCLUDE = os.popen (command).read ()
+       PYTHON_INCLUDE = os.popen (command).read ()#[:-1]
        if env['fast']:
        if env['fast']:
-               env.Append (CCFLAGS = ['-I%s ' % PYTHON_INCLUDE])
+               env.Append (CCFLAGS = ['-I%s' % PYTHON_INCLUDE])
        else:
        else:
-               env.Append (CPPPATH = PYTHON_INCLUDE)
+               env.Append (CPPPATH = [PYTHON_INCLUDE])
 
 
-       headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'libio.h',
-                  'Python.h')
+       headers = ('assert.h', 'grp.h', 'libio.h', 'pwd.h',
+                  'sys/stat.h', 'utf8/wchar.h', 'wchar.h', 'Python.h')
        for i in headers:
                if conf.CheckCHeader (i):
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
        for i in headers:
                if conf.CheckCHeader (i):
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
@@ -344,8 +504,9 @@ def configure (target, source, env):
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
                        conf.env['DEFINES'][key] = 1
 
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
                        conf.env['DEFINES'][key] = 1
 
-       functions = ('fopencookie', 'funopen',
-                    'gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
+       functions = ('chroot', 'fopencookie', 'funopen',
+                    'gettext', 'isinf',
+                    'mbrtowc', 'memmem', 'snprintf', 'vsnprintf', 'wcrtomb')
        for i in functions:
                if 0 or conf.CheckFunc (i):
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
        for i in functions:
                if 0 or conf.CheckFunc (i):
                        key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
@@ -357,18 +518,6 @@ def configure (target, source, env):
        if conf.CheckLib ('dl'):
                pass
 
        if conf.CheckLib ('dl'):
                pass
 
-       if conf.CheckLib ('kpathsea'):
-               conf.env['DEFINES']['KPATHSEA'] = 1
-
-       # huh? 
-       if conf.CheckLib ('kpathsea', 'kpse_find_file'):
-               conf.env['DEFINES']['HAVE_KPSE_FIND_FILE'] = '1'
-       if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
-               conf.env['DEFINES']['HAVE_KPSE_FIND_TFM'] = '1'
-
-       # FIXME fc3 - move to kpath-guile/SConscript?
-       conf.env['DEFINES']['HAVE_LIBKPATHSEA_SO'] = '1'
-
        if env['fast']:
                cpppath = []
                if env.has_key ('CPPPATH'):
        if env['fast']:
                cpppath = []
                if env.has_key ('CPPPATH'):
@@ -378,29 +527,27 @@ def configure (target, source, env):
        #this could happen after flower...
        env.ParseConfig ('guile-config compile')
 
        #this could happen after flower...
        env.ParseConfig ('guile-config compile')
 
-       ## FIXME: pkg-test to required/optional
-       if os.system ('pkg-config --atleast-version=1.6.0 pango'):
-               barf
-       env.ParseConfig ('pkg-config --cflags --libs pango')
-       conf.env['DEFINES']['HAVE_PANGO16'] = '1'
-       
-       if os.system ('pkg-config --atleast-version=1.6.0 pangoft2'):
-               barf
-       env.ParseConfig ('pkg-config --cflags --libs pangoft2')
-       conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
+       test_program (required, 'pkg-config', '0.9.0',
+                     'pkg-config library compile manager', 'pkg-config')
+       if test_lib (required, 'freetype2', '0.0',
+                    'Development files for FreeType 2 font engine',
+                    'freetype6'):
+               conf.env['DEFINES']['HAVE_FREETYPE2'] = '1'
+               
+       if test_lib (required, 'pangoft2', '1.6.0',
+                    'Development files for pango, with FreeType2',
+                    'pango1.0'):
+               conf.env['DEFINES']['HAVE_PANGO_FT2'] = '1'
+
+       if test_lib (optional, 'fontconfig', '2.2.0',
+                    'Development files for fontconfig', 'fontconfig1'):
+               conf.env['DEFINES']['HAVE_FONTCONFIG'] = '1'
        
        #this could happen only for compiling pango-*
        if env['gui']:
        
        #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'):
-                       conf.env['DEFINES']['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
-
-               if conf.CheckLib ('pango-1.0',
-                                 'pango_fc_font_map_add_decoder_find_func'):
-                       conf.env['DEFINES']['HAVE_PANGO_CVS'] = '1'
-                       conf.env['DEFINES']['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
-
+               test_lib (required, 'gtk+-2.0', '2.4.0',
+                         'Development files for GTK+', 'gtk2.0')
+                       
        if env['fast']:
                # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
                # <system-dir>] speeds up SCons
        if env['fast']:
                # Using CCFLAGS = -I<system-dir> rather than CPPPATH = [
                # <system-dir>] speeds up SCons
@@ -469,10 +616,22 @@ def save_config_cache (env):
                sys.stdout.write ('\n')
                sys.stdout.write ('LilyPond configured')
                sys.stdout.write ('\n')
                sys.stdout.write ('\n')
                sys.stdout.write ('LilyPond configured')
                sys.stdout.write ('\n')
-               sys.stdout.write ('now run')
+               sys.stdout.write ('Now run')
                sys.stdout.write ('\n')
                sys.stdout.write ('    scons [TARGET|DIR]...')
                sys.stdout.write ('\n')
                sys.stdout.write ('\n')
                sys.stdout.write ('    scons [TARGET|DIR]...')
                sys.stdout.write ('\n')
+               sys.stdout.write ('\n')
+               sys.stdout.write ('Examples:')
+               sys.stdout.write ('\n')
+               sys.stdout.write ('    scons lily    # build lilypond')
+               sys.stdout.write ('\n')
+               sys.stdout.write ('    scons all     # build everything')
+               sys.stdout.write ('\n')
+               sys.stdout.write ('    scons doc     # build documentation')
+               sys.stdout.write ('\n')
+               ## TODO
+               ## sys.stdout.write ('    scons prefix=/usr DESTDIR=/tmp/pkg all install')
+               ## sys.stdout.write ('\n')
                Exit (0)
        elif not env['checksums']:
                # When using timestams, config.hh is NEW.  The next
                Exit (0)
        elif not env['checksums']:
                # When using timestams, config.hh is NEW.  The next
@@ -485,9 +644,6 @@ def save_config_cache (env):
                s = os.system (command)
                Exit (s)
 
                s = os.system (command)
                Exit (s)
 
-
-if os.path.exists (config_cache) and 'config' in COMMAND_LINE_TARGETS:
-       os.unlink (config_cache)
 # WTF?
 # scons: *** Calling Configure from Builders is not supported.
 # env.Command (config_cache, None, configure)
 # WTF?
 # scons: *** Calling Configure from Builders is not supported.
 # env.Command (config_cache, None, configure)
@@ -507,18 +663,23 @@ SConscript ('buildscripts/builder.py')
 env.PrependENVPath ('PATH',
                    os.path.join (env['absbuild'], env['out'], 'usr/bin'))
 
 env.PrependENVPath ('PATH',
                    os.path.join (env['absbuild'], env['out'], 'usr/bin'))
 
-if os.environ.has_key ('TEXMF'):
-       env.Append (ENV = {'TEXMF' : os.environ['TEXMF']})
+LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond/', version)
+
+if not os.path.exists (LILYPONDPREFIX):
+       os.makedirs (LILYPONDPREFIX)
+
+env.Command (LILYPONDPREFIX, ['#/SConstruct', '#/VERSION'], symlink_tree)
+env.Depends ('lily', LILYPONDPREFIX)
+
 env.Append (ENV = {
 env.Append (ENV = {
-       'TEXMF' : '{$LILYPONDPREFIX,' \
+       'LILYPONDPREFIX' : LILYPONDPREFIX,
+       'TEXMF' : '{$LILYPONDPREFIX,'
        + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
        + os.popen ('kpsexpand \$TEXMF').read ()[:-1] + '}',
-       'LILYPONDPREFIX' : os.path.join (run_prefix, 'share/lilypond'),
        })
 
 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
        })
 
 BUILD_ABC2LY = '${set__x}$PYTHON $srcdir/scripts/abc2ly.py'
-BUILD_LILYPOND = '${set__x}$PYTHON $srcdir/scripts/lilypond.py${__verbose}'
-BUILD_LILYPOND_BIN = '$absbuild/$out/lilypond-bin ${__verbose}'
-BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py --verbose'
+BUILD_LILYPOND = '$absbuild/lily/$out/lilypond ${__verbose}'
+BUILD_LILYPOND_BOOK = '$PYTHON $srcdir/scripts/lilypond-book.py ${__verbose}'
 
 
 # post-option environment-update
 
 
 # post-option environment-update
@@ -532,33 +693,40 @@ env.Append (
        sharedir_package = sharedir_package,
        sharedir_doc_package = sharedir_doc_package,
        sharedir_package_version = sharedir_package_version,
        sharedir_package = sharedir_package,
        sharedir_doc_package = sharedir_doc_package,
        sharedir_package_version = sharedir_package_version,
+       libdir_package = libdir_package,
+       libdir_package_version = libdir_package_version,
 
 
+       # global build verbosity switch
+       __verbose = ' --verbose',
+       
        LILYPOND = BUILD_LILYPOND,
        ABC2LY = BUILD_ABC2LY,
        LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
        LILYPOND_BOOK_FORMAT = 'texi-html',
        MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
        LILYPOND = BUILD_LILYPOND,
        ABC2LY = BUILD_ABC2LY,
        LILYPOND_BOOK = BUILD_LILYPOND_BOOK,
        LILYPOND_BOOK_FORMAT = 'texi-html',
        MAKEINFO_FLAGS = '--css-include=$srcdir/Documentation/texinfo.css',
-
+       # PYTHONPATH = ['$absbuild/python/$out'],
        TEXI2DVI_PAPERSIZE = '@afourpaper',
        TEXI2DVI_PAPERSIZE = '@afourpaper',
-       TEXI2DVI_FLAGS = [ '-t $TEXI2DVI_PAPERSIZE'],
+       TEXI2DVI_FLAGS = [ '-t$TEXI2DVI_PAPERSIZE'],
        DVIPS_PAPERSIZE = 'a4',
        DVIPS_PAPERSIZE = 'a4',
-       DVIPS_FLAGS = ['-t $DVIPS_PAPERSIZE',
+       DVIPS_FLAGS = ['-t$DVIPS_PAPERSIZE',
                       '-u+lilypond.map',
                       '-u+ec-mftrace.map'],
        PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
        )
 
                       '-u+lilypond.map',
                       '-u+ec-mftrace.map'],
        PSPDF_FLAGS = ['-sPAPERSIZE=$DVIPS_PAPERSIZE'],
        )
 
+env.Append (CCFLAGS = ['-pipe', '-Wno-pmf-conversions'])
 if env['debugging']:
 if env['debugging']:
-       env.Append (CCFLAGS = ['-g', '-pipe'])
+       env.Append (CCFLAGS = ['-g'])
 if env['optimising']:
        env.Append (CCFLAGS = '-O2')
 if env['optimising']:
        env.Append (CCFLAGS = '-O2')
-       env.Append (CXXFLAGS = ['-DSTRING_UTILS_INLINED'])
 if env['warnings']:
        env.Append (CCFLAGS = ['-W', '-Wall'])
        env.Append (CXXFLAGS = ['-Wconversion'])
 
 # ugr,huh?
 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
 if env['warnings']:
        env.Append (CCFLAGS = ['-W', '-Wall'])
        env.Append (CXXFLAGS = ['-Wconversion'])
 
 # ugr,huh?
 env.Append (LINKFLAGS = ['-Wl,--export-dynamic'])
+# FIXME: ParseConfig ignores -L flag?
+env.Append (LINKFLAGS = ['-L/usr/X11R6/lib'])
 
 if env['verbose']:
        env['__verbose'] = ' --verbose'
 
 if env['verbose']:
        env['__verbose'] = ' --verbose'
@@ -595,15 +763,27 @@ if 'realclean' in COMMAND_LINE_TARGETS:
                os.unlink (config_cache)
        Exit (s)
 
                os.unlink (config_cache)
        Exit (s)
 
+def symlink_tree ():
+       print "BOE"
+       raise urg
+       
 # Declare SConscript phonies 
 env.Alias ('minimal', config_cache)
 # Declare SConscript phonies 
 env.Alias ('minimal', config_cache)
-env.Alias ('mf-essential', config_cache)
 
 
-env.Alias ('minimal', ['lily', 'mf-essential'])
-env.Alias ('all', ['minimal', 'mf', '.'])
+if 0:
+       env.Alias ('mf-essential', config_cache)
+       env.Alias ('minimal', ['python', 'lily', 'mf-essential'])
+       env.Alias ('all', ['minimal', 'mf', '.'])
+
+else:
+       env.Alias ('minimal', ['python', 'lily', 'mf'])
+       env.Alias ('all', ['minimal', '.'])
+
+
 # Do we want the doc/web separation?
 env.Alias ('doc',
 # Do we want the doc/web separation?
 env.Alias ('doc',
-          ['Documentation',
+          ['minimal',
+           'Documentation',
            'Documentation/user',
            'Documentation/topdocs',
            'Documentation/bibliography',
            'Documentation/user',
            'Documentation/topdocs',
            'Documentation/bibliography',
@@ -623,14 +803,13 @@ env.Command (version_hh, '#/VERSION',
 # post-config environment update
 env.Append (
        run_prefix = run_prefix,
 # post-config environment update
 env.Append (
        run_prefix = run_prefix,
-       LILYPONDPREFIX = os.path.join (run_prefix, 'share/lilypond'),
+       LILYPONDPREFIX = LILYPONDPREFIX,
 
        # FIXME: move to lily/SConscript?
 
        # FIXME: move to lily/SConscript?
-       LIBPATH = [os.path.join (absbuild, 'flower', env['out']),
-                  os.path.join (absbuild, 'kpath-guile', env['out']),
-                  os.path.join (absbuild, 'ttftool', env['out']),],
+       LIBPATH = [os.path.join (absbuild, 'flower', env['out'])],
        CPPPATH = [outdir, ],
        CPPPATH = [outdir, ],
-       LILYPOND_PATH = ['.', '$srcdir/input',
+       LILYPOND_PATH = ['.',
+                        '$srcdir/input',
                         '$srcdir/input/regression',
                         '$srcdir/input/test',
                         '$srcdir/input/tutorial',
                         '$srcdir/input/regression',
                         '$srcdir/input/test',
                         '$srcdir/input/tutorial',
@@ -645,77 +824,6 @@ env.Append (
                         '$absbuild/Documentation/user/$out'],
        )
 
                         '$absbuild/Documentation/user/$out'],
        )
 
-def symlink_tree (target, source, env):
-       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, '/'))
-                       if src.find ('@') > -1:
-                               frm = os.path.join ('../' * depth,
-                                                   string.replace (src, '@',
-                                                                   env['out']))
-                       else:
-                               frm = os.path.join ('../' * depth, src,
-                                                   env['out'])
-               if src[-1] == '/':
-                       frm = os.path.join (frm, os.path.basename (dst))
-               if env['verbose']:
-                       print 'ln -s %s -> %s' % (frm, os.path.basename (dst))
-               os.symlink (frm, os.path.basename (dst))
-       shutil.rmtree (run_prefix)
-       prefix = os.path.join (env['out'], 'usr')
-       map (lambda x: symlink (x[0], os.path.join (prefix,
-                                                   x[1] % {'ver' : version})),
-            # ^# := source dir
-            # @  := out
-            # /$ := add dst file_name
-            (('python',     'lib/lilypond/python'),
-             ('lily/',      'bin/lilypond'),
-             ('scripts/',   'bin/convert-ly'),
-             ('scripts/',   'bin/lilypond-book'),
-             ('scripts/',   'bin/ps2png'),
-             ('mf',         'share/lilypond/%(ver)s/dvips/mf-out'),
-             ('#ps',        'share/lilypond/%(ver)s/dvips/ps'),
-             ('#ps',        'share/lilypond/%(ver)s/tex/music-drawing-routines.ps'),
-             ('mf',         'share/lilypond/%(ver)s/otf'),
-             ('mf',         'share/lilypond/%(ver)s/tfm'),
-             ('tex',        'share/lilypond/%(ver)s/tex/enc'),
-             ('#mf',        'share/lilypond/%(ver)s/fonts/mf'),
-             ('mf',         'share/lilypond/%(ver)s/fonts/map'),
-             ('mf',         'share/lilypond/%(ver)s/fonts/otf'),
-             ('mf',         'share/lilypond/%(ver)s/fonts/tfm'),
-             ('mf',         'share/lilypond/%(ver)s/fonts/type1'),
-             ('#tex',       'share/lilypond/%(ver)s/tex/source'),
-             ('tex',        'share/lilypond/%(ver)s/tex/tex-out'),
-             ('mf',         'share/lilypond/%(ver)s/tex/mf-out'),
-             ('#ly',        'share/lilypond/%(ver)s/ly'),
-             ('#scm',       'share/lilypond/%(ver)s/scm'),
-             ('#scripts',   'share/lilypond/%(ver)s/scripts'),
-             ('#ps',        'share/lilypond/%(ver)s/ps'),
-             ('po/@/nl.mo', 'share/locale/nl/LC_MESSAGES/lilypond.mo'),
-             ('elisp',      'share/lilypond/%(ver)s/elisp')))
-       os.chdir (srcdir)
-
-if env['debugging']:
-       stamp = os.path.join (run_prefix, 'stamp')
-       env.Command (stamp, 'SConstruct', [symlink_tree, 'touch $TARGET'])
-       env.Depends ('lily', stamp)
-       
 #### dist, tar
 def plus (a, b):
        a + b
 #### dist, tar
 def plus (a, b):
        a + b
@@ -727,18 +835,20 @@ def cvs_entry_is_file (line):
        return line[0] == '/' and line[-2] == '/'
 
 def cvs_dirs (dir):
        return line[0] == '/' and line[-2] == '/'
 
 def cvs_dirs (dir):
-       ENTRIES = os.path.join (dir, 'CVS/Entries')
-       if not os.path.exists (ENTRIES):
+       entries = os.path.join (dir, 'CVS/Entries')
+       if not os.path.exists (entries):
                return []
                return []
-       entries = open (ENTRIES).readlines ()
+       entries = open (entries).readlines ()
        dir_entries = filter (cvs_entry_is_dir, entries)
        dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
                    dir_entries)
        return dirs + map (cvs_dirs, dirs)
 
 def cvs_files (dir):
        dir_entries = filter (cvs_entry_is_dir, entries)
        dirs = map (lambda x: os.path.join (dir, x[2:x[2:].index ('/')+3]),
                    dir_entries)
        return dirs + map (cvs_dirs, dirs)
 
 def cvs_files (dir):
-       ENTRIES = os.path.join (dir, 'CVS/Entries')
-       entries = open (ENTRIES).readlines ()
+       entries = os.path.join (dir, 'CVS/Entries')
+       if not os.path.exists (entries):
+               return []
+       entries = open (entries).readlines ()
        file_entries = filter (cvs_entry_is_file, entries)
        files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
        return map (lambda x: os.path.join (dir, x), files)
        file_entries = filter (cvs_entry_is_file, entries)
        files = map (lambda x: x[1:x[1:].index ('/')+1], file_entries)
        return map (lambda x: os.path.join (dir, x), files)
@@ -752,22 +862,31 @@ def flatten (tree, lst):
                                lst.append (i)
        return lst
 
                                lst.append (i)
        return lst
 
+if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
+       subdirs = flatten (cvs_dirs ('.'), [])
+else:
+       # ugh
+       command = 'cd %(srcdir)s \
+       && find . -name SConscript | sed s@/SConscript@@' % vars ()
+       subdirs = string.split (os.popen (command).read ())
+
 if env['fast']\
    and 'all' not in COMMAND_LINE_TARGETS\
    and 'doc' not in COMMAND_LINE_TARGETS\
    and 'web' not in COMMAND_LINE_TARGETS\
    and 'install' not in COMMAND_LINE_TARGETS\
    and 'clean' not in COMMAND_LINE_TARGETS:
 if env['fast']\
    and 'all' not in COMMAND_LINE_TARGETS\
    and 'doc' not in COMMAND_LINE_TARGETS\
    and 'web' not in COMMAND_LINE_TARGETS\
    and 'install' not in COMMAND_LINE_TARGETS\
    and 'clean' not in COMMAND_LINE_TARGETS:
-       subdirs = ['lily', 'lily/include',
-                  'flower', 'flower/include',
-                  'kpath-guile',
-                  'ttftool',
+       subdirs = [ 'python',
+                   'lily',
+                  'flower',
                   'mf',
                   ]
                   'mf',
                   ]
+
+if os.path.isdir ('%(srcdir)s/CVS' % vars ()):
+       src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
 else:
 else:
-       subdirs = flatten (cvs_dirs ('.'), [])
+       src_files = ['foobar']
 
 
-src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
 txt_files = map (lambda x: x + '.txt', readme_files)
 
 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
 txt_files = map (lambda x: x + '.txt', readme_files)
 
@@ -810,14 +929,16 @@ if not env['fast']:
        web_ball = web_base + '.tar.gz'
        env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
        web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
        web_ball = web_base + '.tar.gz'
        env['footify'] = 'MAILADDRESS=bug-lilypond@gnu.org $PYTHON stepmake/bin/add-html-footer.py --name=lilypond --version=$TOPLEVEL_VERSION'
        web_ext = ['.html', '.ly', '.midi', '.pdf', '.png', '.ps.gz', '.txt',]
-       web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"')
+       web_path = '-path "*/$out/*"' + string.join (web_ext, ' -or -path "*/$out/*"') + '-or -type l'
        env['web_path'] = web_path
        web_list = os.path.join (outdir, 'weblist')
        # compatible make heritits
        # fixme: generate in $outdir is cwd/builddir
        env.Command (web_list,
        env['web_path'] = web_path
        web_list = os.path.join (outdir, 'weblist')
        # compatible make heritits
        # fixme: generate in $outdir is cwd/builddir
        env.Command (web_list,
-                    ## this is correct, but takes > 5min if you have a peder :-)
-                    ##'doc',
+                    ## Adding 'doc' dependency is correct, but takes
+                    ## > 5min extra if you have a peder :-)
+                    #'doc',
+                    
                     '#/VERSION',
                     ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
                      'cd $absbuild && $footify $$(find . -name "*.html" -print)',
                     '#/VERSION',
                     ['$PYTHON buildscripts/mutopia-index.py -o examples.html ./',
                      'cd $absbuild && $footify $$(find . -name "*.html" -print)',