diff --git a/bento.info b/bento.info
index 55e417b3cdd2..c3f78cf1e265 100644
--- a/bento.info
+++ b/bento.info
@@ -35,11 +35,13 @@ Classifiers:
     Operating System :: MacOS
 
 Recurse:
-    numpy/core
+    numpy/core,
+    numpy/lib
 
 HookFile:
     bscript,
-    numpy/core/bscript
+    numpy/core/bscript,
+    numpy/lib/bscript
 
 ExtraSourceFiles:
     numpy_templates.py,
diff --git a/bscript b/bscript
index 8d7e55664386..3796b839bf68 100644
--- a/bscript
+++ b/bscript
@@ -1,4 +1,5 @@
 import sys
+import shutil
 
 # Ugly but necessary hack: import numpy here so that wscript in sub directories
 # will see this numpy and not an already installed one
@@ -7,11 +8,13 @@ __builtin__.__NUMPY_SETUP__ = True
 
 from bento.commands.hooks \
     import \
-        pre_configure
+        pre_configure, post_build
 from bento.commands.extras.waf \
     import \
         ConfigureWafContext, BuildWafContext
 
+import waflib
+
 def check_blas_lapack(conf):
     conf.env.HAS_CBLAS = False
     if sys.platform == "win32":
@@ -56,8 +59,63 @@ def configure(context):
         conf.env.CC = ["/usr/bin/gcc-4.0"]
         conf.env.LINK_CC = ["/usr/bin/gcc-4.0"]
 
+    conf.env.CFLAGS_PYEXT.append("-Wfatal-errors")
     check_blas_lapack(conf)
 
+# FIXME: abstract those module gen tasks...
+class write_module(waflib.Task.Task):
+    color = "CYAN"
+    vars = ["CONTENT"]
+    def run(self):
+        # FIXME: put actual data here
+        self.outputs[0].write(self.env.CONTENT)
+
+@waflib.TaskGen.feature("gen_pymodule")
+def process_write_config(self):
+    if not hasattr(self, "content"):
+        raise ValueError("task gen %r expects a 'content' argument" % self.name)
+    else:
+        self.env.CONTENT = self.content
+    tsk = self.create_task("write_module")
+    tsk.set_outputs(self.path.find_or_declare(self.target))
+    return tsk
+
+@post_build()
+def pbuild(context):
+    bld = context.waf_context
+
+    bld(features="gen_pymodule",
+        target="numpy/__config__.py",
+        content="""\
+def show():
+    pass
+""",
+        always=True)
+    bld(features="gen_pymodule",
+        target="numpy/version.py",
+        content="""\
+git_revision = ""
+version = ""
+""",
+        always=True)
+    bld.compile()
+
+    # Poor man's and temporary replacement for in-place build
+    if "-i" in sys.argv:
+        for g in bld.groups:
+            for task_gen in g:
+                if hasattr(task_gen, "link_task"):
+                    ltask = task_gen.link_task
+                    for output in ltask.outputs:
+                        if output.is_child_of(bld.bldnode):
+                            shutil.copy(output.abspath(), output.path_from(bld.bldnode))
+                elif "gen_pymodule" in task_gen.features:
+                    if len(task_gen.tasks) > 0:
+                        task = task_gen.tasks[0]
+                        for output in task.outputs:
+                            if output.is_child_of(bld.bldnode):
+                                shutil.copy(output.abspath(), output.path_from(bld.bldnode))
+
 def startup(context):
     context.register_context("configure", ConfigureWafContext)
     context.register_context("build", BuildWafContext)
diff --git a/numpy/core/bento.info b/numpy/core/bento.info
index 378d7dce433d..4eb968a500a4 100644
--- a/numpy/core/bento.info
+++ b/numpy/core/bento.info
@@ -4,7 +4,8 @@ Library:
             src/npymath/_signbit.c,
             src/npymath/ieee754.c.src,
             src/npymath/npy_math.c.src,
-            src/npymath/npy_math_complex.c.src
+            src/npymath/npy_math_complex.c.src,
+            src/npymath/halffloat.c
     Extension: multiarray
         Sources:
             src/multiarray/multiarraymodule_onefile.c
diff --git a/numpy/core/bscript b/numpy/core/bscript
index 6bd5c9c87aa8..93783cdea135 100644
--- a/numpy/core/bscript
+++ b/numpy/core/bscript
@@ -3,14 +3,28 @@ import sys
 
 from bento.commands.hooks \
     import \
-        pre_configure
+        pre_configure, pre_build, post_build
 import waflib
+import waflib.Errors
+from waflib.Task \
+    import \
+        Task
+waflib.Logs.verbose = 1
 
 # Importing this adds new checkers to waf configure context - I don't like this
 # way of working, should find a more explicit way to attach new functions to
 # context.
 import numpy.build_utils
 
