Hello, I have attached sipdistutils.py which gives preliminar support for compiling SIP extensions with distutils. It is based on Pyrex's distutils support.
When you build an extension, the following happens: - The list of provided files is searched for files with extension .sip. - The files are compiled through "sip" (looking for the correct version), generating the source code in the distutils build temp directory. The SIP build file (.sbf) is also generated. - The .sbf file is parsed to extract the "sources" list of generated files - The files are appended to the list of sources to be compiled to build the extension. - Distutils contains normal execution and the .pyd/.so is created. - In later runs, the .sbf file is used to do date-based dependency check across the original .sip file. Example of usage (setup.py file): #!/usr/bin/env python from distutils.core import setup from distutils.extension import Extension from sipdistutils import build_ext setup( name = 'boolop', ext_modules=[ Extension("boolop", ["boolop.sip", "boolop.cpp"], ], cmdclass = {'build_ext': build_ext} # use sip's build_ext ) Caveats: - It doesn't support building an extension with two sip files with the same basename. - It should run whichever SIP is installed in the Python distribution which is executing distutils. It looks for SIP in the exec_prefix directory (under Windows, this is the base directory of Python). Otherwise, it defaults to using the path, but if you have multiple Python/SIP versions that could be incorrect. I could run a version check between the output of "sip -V" and sip.SIP_VERSION_STR, but it looks just too hard. There ought to be a better way to find the right sip executable, even under Linux. Suggestions? Comments? I tried basic usage under Windows and Linux and it works. Can we this included in future SIP versions? I think people will be delighted to use distutils to build their SIP-based extensions. -- Giovanni Bajo
# Subclasses disutils.command.build_ext, # replacing it with a SIP version that compiles .sip -> .cpp # before calling the original build_ext command. # Based on Pyrex.Distutils, written by Graham Fawcett and Darrel Gallion. import distutils.command.build_ext from distutils.dep_util import newer import os import sys def replace_suffix(path, new_suffix): return os.path.splitext(path)[0] + new_suffix class build_ext (distutils.command.build_ext.build_ext): description = "Compiler SIP descriptions, then build C/C++ extensions (compile/link to build directory)" def _get_sip_output_list(self, sbf): """ Parse the sbf file specified to extract the name of the generated source files. Make them absolute assuming they reside in the temp directory. """ for L in file(sbf): key, value = L.split("=", 1) if key.strip() == "sources": out = [] for o in value.split(): out.append(os.path.join(self.build_temp, o)) return out raise RuntimeError, "cannot parse SIP-generated '%s'" % sbf def _find_sip(self): if os.name in ["nt", "cygwin"]: sip = "sip.exe" else: sip = "sip" # Try looking in the exec_prefix directory (which seems to be # where it usually resides). if os.path.isfile(os.path.join(sys.exec_prefix, sip)): return os.path.join(sys.exec_prefix, sip) # Assume it's in the PATH: self.spawn() will find it there. return sip def swig_sources (self, sources, extension=None): if not self.extensions: return # Create the temporary directory if it does not exist already if not os.path.isdir(self.build_temp): os.makedirs(self.build_temp) # Collect the names of the source (.sip) files sip_sources = [] sip_sources = [source for source in sources if source.endswith('.sip')] other_sources = [source for source in sources if not source.endswith('.sip')] generated_sources = [] for sip in sip_sources: # Use the sbf file as dependency check sipbn = os.path.basename(sip) sbf = os.path.join(self.build_temp, replace_suffix(sipbn, "sbf")) if newer(sip, sbf) or self.force: self.sip_compile(sip, sbf) out = self._get_sip_output_list(sbf) generated_sources.extend(out) return generated_sources + other_sources def sip_compile(self, source, sbf): self.spawn(["sip", "-c", self.build_temp, "-b", sbf, source])
_______________________________________________ PyKDE mailing list PyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde