From 9c7c0bf95c7901ad6be772efd9d32dd7d1358bd8 Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Sun, 5 Aug 2012 19:07:48 +0000
Subject: Do everything in the top level wscript file and remove wscript
 symlinks from extensions.

---
 doc/reference.doxygen.in                      |  46 ++---
 ext.wscript                                   |  98 -----------
 lv2/lv2plug.in/ns/ext/atom/wscript            |   1 -
 lv2/lv2plug.in/ns/ext/buf-size/wscript        |   1 -
 lv2/lv2plug.in/ns/ext/data-access/wscript     |   1 -
 lv2/lv2plug.in/ns/ext/dynmanifest/wscript     |   1 -
 lv2/lv2plug.in/ns/ext/event/wscript           |   1 -
 lv2/lv2plug.in/ns/ext/instance-access/wscript |   1 -
 lv2/lv2plug.in/ns/ext/log/wscript             |   1 -
 lv2/lv2plug.in/ns/ext/midi/wscript            |   1 -
 lv2/lv2plug.in/ns/ext/morph/wscript           |   1 -
 lv2/lv2plug.in/ns/ext/parameters/wscript      |   1 -
 lv2/lv2plug.in/ns/ext/patch/wscript           |   1 -
 lv2/lv2plug.in/ns/ext/port-groups/wscript     |   1 -
 lv2/lv2plug.in/ns/ext/port-props/wscript      |   1 -
 lv2/lv2plug.in/ns/ext/presets/wscript         |   1 -
 lv2/lv2plug.in/ns/ext/resize-port/wscript     |   1 -
 lv2/lv2plug.in/ns/ext/state/wscript           |   1 -
 lv2/lv2plug.in/ns/ext/time/wscript            |   1 -
 lv2/lv2plug.in/ns/ext/uri-map/wscript         |   1 -
 lv2/lv2plug.in/ns/ext/urid/wscript            |   1 -
 lv2/lv2plug.in/ns/ext/worker/wscript          |   1 -
 lv2/lv2plug.in/ns/extensions/ui/wscript       |   1 -
 lv2/lv2plug.in/ns/extensions/units/wscript    |   1 -
 lv2/lv2plug.in/ns/meta/wscript                |   1 -
 wscript                                       | 238 ++++++++++++++++----------
 26 files changed, 172 insertions(+), 233 deletions(-)
 delete mode 100644 ext.wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/atom/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/buf-size/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/data-access/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/dynmanifest/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/event/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/instance-access/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/log/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/midi/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/morph/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/parameters/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/patch/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/port-groups/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/port-props/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/presets/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/resize-port/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/state/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/time/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/uri-map/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/urid/wscript
 delete mode 120000 lv2/lv2plug.in/ns/ext/worker/wscript
 delete mode 120000 lv2/lv2plug.in/ns/extensions/ui/wscript
 delete mode 120000 lv2/lv2plug.in/ns/extensions/units/wscript
 delete mode 120000 lv2/lv2plug.in/ns/meta/wscript

diff --git a/doc/reference.doxygen.in b/doc/reference.doxygen.in
index fb0be10..d0230a1 100644
--- a/doc/reference.doxygen.in
+++ b/doc/reference.doxygen.in
@@ -557,7 +557,7 @@ SHOW_USED_FILES        = YES
 # This will remove the Files entry from the Quick Index and from the
 # Folder Tree View (if specified). The default is YES.
 
-SHOW_FILES             = YES
+SHOW_FILES             = NO
 
 # Set the SHOW_NAMESPACES tag to NO to disable the generation of the
 # Namespaces page.
@@ -656,27 +656,27 @@ WARN_LOGFILE           =
 # with spaces.
 
 INPUT                  = @LV2_SRCDIR@/doc/mainpage.dox \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/atom/atom.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/atom/forge.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/atom/util.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/buf-size/buf-size.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/data-access/data-access.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/event/event-helpers.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/event/event.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/instance-access/instance-access.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/log/log.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/morph/morph.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/patch/patch.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/port-groups/port-groups.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/resize-port/resize-port.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/state/state.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/time/time.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/uri-map/uri-map.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/urid/urid.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/ext/worker/worker.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/extensions/ui/ui.h \
