0

setup.py now auto-discovers available render primitives

This commit is contained in:
Aaron Griffith
2012-01-08 00:52:30 -05:00
parent a682b8a689
commit 7cacc59428
4 changed files with 70 additions and 58 deletions

3
.gitignore vendored
View File

@@ -22,8 +22,9 @@ overviewer_core/c_overviewer.pyd
overviewer_core/c_overviewer_d.pyd overviewer_core/c_overviewer_d.pyd
overviewer_core/c_overviewer.dylib overviewer_core/c_overviewer.dylib
# generated version file # generated files
overviewer_core/overviewer_version.py overviewer_core/overviewer_version.py
overviewer_core/src/primitives.h
# Mac OS X noise # Mac OS X noise
.DS_Store .DS_Store

View File

@@ -19,29 +19,13 @@
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
extern RenderPrimitiveInterface primitive_base; /* this file defines render_primitives,
extern RenderPrimitiveInterface primitive_nether; a list of all render primitives, ending in NULL
extern RenderPrimitiveInterface primitive_height_fading;
extern RenderPrimitiveInterface primitive_depth;
extern RenderPrimitiveInterface primitive_edge_lines;
/* list of all render primitives, ending in NULL
all of these will be available to the user, so DON'T include primitives all of these will be available to the user, so DON'T include primitives
that are only useful as a base for other primitives. */ that are only useful as a base for other primitives.
static RenderPrimitiveInterface *render_primitives[] = {
&primitive_base, this file is auto-generated by setup.py */
&primitive_nether, #include "primitives.h"
&primitive_height_fading,
&primitive_depth,
&primitive_edge_lines,
//&rendermode_lighting,
//&rendermode_smooth_lighting,
//&rendermode_cave,
//&rendermode_spawn,
//&rendermode_mineral,
NULL
};
/* rendermode encapsulation */ /* rendermode encapsulation */

View File

@@ -15,15 +15,27 @@
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>. * with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* /* To make a new render primitive:
* To make a new render primitive (the C part, at least):
* *
* * add a data struct and extern'd interface declaration below * * add a new class to rendermodes.py
* there are a ton of examples there, the syntax is pretty simple. If
* you need any extra objects that are easy to create in python, this
* is where you put them.
* *
* * fill in this interface struct in primitives/(yourmode).c * * create a file in src/primitives with the same name
* (see primitives/base.c for an example: the "base" primitive) * so, Nether (named "nether") goes in `nether.c`.
* *
* * add your primitive to the list in rendermodes.c * * declare a RenderPrimitiveInterface with the name primitive_name
* if you have an underscore in the name, replace it with a
* hyphen. height-fading uses primitive_height_fading.
*
* * fill in the entries of this struct
* the name should match, and you should declare an 'instance' struct
* to use as the self argument to each function. See nether.c and
* height-fading.c for simple examples.
*
* setup.py will pick up your primitive, add it to the global list, and build
* it for you if you follow these conventions.
*/ */
#ifndef __RENDERMODES_H_INCLUDED__ #ifndef __RENDERMODES_H_INCLUDED__

View File

