Skip to content

Commit

Permalink
FEAT: numpy.core and numpy.lib both build
Browse files Browse the repository at this point in the history
  • Loading branch information
cournape committed Aug 28, 2011
1 parent 992b4a7 commit aa7e9bd
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 5 deletions.
6 changes: 4 additions & 2 deletions bento.info
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
60 changes: 59 additions & 1 deletion bscript
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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":
Expand Down Expand Up @@ -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)
3 changes: 2 additions & 1 deletion numpy/core/bento.info
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
205 changes: 204 additions & 1 deletion numpy/core/bscript
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions numpy/lib/bento.info
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Library:
Extension: _compiled_base
Sources:
src/_compiled_base.c
33 changes: 33 additions & 0 deletions numpy/lib/bscript
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit aa7e9bd

Please sign in to comment.