-                         @LV2_SRCDIR@/lv2/lv2plug.in/ns/lv2core/lv2.h
+                         lv2/lv2plug.in/ns/ext/atom/atom.h \
+                         lv2/lv2plug.in/ns/ext/atom/forge.h \
+                         lv2/lv2plug.in/ns/ext/atom/util.h \
+                         lv2/lv2plug.in/ns/ext/buf-size/buf-size.h \
+                         lv2/lv2plug.in/ns/ext/data-access/data-access.h \
+                         lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h \
+                         lv2/lv2plug.in/ns/ext/event/event-helpers.h \
+                         lv2/lv2plug.in/ns/ext/event/event.h \
+                         lv2/lv2plug.in/ns/ext/instance-access/instance-access.h \
+                         lv2/lv2plug.in/ns/ext/log/log.h \
+                         lv2/lv2plug.in/ns/ext/morph/morph.h \
+                         lv2/lv2plug.in/ns/ext/patch/patch.h \
+                         lv2/lv2plug.in/ns/ext/port-groups/port-groups.h \
+                         lv2/lv2plug.in/ns/ext/resize-port/resize-port.h \
+                         lv2/lv2plug.in/ns/ext/state/state.h \
+                         lv2/lv2plug.in/ns/ext/time/time.h \
+                         lv2/lv2plug.in/ns/ext/uri-map/uri-map.h \
+                         lv2/lv2plug.in/ns/ext/urid/urid.h \
+                         lv2/lv2plug.in/ns/ext/worker/worker.h \
+                         lv2/lv2plug.in/ns/extensions/ui/ui.h \
+                         lv2/lv2plug.in/ns/lv2core/lv2.h
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -848,7 +848,7 @@ USE_HTAGS              = NO
 # will generate a verbatim copy of the header file for each class for
 # which an include is specified. Set to NO to disable this.
 
-VERBATIM_HEADERS       = YES
+VERBATIM_HEADERS       = NO
 
 #---------------------------------------------------------------------------
 # configuration options related to the alphabetical class index
