From 73dbefbe532057ce77d9f338a4dc093cdce89898 Mon Sep 17 00:00:00 2001 From: regrain Date: Thu, 22 May 2003 10:44:30 +0000 Subject: [PATCH] * Modification of setup.py to compile vtk part too. Then, we have 2 wrappers which must work with same distutils. For that, we have a generic distutils in distusiltsWrapping.py ; with : - build_extWrap class to wrap generically all extensions, - ExtensionWrap base class for all wrapping extension that contains a wrapper - Wrapper interface which wrap sources + In WrapSwig.py we have extension and wrapper for Swig + In WrapVTK.py we have extension and wrapper for VTK * MANIFEST.in : modifications to consider vtk directory and new python files for compilation -- BeNours --- ChangeLog | 15 +++- MANIFEST.in | 3 +- WrapSwig.py | 106 ++++++++++++++++++++++++++ WrapVTK.py | 125 ++++++++++++++++++++++++++++++ distutilsSwigCPlusPlus.py | 156 -------------------------------------- distutilsWrapping.py | 72 ++++++++++++++++++ setup.py | 72 +++++++++++++----- 7 files changed, 374 insertions(+), 175 deletions(-) create mode 100644 WrapSwig.py create mode 100644 WrapVTK.py delete mode 100644 distutilsSwigCPlusPlus.py create mode 100644 distutilsWrapping.py diff --git a/ChangeLog b/ChangeLog index a7f655fe..eae0cf63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,17 @@ -2003-05-21 Eric Boix with JPR +2003-05-22 Benoit Regrain + * Modification of setup.py to compile vtk part too. Then, we have 2 + wrappers which must work with same distutils. For that, we have a + generic distutils in distusiltsWrapping.py ; with : + - build_extWrap class to wrap generically all extensions, + - ExtensionWrap base class for all wrapping extension that contains + a wrapper + - Wrapper interface which wrap sources + + In WrapSwig.py we have extension and wrapper for Swig + + In WrapVTK.py we have extension and wrapper for VTK + * MANIFEST.in : modifications to consider vtk directory and new python + files for compilation + +2003-05-21 Eric Boix with Benoit Regrain * Added python wrappers of vtkGdcmReader vtk class (see the source in vtk/vtkGdcmReader.cxx) : - vtk/Makefile.am now builds a library diff --git a/MANIFEST.in b/MANIFEST.in index 0d995412..9865aca3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ -include distutilsSwigCPlusPlus.py +include *.py recursive-include src *.h +recursive-include vtk *.h recursive-include Dicts *.dic recursive-include Data *.* diff --git a/WrapSwig.py b/WrapSwig.py new file mode 100644 index 00000000..f8e02f9a --- /dev/null +++ b/WrapSwig.py @@ -0,0 +1,106 @@ +from distutilsWrapping import * +from types import ListType +import os + +class SwigWrapper(Wrapper): + """ + This distutils command is meant to be used with MyExtension extension,which + defines a swig_include attribute. + """ + def WrapSources(self,distutil,extWrap,sources): + """Walk the list of source files in 'sources',looking for SWIG + interface(.i) files. Run SWIG on all that are found,and + return a modified 'sources' list with SWIG source files replaced + by the generated C(or C++) files. + """ + + new_sources=[] + swig_sources=[] + swig_targets={} + + # XXX this drops generated C/C++ files into the source tree,which + # is fine for developers who want to distribute the generated + # source -- but there should be an option to put SWIG output in + # the temp dir. + + ## Modified lines(compared to buil_exts.wig_sources original method) + if extWrap.swig_cpp: + target_ext='_wrap.cpp' + else: + target_ext='_wrap.c' + ## End of modification + + for source in sources: + (base,ext)=os.path.splitext(source) + if ext==".i": # SWIG interface file + new_sources.append(base + target_ext) + swig_sources.append(source) + swig_targets[source]=new_sources[-1] + elif ext==".h": + continue + else: + new_sources.append(source) + + if not swig_sources: + return new_sources + + swig=distutil.find_swig() + + ## Modified lines(compared to buil_exts.wig_sources original method) + swig_cmd=[swig,"-python"] + if extWrap.swig_cpp: + swig_cmd.append("-c++") + + if extWrap.swig_include: + for pth in extWrap.swig_include: + swig_cmd.append("-I%s"%pth) + ## End of modification + + for source in swig_sources: + target=swig_targets[source] + distutil.announce("swigging %s to %s" %(source,target)) + distutil.spawn(swig_cmd + ["-o",target,source]) + ## Modified lines(compared to buil_exts.wig_sources original method) + # When swig generated some shadow classes,place them under + # self.build_lib(the build directory for Python source). + if extWrap.swig_cpp: + # Generate the full pathname of the shadow classes file + import string + swig_shadow=string.split(os.path.basename(source),".")[0] + swig_shadow=swig_shadow + '.py' + # On win32 swig places the shadow classes in the directory + # where it was invoked. This is to be opposed to posix where + # swig places the shadow classes aside the C++ wrapping code + #(the target in our context). + if(os.name=='posix'): + infile=os.path.join(os.path.dirname(source),swig_shadow) + else: + infile=swig_shadow + if os.path.isfile(infile): + outfile=[distutil.build_lib,distutil.distribution.get_name()] + outfile.append(swig_shadow) + outfile=apply(os.path.join,outfile) + distutil.copy_file(infile,outfile,preserve_mode=0) + else: + distutil.announce("Warning: swig shadow classes not copied") + ## End of modification + + return new_sources + +class SwigExtension(ExtensionWrap): + """ + This class extends basic distutils Extension class,adding two keyword + arguments : + * swig_cpp,which triggers -c++ mode when swigging + * swig_include,which specifies -I flag when swigging + This class is meant to be build with mybuild_ext distutils command. + """ + def __init__(self,swig_include=None,swig_cpp=None,**args): + ExtensionWrap.__init__(self,SwigWrapper(),**args) + + assert((swig_include==None or type(swig_include) is ListType), + "swig_include must be a list of strings") + + self.swig_include=swig_include or [] + self.swig_cpp=swig_cpp + diff --git a/WrapVTK.py b/WrapVTK.py new file mode 100644 index 00000000..49772bcc --- /dev/null +++ b/WrapVTK.py @@ -0,0 +1,125 @@ +from distutilsWrapping import * +import types +import string +import os + +class VTKWrapper(Wrapper): + """ + This distutils command is meant to be used with MyExtension extension, which + defines a swig_include attribute. + """ + def WrapSources(self,distutil,extWrap,sources): + """ + Walk the list of source files in 'sources', looking for VTK + interface (vtk*.cxx) files. Compile vtkWrapPythonInit. + Run vtkWrapPython on all that are found, and + return a modified 'sources' list with SWIG source files replaced + by the generated C (or C++) files. + + FIXME nierk + """ + self.__extWrap=extWrap + + newSources=[] + vtkSources=[] + vtkTargets={} + + # Wrapping of sources + target_ext='Python.cxx' + + for source in sources: + (base,ext)=os.path.splitext(source) + fileName=os.path.split(base) + if((ext==".cxx")and(fileName[-1][0:3]=="vtk")): + newSources.append(source) + newSources.append(base+target_ext) + vtkSources.append(base+'.h') + vtkTargets[base+'.h']=newSources[-1] + else: + newSources.append(source) + + # Find vtkWrapPython + wrapper=self.FindvtkWrapPython() + if(not self.__extWrap.vtkHints): + self.__extWrap.vtkHints="toto" + + wrapCmd=[wrapper] + for source in vtkSources: + target=vtkTargets[source] + distutil.announce("VTK wrapping %s to %s" % (source,target)) + distutil.spawn([wrapper,source,self.__extWrap.vtkHints,target]) + + # Compilation of vtkWrapPythonInit + vtkWrapInit=self.__extWrap.vtkModule+"Init"+target_ext + distutil.announce("VTK init wrapping to %s" % vtkWrapInit) + self.WrapInit(vtkSources,vtkWrapInit) + newSources.append(vtkWrapInit) + + return newSources + + def FindvtkWrapPython(self): + assert(os.path.isfile(self.__extWrap.vtkWrapper), + "Write an heuristic in FindvtkWrapPython") + return(self.__extWrap.vtkWrapper) + + def WrapInit(self,vtkSource,target): + dllName=string.split(self.__extWrap.vtkModule,'.')[-1] + f=open(target,"w") + + f.write('#include \n') + f.write('#include "Python.h"\n\n') + + for src in vtkSource: + src=os.path.split(src)[-1] + (src,_)=os.path.splitext(src) + f.write('extern "C" { ') + if(os.name!="posix"): + f.write('__declspec( dllexport ) ') + f.write('PyObject *PyVTKClass_%sNew(char *); }\n'% src) + + # Lib Init + f.write('\nstatic PyMethodDef Py%s_ClassMethods[] = {\n'% dllName) + f.write('{NULL, NULL}};\n\n') + + f.write('extern "C" { ') + if(os.name!="posix"): + f.write('__declspec( dllexport ) ') + f.write('void init%s();}\n\n'% dllName) + + f.write('void init%s()\n{\n'% dllName) + f.write(' PyObject *m, *d, *c;\n\n') + f.write(' static char modulename[] = "%s";\n'% dllName) + f.write(' m = Py_InitModule(modulename, Py%s_ClassMethods);\n'% dllName) + + f.write(' d = PyModule_GetDict(m);\n') + f.write(' if (!d) Py_FatalError("can''t get dictionary for module %s!");\n\n'% dllName) + + # New function + for src in vtkSource: + src=os.path.split(src)[-1] + (src,_)=os.path.splitext(src) + f.write(' if ((c = PyVTKClass_%sNew(modulename)))\n'% src) + f.write(' if (-1 == PyDict_SetItemString(d, "%s", c))\n'% src) + f.write(' Py_FatalError("can''t add class %s to dictionary!");\n\n'% src) + f.write('}\n\n') + + f.close() + +class VTKExtension(ExtensionWrap): + """ + This class extends basic distutils Extension class, adding two keyword + arguments : + * swig_cpp, which triggers -c++ mode when swigging + * swig_include, which specifies -I flag when swigging + This class is meant to be build with mybuild_ext distutils command. + """ + def __init__(self,name,vtkHints=None, + vtkWrapper=None,**args): + ExtensionWrap.__init__(self,name=name,wrapper=VTKWrapper(),**args) + + assert(type(name)==types.StringType,"vtk Module must be a string") + + self.vtkHints=vtkHints + self.vtkModule=name + self.vtkWrapper=vtkWrapper + diff --git a/distutilsSwigCPlusPlus.py b/distutilsSwigCPlusPlus.py deleted file mode 100644 index d4e8e402..00000000 --- a/distutilsSwigCPlusPlus.py +++ /dev/null @@ -1,156 +0,0 @@ -from distutils.command.build_ext import build_ext -from distutils.core import Extension -from types import ListType -import os - -class mybuild_ext(build_ext): - """ - This distutils command is meant to be used with MyExtension extension, which - defines a swig_include attribute. - """ - build_ext.user_options.append(('swig-include=','S', - "list of directories for swig to search in" + - "for header files")) - - def initialize_options (self): - build_ext.initialize_options(self) - self.swig_include = None - - def finalize_options (self): - build_ext.finalize_options(self) - if self.swig_include!=None: - self.swig_include=self.swig_include.split(":") - - def build_extension(self, ext): - # command-line arguments prevail over extension arguments - # but if no command-line argument is defined, extension argument is - # taken into account - if self.swig_include==None:self.swig_include=ext.swig_include - if self.swig_cpp==None:self.swig_cpp=ext.swig_cpp - - build_ext.build_extension(self,ext) - - def swig_sources (self, sources): - - """Walk the list of source files in 'sources', looking for SWIG - interface (.i) files. Run SWIG on all that are found, and - return a modified 'sources' list with SWIG source files replaced - by the generated C (or C++) files. - """ - - new_sources = [] - swig_sources = [] - swig_targets = {} - - # XXX this drops generated C/C++ files into the source tree, which - # is fine for developers who want to distribute the generated - # source -- but there should be an option to put SWIG output in - # the temp dir. - - ## Modified lines (compared to buil_exts.wig_sources original method) - if self.swig_cpp: - target_ext = '_wrap.cpp' - else: - target_ext = '_wrap.c' - ## End of modification - - for source in sources: - (base, ext) = os.path.splitext(source) - if ext == ".i": # SWIG interface file - new_sources.append(base + target_ext) - swig_sources.append(source) - swig_targets[source] = new_sources[-1] - elif ext == ".h": - continue - else: - new_sources.append(source) - - if not swig_sources: - return new_sources - - swig = self.find_swig() - - ## Modified lines (compared to buil_exts.wig_sources original method) - swig_cmd = [swig, "-python"] - if self.swig_cpp: - swig_cmd.append("-c++") - - if self.swig_include: - for pth in self.swig_include: - swig_cmd.append("-I%s"%pth) - ## End of modification - - for source in swig_sources: - target = swig_targets[source] - self.announce("swigging %s to %s" % (source, target)) - self.spawn(swig_cmd + ["-o", target, source]) - ## Modified lines (compared to buil_exts.wig_sources original method) - # When swig generated some shadow classes, place them under - # self.build_lib (the build directory for Python source). - if self.swig_cpp: - # Generate the full pathname of the shadow classes file - import string - swig_shadow = string.split(os.path.basename(source), ".")[0] - swig_shadow = swig_shadow + '.py' - # On win32 swig places the shadow classes in the directory - # where it was invoked. This is to be opposed to posix where - # swig places the shadow classes aside the C++ wrapping code - # (the target in our context). - if(os.name=='posix'): - infile = os.path.join(os.path.dirname(source), swig_shadow) - else: - infile = swig_shadow - if os.path.isfile(infile): - outfile = [self.build_lib, self.distribution.get_name()] - outfile.append(swig_shadow) - outfile = apply(os.path.join, outfile) - self.copy_file(infile, outfile, preserve_mode=0) - else: - self.announce("Warning: swig shadow classes not copied") - ## End of modification - - return new_sources - -class MyExtension(Extension): - """ - This class extends basic distutils Extension class, adding two keyword - arguments : - * swig_cpp, which triggers -c++ mode when swigging - * swig_include, which specifies -I flag when swigging - This class is meant to be build with mybuild_ext distutils command. - """ - def __init__(self,swig_include=None,swig_cpp=None,**args): - Extension.__init__(self,**args) - - assert ((swig_include==None or type(swig_include) is ListType), - "swig_include must be a list of strings") - - self.swig_include = swig_include or [] - self.swig_cpp = swig_cpp - -""" -Example of use of these classes in distutils setup method : - -from Transfert.tcDistUtils import mybuild_ext,MyExtension -setup(name="xxx", - version="X.Y", - description="blah blah blah", - author="John Doe", - author_email="i.hate@spam.com", - url="http://www.fakeurl.com", - packages=["yyy"], - cmdclass={'build_ext':mybuild_ext}, # redirects default build_ext - ext_modules=[MyExtension(name="src/xxx, # instance of our Extension class - sources=["src/xxx.cpp", - "src/xxx.i"], - include_dirs=["/usr/include/python2.1", - "/usr/include/vtk"], - libraries=["vtkGraphics"], - swig_cpp=1, # C++ support - swig_include=["src"] # SWIG include dirs - ) - ] - ) - -and then run "python setup.py build"... -""" diff --git a/distutilsWrapping.py b/distutilsWrapping.py new file mode 100644 index 00000000..96152a9b --- /dev/null +++ b/distutilsWrapping.py @@ -0,0 +1,72 @@ +from distutils.command.build_ext import build_ext +from distutils.core import Extension +from types import ListType +import os + +class build_extWrap(build_ext): + """ + This distutils command is meant to be used with all wrapper defined for + this format. + To realize it,we can't have command-line parameters + """ + def build_extension(self,ext): + # command-line arguments prevail over extension arguments + # but if no command-line argument is defined,extension argument is + # taken into account + self.__ext=ext + build_ext.build_extension(self,ext) + + def swig_sources(self,sources): + """Walk the list of source files in 'sources',looking for SWIG + interface(.i) files. Run SWIG on all that are found,and + return a modified 'sources' list with SWIG source files replaced + by the generated C(or C++) files. + """ + try: + return(self.__ext.wrapper.WrapSources(self,self.__ext,sources)) + except Exception,e: + print Exception,e + self.announce("Warning: wrapping error") + return(sources) + +class Wrapper: + def WrapSources(self,distutil,extWrap,sources): + pass + +class ExtensionWrap(Extension): + """ + This class extends basic distutils Extension class,adding two keyword + arguments : + * swig_cpp,which triggers -c++ mode when swigging + * swig_include,which specifies -I flag when swigging + This class is meant to be build with mybuild_ext distutils command. + """ + def __init__(self,wrapper=None,**args): + Extension.__init__(self,**args) + + self.wrapper=wrapper + +""" +Example of use of these classes in distutils setup method : + +from Transfert.tcDistUtils import mybuild_ext,MyExtension +setup(name="xxx", + version="X.Y", + description="blah blah blah", + author="John Doe", + author_email="i.hate@spam.com", + url="http://www.fakeurl.com", + packages=["yyy"], + cmdclass={'build_ext':build_extWrap},# redirects default build_ext + ext_modules=[ExtensionWrap(name="src/xxx,# instance of our Extension class + sources=["src/xxx.cpp", + "src/xxx.i"], + include_dirs=["/usr/include/python2.1", + "/usr/include/vtk"], + libraries=["vtkGraphics"], + ) + ] + ) + +and then run "python setup.py build"... +""" diff --git a/setup.py b/setup.py index d36e0517..b1f59235 100644 --- a/setup.py +++ b/setup.py @@ -1,48 +1,86 @@ from distutils.core import setup import glob, os, sys, shutil -from distutilsSwigCPlusPlus import * +from distutilsWrapping import * +from WrapSwig import * +from WrapVTK import * ThisModule='gdcmPython' gdcmPythonSrcDir=ThisModule gdcmSrcDir ="src" +gdcmvtkSrcDir ="vtk" gdcmDictsDir ="Dicts" gdcmTestDir ="Test" # Due to a disutil oddity on Unices : see # http://aspn.activestate.com/ASPN/Mail/Message/distutils-sig/588325 if(os.name=='posix'): - targetDir=os.path.join('lib','python'+sys.version[:3],'site-packages') - libraries=["stdc++"] - macros =[('__STDC_LIMIT_MACROS', '1')] + targetDir=os.path.join('lib','python'+sys.version[:3],'site-packages') + libraries=["stdc++"] + macros =[('__STDC_LIMIT_MACROS', '1')] + + VTK_PATH="/usr" + vtkWrapper="vtkWrapPython" else: - targetDir=os.path.join('lib','site-packages') - libraries=["WSOCK32"] - macros =[] + targetDir=os.path.join('lib','site-packages') + libraries=["WSOCK32"] + macros =[] + + try: + VTK_PATH=os.environ['VTK_PATH'] + except KeyError,e: + err=str(e) + print "Environment variable",err[err.rfind(':')+1:],'not defined, '\ + 'please fix it!' + VTK_PATH="c:\\Creatis\\vtkDistrib" + vtkWrapper=os.path.join(VTK_PATH,"bin","vtkWrapPython") targetDir=os.path.join(targetDir, ThisModule) +# For the Swig compilation Sources = [] Sources.extend(glob.glob(os.path.join(gdcmSrcDir,"*.cxx"))) Sources.extend(glob.glob(os.path.join(gdcmSrcDir,"*.h"))) Sources.append(os.path.join(gdcmPythonSrcDir,"gdcm.i")) +# For the VTK compilation +VTK_INCLUDE_DIR=os.path.join(VTK_PATH,"include","vtk") +VTK_LIB_DIR=os.path.join(VTK_PATH,"lib","vtk") + +vtkSources = [] +vtkSources.extend(glob.glob(os.path.join(gdcmvtkSrcDir,"vtk*.cxx"))) +vtkSources.extend(glob.glob(os.path.join(gdcmSrcDir,"*.cxx"))) +# vtkSources.extend(glob.glob(os.path.join(gdcmvtkSrcDir,"vtk*.h"))) + +vtkLibraries=["vtkCommon","vtkCommonPython", + "vtkIO","vtkIOPython", + "vtkFiltering","vtkFilteringPython"] + setup(name=ThisModule, - version="0.1", + version="0.2", description="...", author="frog", author_email="frog@creatis.insa-lyon.fr", url="http://www.creatis.insa-lyon.fr/", packages=[ gdcmPythonSrcDir, gdcmPythonSrcDir + '.demo' ], - cmdclass={'build_ext':mybuild_ext}, # redirects default build_ext - ext_modules=[MyExtension( - name='_gdcm', - sources=Sources, - include_dirs=[gdcmSrcDir], - libraries=libraries, - define_macros=macros, - swig_cpp=1, - swig_include=[ gdcmSrcDir] ) ], + cmdclass={'build_ext':build_extWrap}, # redirects default build_ext + ext_modules=[SwigExtension(name='_gdcm', + sources=Sources, + include_dirs=[gdcmSrcDir], + libraries=libraries, + define_macros=macros, + swig_cpp=1, + swig_include=[gdcmSrcDir] + ), + VTKExtension(name='gdcmPython.vtkgdcmPython', + sources=vtkSources, + include_dirs=[gdcmSrcDir,gdcmvtkSrcDir,VTK_INCLUDE_DIR], + libraries=libraries+vtkLibraries, + define_macros=macros, + library_dirs=[VTK_LIB_DIR], + vtkWrapper=vtkWrapper, + ), + ], data_files=[(os.path.join(targetDir,gdcmTestDir), glob.glob(os.path.join(gdcmTestDir,"*.acr"))), (os.path.join(targetDir,"Dicts"), -- 2.45.1