+from numpy.distutils.conv_template \
+    import \
+        process_str as process_c_str
+from code_generators.numpy_api \
+    import \
+        multiarray_api, ufunc_api
+from code_generators import generate_numpy_api, generate_ufunc_api, \
+        generate_umath
+
 from setup_common \
     import \
         OPTIONAL_STDFUNCS_MAYBE, OPTIONAL_STDFUNCS, C99_FUNCS_EXTENDED, \
@@ -247,3 +261,192 @@ def configure(context):
     conf.write_config_header("config.h")
 
     write_numpy_config(conf)
+
+    conf.env.INCLUDES = [".", "include", "include/numpy"]
+
+    # FIXME: Should be handled in bento context
+    conf.store()
+
+class CTemplateTask(waflib.Task.Task):
+    color = 'BLUE'
+    before = ['c']
+    def run(self):
+        s = self.inputs[0]
+        cnt = s.read()
+        writestr = process_c_str(cnt)
+        o = self.outputs[0]
+        o.write(writestr)
+
+@waflib.TaskGen.extension(".src")
+def c_template(self, node):
+    outs = []
+    outs.append(node.change_ext(""))
+
+    tsk = self.create_task('CTemplateTask', node, outs)
+    if "c" in self.features:
+        self.source.append(outs[0])
+
+class numpy_api_generator(Task):
+    vars = ["API_TUPLE"]
+    color = "BLUE"
+    before = ["c"]
+    def run(self):
+        targets = [o.path_from(self.generator.bld.srcnode) for o in self.outputs]
+        generate_numpy_api.do_generate_api(targets, self.env.API_TUPLE)
+        return 0
+
+class ufunc_api_generator(Task):
+    vars = ["API_TUPLE"]
+    color = "BLUE"
+    before = ["c"]
+    def run(self):
+        targets = [o.path_from(self.generator.bld.srcnode) for o in self.outputs]
+        generate_ufunc_api.do_generate_api(targets, self.env.API_TUPLE)
+        return 0
+
+@waflib.TaskGen.feature("numpy_api_gen")
+def process_multiarray_api_generator(self):
+    tsk = self.create_task("numpy_api_generator")
+    if hasattr(self, "api_tuple"):
+        tsk.env.API_TUPLE = self.api_tuple
+    else:
+        if not "API_TUPLE" in tsk.env:
+            tsk.env.API_TUPLE = ()
+    header = "__%s.h" % self.pattern
+    source = "__%s.c" % self.pattern
+    txt = self.pattern + ".txt"
+    files = [header, source, txt]
+    tsk.set_outputs([self.path.find_or_declare(f) for f in files])
+    return tsk
+
+@waflib.TaskGen.feature("ufunc_api_gen")
+def process_api_ufunc_generator(self):
+    tsk = self.create_task("ufunc_api_generator")
+    if hasattr(self, "api_tuple"):
+        tsk.env.API_TUPLE = self.api_tuple
+    else:
+        if not "API_TUPLE" in tsk.env:
+            tsk.env.API_TUPLE = ()
+    header = "__%s.h" % self.pattern
+    source = "__%s.c" % self.pattern
+    txt = self.pattern + ".txt"
+    files = [header, source, txt]
+    tsk.set_outputs([self.path.find_or_declare(f) for f in files])
+    return tsk
+
+class umath_generator(Task):
+    vars = ["API_TUPLE"]
+    color = "BLUE"
+    before = ["c"]
+    ext_in = ".in"
+    def run(self):
+        if len(self.outputs) > 1:
+            raise ValueError("Only one target (the .c file) is expected in the umath generator task")
+        code = generate_umath.make_code(generate_umath.defdict, generate_umath.__file__)
+        self.outputs[0].write(code)
+        return 0
+
+@waflib.TaskGen.feature("umath_gen")
+def process_umath_generator(self):
+    tsk = self.create_task("umath_generator")
+    source = "__%s.c" % self.pattern
+    tsk.set_outputs(self.path.find_or_declare(source))
+    return tsk
+
+from os.path import join as pjoin
+@pre_build()
+def pbuild(context):
+    bld = context.waf_context
+    # FIXME: bento command's context should have API so that subclasses can
+    # customize recurse behavior
+    # XXX: there is a risk of confusion between waf Node class and our own:
+    # mixing them is a big no no, and may cause very hard to debug issues.
+    # Find a solution
+    old_path = bld.path
+    bld.path = old_path.find_dir(context.local_node.path_from(context.top_node))
+    assert bld.path.__class__ == old_path.__class__
+
+    def builder(bld, library):
+        # FIXME: hack to build static library that can be linked into a dlopen-able
+        # library
+        bld(features="c pyext cstlib",
+            source=library.sources,
+            includes=["src/private", "src/npymath", "include"],
+            use="cshlib",
+            target=library.name)
+    context.register_clib_builder("npymath", builder)
+
+    def builder_multiarray(bld, extension):
+        bld(name="multiarray_api",
+            features="numpy_api_gen",
+            api_tuple=multiarray_api,
+            pattern="multiarray_api")
+
+        multiarray_templates = ["src/multiarray/scalartypes.c.src",
+                "src/multiarray/arraytypes.c.src", 
+                "src/multiarray/new_iterator.c.src", 
+                "src/multiarray/lowlevel_strided_loops.c.src", 
+                "src/multiarray/einsum.c.src"]
+        bld(target="multiarray_templates", source=multiarray_templates)
+        includes = ["src/multiarray", "src/private"]
+        bld(features="c cshlib pyext",
+            includes=includes,
+            target="multiarray",
+            source=extension.sources,
+            use="npymath")
+    context.register_builder("multiarray", builder_multiarray)
+
+    def builder_sort(bld, extension):
+        includes = [".", "src/private"]
+        bld(features="c cshlib pyext",
+            target="_sort",
+            source=extension.sources,
+            includes=includes,
+            use="npymath")
+    context.register_builder("_sort", builder_sort)
+
+    def build_ufunc(bld, extension):
+        bld(features="ufunc_api_gen",
+            api_tuple=ufunc_api,
+            pattern="ufunc_api",
+            name="ufunc_api")
+
+        ufunc_templates = ["src/umath/loops.c.src",
+                "src/umath/umathmodule.c.src",
+                "src/umath/funcs.inc.src"]
+        bld(target="ufunc_templates", source=ufunc_templates)
+
+        bld(features="umath_gen",
+            pattern="umath_generated",
+            name="umath_gen")
+
+        includes = ["src/umath", "src/private"]
+        bld(features="c cshlib pyext",
+            includes=includes,
+            target="umath",
+            source=extension.sources,
+            use="npymath")
+    context.register_builder("umath", build_ufunc)
+
+    def build_scalarmath(bld, extension):
+        bld(features="c cshlib pyext",
+            target=extension.name,
+            source=extension.sources,
+            use="npymath")
+    context.register_builder("scalarmath", build_scalarmath)
+
+    def build_multiarray_tests(bld, extension):
+        bld(features="c cshlib pyext",
+            target=extension.name,
+            source=extension.sources,
+            use="npymath")
+    context.register_builder("multiarray_tests", build_multiarray_tests)
+
+    if bld.env.HAS_CBLAS:
+        bld(features="c cshlib pyext",
+            target="_dotblas",
+            source="blasdot/_dotblas.c",
+            includes="src/private",
+            use="CBLAS")
+
+    bld.path = old_path
diff --git a/numpy/lib/bento.info b/numpy/lib/bento.info
new file mode 100644
index 000000000000..6aeeaf08f8e5
--- /dev/null
+++ b/numpy/lib/bento.info
@@ -0,0 +1,4 @@
+Library:
+    Extension: _compiled_base
+        Sources:
+             src/_compiled_base.c
diff --git a/numpy/lib/bscript b/numpy/lib/bscript
new file mode 100644
index 000000000000..03e36ce3117a
--- /dev/null
+++ b/numpy/lib/bscript
@@ -0,0 +1,33 @@
+import os
+
+from bento.commands.hooks \
+    import \
+        pre_build
+
+@pre_build()
+def pbuild(context):
+    bld = context.waf_context
+    # FIXME: bento command's context should have API so that subclasses can
+    # customize recurse behavior
+    # XXX: there is a risk of confusion between waf Node class and our own:
+    # mixing them is a big no no, and may cause very hard to debug issues.
+    # Find a solution
+    old_path = bld.path
+    bld.path = old_path.find_dir(context.local_node.path_from(context.top_node))
+    assert bld.path.__class__ == old_path.__class__
+
+    # FIXME: there has to be a better way to refer to numpy/core include
+    includes = [
+            os.path.join(bld.srcnode.path_from(bld.path), "numpy/core"),
+            os.path.join(bld.srcnode.path_from(bld.path), "numpy/core/include"),
+            os.path.join(bld.srcnode.path_from(bld.path), "numpy/core/include/numpy"),
+            os.path.join(bld.srcnode.path_from(bld.path), "numpy/core/src/private")]
+
+    def builder_compiled_base(bld, extension):
+        bld(features="c cshlib pyext",
+            target=extension.name,
+            includes=includes,
+            source=extension.sources)
+    context.register_builder("_compiled_base", builder_compiled_base)
+
+    bld.path = old_path