diff --git a/ext.wscript b/ext.wscript
deleted file mode 100644
index 197f82e..0000000
--- a/ext.wscript
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-import glob
-import os
-import shutil
-
-from waflib.extras import autowaf as autowaf
-
-# A rule for making a link in the build directory to a source file
-def link(task):
-    if hasattr(os, 'symlink'):
-        func = os.symlink
-    else:
-        func = shutil.copy  # Symlinks unavailable, make a copy
-
-    try:
-        os.remove(task.outputs[0].abspath())  # Remove old target
-    except:
-        pass  # No old target, whatever
-
-    func(task.inputs[0].abspath(), task.outputs[0].abspath())
-
-def configure(conf):
-    pass
-
-def options(opt):
-    opt.load('compiler_c')
-    autowaf.set_options(opt)
-    opt.add_option('--test', action='store_true', default=False, dest='build_tests',
-                   help="Build unit tests")
-    opt.add_option('--copy-headers', action='store_true', default=False,
-                   dest='copy_headers',
-                   help='Copy headers instead of linking to bundle')
-
-def build(bld):
-    path        = bld.path.srcpath()[len('lv2/'):]
-    name        = os.path.basename(path)
-    bundle_dir  = os.path.join(bld.env['LV2DIR'], name + '.lv2')
-    include_dir = os.path.join(bld.env['INCLUDEDIR'], 'lv2', path)
-
-    # Copy headers to URI-style include paths in build directory
-    for i in bld.path.ant_glob('*.h'):
-        bld(rule   = link,
-            name   = 'link',
-            cwd    = 'build/lv2/%s' % path,
-            source = '%s' % i,
-            target = 'lv2/%s/%s' % (path, i))
-
-    if bld.env['BUILD_TESTS'] and bld.path.find_node('%s-test.c' % name):
-        test_lib    = []
-        test_cflags = ['']
-        if bld.is_defined('HAVE_GCOV'):
-            test_lib    += ['gcov']
-            test_cflags += ['-fprofile-arcs', '-ftest-coverage']
-
-        # Unit test program
-        bld(features     = 'c cprogram',
-            source       = '%s-test.c' % name,
-            lib          = test_lib,
-            target       = '%s-test' % name,
-            install_path = '',
-            cflags       = test_cflags)
-            
-    # Install bundle
-    bld.install_files(bundle_dir,
-                      bld.path.ant_glob('?*.*', excl='*.in'))
-
-    # Install URI-like includes
-    if bld.path.ant_glob('*.h'):
-        if bld.env['COPY_HEADERS']:
-            bld.install_files(include_dir, bld.path.ant_glob('*.h'))
-        else:
-            bld.symlink_as(include_dir,
-                           os.path.relpath(bundle_dir,
-                                           os.path.dirname(include_dir)))
-
-def test(ctx):
-    name = os.path.basename(ctx.path.srcpath()[len('lv2/'):])
-    autowaf.pre_test(ctx, name, dirs=['.'])
-    os.environ['PATH'] = '.' + os.pathsep + os.getenv('PATH')
-    autowaf.run_tests(ctx, name, ['%s-test' % name], dirs=['.'])
-    autowaf.post_test(ctx, name, dirs=['.'])
-
-def news(ctx):
-    path = ctx.path.abspath()
-    autowaf.write_news(os.path.basename(path),
-                       glob.glob(os.path.join(path, '*.ttl')),
-                       os.path.join(path, 'NEWS'))
-
-def pre_dist(ctx):
-    # Write NEWS file in source directory
-    news(ctx)
-
-def post_dist(ctx):
-    # Delete generated NEWS file from source directory
-    try:
-        os.remove(os.path.join(ctx.path.abspath(), 'NEWS'))
-    except:
-        pass
diff --git a/lv2/lv2plug.in/ns/ext/atom/wscript b/lv2/lv2plug.in/ns/ext/atom/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/atom/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/buf-size/wscript b/lv2/lv2plug.in/ns/ext/buf-size/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/buf-size/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/data-access/wscript b/lv2/lv2plug.in/ns/ext/data-access/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/data-access/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/dynmanifest/wscript b/lv2/lv2plug.in/ns/ext/dynmanifest/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/dynmanifest/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/event/wscript b/lv2/lv2plug.in/ns/ext/event/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/event/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/instance-access/wscript b/lv2/lv2plug.in/ns/ext/instance-access/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/instance-access/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/log/wscript b/lv2/lv2plug.in/ns/ext/log/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/log/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/midi/wscript b/lv2/lv2plug.in/ns/ext/midi/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/midi/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/morph/wscript b/lv2/lv2plug.in/ns/ext/morph/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/morph/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/parameters/wscript b/lv2/lv2plug.in/ns/ext/parameters/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/parameters/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/patch/wscript b/lv2/lv2plug.in/ns/ext/patch/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/patch/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/port-groups/wscript b/lv2/lv2plug.in/ns/ext/port-groups/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/port-groups/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/port-props/wscript b/lv2/lv2plug.in/ns/ext/port-props/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/port-props/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/presets/wscript b/lv2/lv2plug.in/ns/ext/presets/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/presets/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/resize-port/wscript b/lv2/lv2plug.in/ns/ext/resize-port/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/resize-port/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/state/wscript b/lv2/lv2plug.in/ns/ext/state/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/state/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/time/wscript b/lv2/lv2plug.in/ns/ext/time/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/time/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/uri-map/wscript b/lv2/lv2plug.in/ns/ext/uri-map/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/uri-map/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/urid/wscript b/lv2/lv2plug.in/ns/ext/urid/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/urid/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/ext/worker/wscript b/lv2/lv2plug.in/ns/ext/worker/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/ext/worker/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/extensions/ui/wscript b/lv2/lv2plug.in/ns/extensions/ui/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/extensions/ui/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/extensions/units/wscript b/lv2/lv2plug.in/ns/extensions/units/wscript
deleted file mode 120000
index 7e2c01b..0000000
--- a/lv2/lv2plug.in/ns/extensions/units/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../ext.wscript
\ No newline at end of file
diff --git a/lv2/lv2plug.in/ns/meta/wscript b/lv2/lv2plug.in/ns/meta/wscript
deleted file mode 120000
index ec20a77..0000000
--- a/lv2/lv2plug.in/ns/meta/wscript
+++ /dev/null
@@ -1 +0,0 @@
-../../../../ext.wscript
\ No newline at end of file
diff --git a/wscript b/wscript
index 97708f8..6ed794a 100644
--- a/wscript
+++ b/wscript
@@ -31,18 +31,8 @@ def options(opt):
     opt.add_option('--copy-headers', action='store_true', default=False,
                    dest='copy_headers',
                    help='Copy headers instead of linking to bundle')