@@ -15,6 +15,7 @@ import glob
import platform import platform
import time import time
import overviewer_core.util as util import overviewer_core.util as util
import numpy
try: try:
import py2exe import py2exe
@@ -133,7 +134,6 @@ if py2exe is None:
# #
# Third-party modules - we depend on numpy for everything # Third-party modules - we depend on numpy for everything
import numpy
# Obtain the numpy include directory. This logic works across numpy versions. # Obtain the numpy include directory. This logic works across numpy versions.
try: try:
numpy_include = numpy.get_include() numpy_include = numpy.get_include()
@@ -149,9 +149,13 @@ except Exception:
# used to figure out what files to compile # used to figure out what files to compile
#render_modes = ['normal', 'lighting', 'smooth-lighting', 'cave'] # auto-created from files in primitives/, but we need the raw names so
#render_modes += ['overlay', 'spawn', 'mineral'] # we can use them later.
primitives = ['base', 'nether', 'height-fading', 'depth', 'edge-lines'] primitives = []
for name in glob.glob("overviewer_core/src/primitives/*.c"):
name = os.path.split(name)[-1]
name = os.path.splitext(name)[0]
primitives.append(name)
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c'] c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
c_overviewer_files += map(lambda mode: 'primitives/%s.c' % (mode,), primitives) c_overviewer_files += map(lambda mode: 'primitives/%s.c' % (mode,), primitives)
@@ -169,7 +173,7 @@ setup_kwargs['ext_modules'].append(Extension('overviewer_core.c_overviewer', c_o
setup_kwargs['options']['build_ext'] = {'inplace' : 1} setup_kwargs['options']['build_ext'] = {'inplace' : 1}
# custom clean command to remove in-place extension # custom clean command to remove in-place extension
# and the version file # and the version file, primitives header
class CustomClean(clean): class CustomClean(clean):
def run(self): def run(self):
# do the normal cleanup # do the normal cleanup
@@ -178,31 +182,24 @@ class CustomClean(clean):
# try to remove '_composite.{so,pyd,...}' extension, # try to remove '_composite.{so,pyd,...}' extension,
# regardless of the current system's extension name convention # regardless of the current system's extension name convention
build_ext = self.get_finalized_command('build_ext') build_ext = self.get_finalized_command('build_ext')
pretty_fname = build_ext.get_ext_filename('overviewer_core.c_overviewer') ext_fname = build_ext.get_ext_filename('overviewer_core.c_overviewer')
fname = pretty_fname
if os.path.exists(fname):
try:
if not self.dry_run:
os.remove(fname)
log.info("removing '%s'", pretty_fname)
except OSError:
log.warn("'%s' could not be cleaned -- permission denied",
pretty_fname)
else:
log.debug("'%s' does not exist -- can't clean it",
pretty_fname)
versionpath = os.path.join("overviewer_core", "overviewer_version.py") versionpath = os.path.join("overviewer_core", "overviewer_version.py")
if os.path.exists(versionpath): primspath = os.path.join("overviewer_core", "src", "primitives.h")
try:
if not self.dry_run: for fname in [ext_fname, versionpath, primspath]:
os.remove(versionpath) if os.path.exists(fname):
log.info("removing '%s'", versionpath) try:
except OSError: log.info("removing '%s'", fname)
log.warn("'%s' could not be cleaned -- permission denied", versionpath) if not self.dry_run:
else: os.remove(fname)
log.debug("'%s' does not exist -- can't clean it", versionpath)
except OSError:
log.warn("'%s' could not be cleaned -- permission denied",
fname)
else:
log.debug("'%s' does not exist -- can't clean it",
fname)
# now try to purge all *.pyc files # now try to purge all *.pyc files
for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), ".")): for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), ".")):
for f in files: for f in files:
@@ -226,16 +223,34 @@ def generate_version_py():
except Exception: except Exception:
print "WARNING: failed to build overviewer_version file" print "WARNING: failed to build overviewer_version file"
def generate_primitives_h():
global primitives
prims = [p.lower().replace('-', '_') for p in primitives]
outstr = "/* this file is auto-generated by setup.py */\n"
for p in prims:
outstr += "extern RenderPrimitiveInterface primitive_{0};\n".format(p)
outstr += "static RenderPrimitiveInterface *render_primitives[] = {\n"
for p in prims:
outstr += " &primitive_{0},\n".format(p)
outstr += " NULL\n"
outstr += "};\n"
with open("overviewer_core/src/primitives.h", "w") as f:
f.write(outstr)
class CustomSDist(sdist): class CustomSDist(sdist):
def run(self): def run(self):
# generate the version file # generate the version file
generate_version_py() generate_version_py()
generate_primitives_h()
sdist.run(self) sdist.run(self)
class CustomBuild(build): class CustomBuild(build):
def run(self): def run(self):
# generate the version file # generate the version file
generate_version_py() generate_version_py()
generate_primitives_h()
build.run(self) build.run(self)
print "\nBuild Complete" print "\nBuild Complete"