-    for i in ['lv2/lv2plug.in/ns/lv2core']:
-        opt.recurse(i)
-
-def get_subdirs(with_plugins=True):
-    subdirs = ['lv2/lv2plug.in/ns/lv2core/',
-               'lv2/lv2plug.in/ns/meta/']
-    subdirs += glob.glob('lv2/lv2plug.in/ns/ext/*/')
-    subdirs += glob.glob('lv2/lv2plug.in/ns/extensions/*/')
-    if with_plugins:
-        subdirs += glob.glob('plugins/*/')
-    return subdirs
-    
+    opt.recurse('lv2/lv2plug.in/ns/lv2core')
+
 def configure(conf):
     try:
         conf.load('compiler_c')
@@ -52,7 +42,7 @@ def configure(conf):
         Options.options.no_plugins = True
 
     autowaf.configure(conf)
-    autowaf.set_recursive()
+    conf.recurse('lv2/lv2plug.in/ns/lv2core')
 
     if conf.env['MSVC_COMPILER']:
         conf.env.append_unique('CFLAGS', ['-TP', '-MD'])
@@ -71,26 +61,18 @@ def configure(conf):
     if conf.env['BUILD_TESTS'] and not conf.is_defined('HAVE_GCOV'):
         conf.check_cc(lib='gcov', define_name='HAVE_GCOV', mandatory=False)
 
-    subdirs = get_subdirs(conf.env['BUILD_PLUGINS'])
-
-    for i in subdirs:
-        try:
-            conf.recurse(i)
-        except:
-            Logs.warn('Configuration failed, %s will not be built\n' % i)
-            subdirs.remove(i)
-
-    conf.env['LV2_SUBDIRS'] = subdirs
+    if conf.env['BUILD_PLUGINS']:
+        for i in conf.path.ant_glob('plugins/*', dir=True):
+            try:
+                conf.recurse(i)
+            except:
+                Logs.warn('Configuration failed, %s will not be built\n' % i)
 
     autowaf.configure(conf)
     autowaf.display_header('LV2 Configuration')
     autowaf.display_msg(conf, 'Bundle directory', conf.env['LV2DIR'])
     autowaf.display_msg(conf, 'Version', VERSION)
 
-# Rule for copying a file to the build directory
-def copy(task):
-    shutil.copy(task.inputs[0].abspath(), task.outputs[0].abspath())
-
 def chop_lv2_prefix(s):
     if s.startswith('lv2/lv2plug.in/'):
         return s[len('lv2/lv2plug.in/'):]
@@ -235,9 +217,74 @@ def build_index(task):
                { '@ROWS@': ''.join(rows),
                  '@TIME@': datetime.datetime.utcnow().strftime('%F %H:%M UTC') })
 
+# Task for making a link in the build directory to a source file
+def link(task):
+    if hasattr(os, 'symlink'):
+        func = os.symlink
+    else:
+        func = shutil.copy  # Symlinks unavailable, make a copy
+
+    try:
+        os.remove(task.outputs[0].abspath())  # Remove old target
+    except:
+        pass  # No old target, whatever
+
+    func(task.inputs[0].abspath(), task.outputs[0].abspath())
+
+def build_ext(bld, path):
+    name        = os.path.basename(path)
+    bundle_dir  = os.path.join(bld.env['LV2DIR'], name + '.lv2')
+    include_dir = os.path.join(bld.env['INCLUDEDIR'], path)
+
+    # Copy headers to URI-style include paths in build directory
+    for i in bld.path.ant_glob(path + '/*.h'):
+        bld(rule   = link,
+            source = i,
+            target = bld.path.get_bld().make_node('%s/%s' % (path, i)))
+
+    # Build test program if applicable
+    if bld.env['BUILD_TESTS'] and bld.path.find_node(path + '/%s-test.c' % name):
+        test_lib    = []
+        test_cflags = ['']
+        if bld.is_defined('HAVE_GCOV'):
+            test_lib    += ['gcov']
+            test_cflags += ['-fprofile-arcs', '-ftest-coverage']
+
+        # Unit test program
+        bld(features     = 'c cprogram',
+            source       = path + '/%s-test.c' % name,
+            lib          = test_lib,
+            target       = path + '/%s-test' % name,
+            install_path = None,
+            cflags       = test_cflags)
+
+    # Install bundle
+    bld.install_files(bundle_dir,
+                      bld.path.ant_glob(path + '/?*.*', excl='*.in'))
+
+    # Install URI-like includes
+    headers = bld.path.ant_glob(path + '/*.h')
+    if headers:
+        if bld.env['COPY_HEADERS']:
+            bld.install_files(include_dir, headers)
+        else:
+            bld.symlink_as(include_dir,
+                           os.path.relpath(bundle_dir,
+                                           os.path.dirname(include_dir)))
+
 def build(bld):
-    for i in bld.env['LV2_SUBDIRS']:
-        bld.recurse(i)
+    exts = (bld.path.ant_glob('lv2/lv2plug.in/ns/ext/*', dir=True) +
+            bld.path.ant_glob('lv2/lv2plug.in/ns/extensions/*', dir=True))
+
+    # Copy lv2.h to URI-style include path in build directory
+    lv2_h_path = 'lv2/lv2plug.in/ns/lv2core/lv2.h'
+    bld(rule   = link,
+        source = bld.path.find_node(lv2_h_path),
+        target = bld.path.get_bld().make_node(lv2_h_path))
+
+    # Build extensions
+    for i in exts:
+        build_ext(bld, i.srcpath())
 
     # LV2 pkgconfig file
     bld(features     = 'subst',
@@ -253,7 +300,8 @@ def build(bld):
         autowaf.build_dox(bld, 'LV2', VERSION, top, out)
 
         # Copy stylesheet to build directory
-        bld(rule     = copy,
+        bld(features = 'subst',
+            is_copy  = True,
             name     = 'copy',
             source   = 'doc/style.css',
             target   = 'aux/style.css')
@@ -261,41 +309,41 @@ def build(bld):
         index_files = []
 
         # Prepare spec output directories
-        for i in bld.env['LV2_SUBDIRS']:
-            if i.startswith('lv2/lv2plug.in'):
-                # Copy spec files to build dir
-                for f in bld.path.ant_glob(i + '*.*'):
-                    bld(rule   = copy,
-                        name   = 'copy',
-                        source = f,
-                        target = chop_lv2_prefix(f.srcpath()))
-
-                base = i[len('lv2/lv2plug.in'):]
-                name = os.path.basename(i[:len(i)-1])
-
-                # Generate .htaccess file
-                bld(features     = 'subst',
-                    source       = 'doc/htaccess.in',
-                    target       = os.path.join(base, '.htaccess'),
-                    install_path = None,
-                    NAME         = name,
-                    BASE         = base)
+        specs = exts + [bld.path.find_node('lv2/lv2plug.in/ns/lv2core')]
+        for i in specs:
+            # Copy spec files to build dir
+            for f in bld.path.ant_glob(i.srcpath() + '/*.*'):
+                bld(features = 'subst',
+                    is_copy  = True,
+                    name     = 'copy',
+                    source   = f,
+                    target   = chop_lv2_prefix(f.srcpath()))
+
+            base = i.srcpath()[len('lv2/lv2plug.in'):]
+            name = os.path.basename(i.srcpath())
+            
+            # Generate .htaccess file
+            bld(features     = 'subst',
+                source       = 'doc/htaccess.in',
+                target       = os.path.join(base, '.htaccess'),
+                install_path = None,
+                NAME         = name,
+                BASE         = base)
 
         # Call lv2specgen for each spec
-        for i in bld.env['LV2_SUBDIRS']:
-            if i.startswith('lv2/lv2plug.in'):
-                name = os.path.basename(i[:len(i)-1])
-                index_file = os.path.join('index_rows', name)
-                index_files += [index_file]
+        for i in specs:
+            name = os.path.basename(i.srcpath())
+            index_file = os.path.join('index_rows', name)
+            index_files += [index_file]
 
-                bld.add_group()  # Barrier (don't call lv2specgen in parallel)
+            bld.add_group()  # Barrier (don't call lv2specgen in parallel)
 
-                # Call lv2specgen to generate spec docs
-                bld(rule   = specgen,
-                    name   = 'specgen',
-                    source = os.path.join(i, name + '.ttl'),
-                    target = ['%s%s.html' % (chop_lv2_prefix(i), name),
-                              index_file])
+            # Call lv2specgen to generate spec docs
+            bld(rule   = specgen,
+                name   = 'specgen',
+                source = os.path.join(i.srcpath(), name + '.ttl'),
+                target = ['%s/%s.html' % (chop_lv2_prefix(i.srcpath()), name),
+                          index_file])
 
         index_files.sort()
         bld.add_group()  # Barrier (wait for lv2specgen to build index)
@@ -317,20 +365,26 @@ def build(bld):
 
         bld(rule         = gen_build_test,
             source       = bld.path.ant_glob('lv2/**/*.h'),
-            target       = 'build_test.c',
+            target       = 'build-test.c',
             install_path = None)
 
-        bld(features     = 'c',
-            source       = bld.path.get_bld().make_node('build_test.c'),
-            target       = 'build_test',
+        bld(features     = 'c cprogram',
+            source       = bld.path.get_bld().make_node('build-test.c'),
+            target       = 'build-test',
             install_path = None)
 
 def lint(ctx):
-    for i in (['lv2/lv2plug.in/ns/lv2core/lv2.h']
-              + glob.glob('lv2/lv2plug.in/ns/ext/*/*.h')
-              + glob.glob('lv2/lv2plug.in/ns/extensions/*/*.h')
-              + glob.glob('plugins/*/*.c') + glob.glob('plugins/*.*.h')):
-        subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-build/include,-runtime/sizeof ' + i, shell=True)
+    for i in ctx.path.ant_glob('lv2/**/*.h'):
+        subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-build/include,-runtime/sizeof ' + i.abspath(), shell=True)
+
+def test(ctx):
+    autowaf.pre_test(ctx, APPNAME, dirs=['.'])
+    for i in ctx.path.ant_glob('**/*-test'):
+        name = os.path.basename(i.abspath())
+        os.environ['PATH'] = '.' + os.pathsep + os.getenv('PATH')
+        autowaf.run_tests(
+            ctx, name, [i.path_from(ctx.path.find_node('build'))], dirs=['.'])
+    autowaf.post_test(ctx, APPNAME, dirs=['.'])
 
 class Dist(Scripting.Dist):
     def execute(self):
@@ -349,24 +403,30 @@ class DistCheck(Dist, Scripting.DistCheck):
     def archive(self):
         Dist.archive(self)
 
-def news(ctx):
-    path = ctx.path.abspath()
-    autowaf.write_news('lv2',
-                       [os.path.join(path, 'lv2/lv2plug.in/ns/meta/meta.ttl')],
-                       'NEWS')
-
-def pre_dist(ctx):
-    # Write NEWS file in source directory
-    news(ctx)
-
-def post_dist(ctx):
-    # Delete generated NEWS file from source directory
-    try:
-        os.remove(os.path.join(ctx.path.abspath(), 'NEWS'))
-    except:
-        pass
-
 def dist(ctx):
-    ctx.recurse(['.'] + get_subdirs(False), name='pre_dist')
+    subdirs = ([ctx.path.find_node('lv2/lv2plug.in/ns/lv2core')] +
+               ctx.path.ant_glob('plugins/*', dir=True) +
+               ctx.path.ant_glob('lv2/lv2plug.in/ns/ext/*', dir=True) +
+               ctx.path.ant_glob('lv2/lv2plug.in/ns/extension/*', dir=True))
+
+    # Write NEWS files in source directory
+    for i in subdirs:
+        print "* " + i.path_from(ctx.path)
+        print ctx.path.ant_glob(i.path_from(ctx.path) + '/*.ttl')
+        def abspath(node):
+            return node.abspath()
+        in_files = map(abspath,
+                       ctx.path.ant_glob(i.path_from(ctx.path) + '/*.ttl'))
+        autowaf.write_news(os.path.basename(i.abspath()),
+                           in_files,
+                           i.abspath() + '/NEWS')
+
+    # Build archive
     ctx.archive()
-    ctx.recurse(['.'] + get_subdirs(False), name='post_dist')
+
+    # Delete generated NEWS files from source directory
+    for i in subdirs:
+        try:
+            os.remove(os.path.join(i.abspath(), 'NEWS'))
+        except:
+            pass
-- 
cgit v1.2.1