[Pyrex] distutils and .c files

dunk dunk at dunkfordyce.co.uk
Sat Nov 12 12:03:57 CET 2005


hi, 
following up from my last message im using the following code to improve 
working with distutils. it automatically adds any included files as deps to 
the extension and also removes the generated .c file if pyrex encountered 
errors.

the code:

import os
import sys

from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
import Pyrex.Compiler.Main
from distutils.dep_util import newer

def replace_suffix(path, new_suffix):
  return os.path.splitext(path)[0] + new_suffix

def find_includes(filename):
  includes = []

  for line in open(filename).readlines():
    if line.startswith('include "'):
      includes.append( line.split('"')[1] )

  # XXX should recursivly scan files?
    
  return includes
      
class pyrex_build_ext(build_ext):
  def swig_sources (self, sources, ext=None):
    if not self.extensions:
      return

    # collect the names of the source (.pyx) files
    pyx_sources = []
    pyx_sources = [source for source in sources if source.endswith('.pyx')]
    other_sources = [source for source in sources if not 
source.endswith('.pyx')]
    deps = [source for source in ext.depends if source.endswith('.pxd') or 
source.endswith('.pyx')]

    extension = self.swig_cpp and '.cpp' or '.c'
    for pyx in pyx_sources:
      # should I raise an exception if it doesn't exist?
      if os.path.exists(pyx):
        print "pyrex'ing %s..." % pyx
        source = pyx

        target = replace_suffix(source, extension)

        pxd = replace_suffix(source, '.pxd')          

        if os.path.exists(pxd):
          includes = find_includes(pxd)

        compile = False
       
        if self.force:
          print "forcing compile"
          compile = True
        elif newer(source, target):
          print "%s is newer than %s" % (source, target)
          compile = True 
        else:
          for file in deps:
            if newer(file, target):
              print "include %s is newer than %s" % (file, target)
              compile = True
              break

        if compile:
          if self.pyrex_compile(source) != 0:
            print "errors compiling %s. aborting and removing %s" % (source, 
target)
            os.unlink(target)
            sys.exit(1)

          if self.swig_cpp:
            # rename .c to .cpp (Pyrex always builds .c ...)
            if os.path.exists(target):
              os.unlink(target)
            #os.rename(source.replace('.pyx', '.c'), target)
            os.rename(replace_suffix(source, '.c'), target)
            # massage the cpp file
            self.c_to_cpp(target)
        else:
          print "not compiling"

    return [replace_suffix(src, extension) for src in pyx_sources] + 
other_sources

  def pyrex_compile(self, source):
    result = Pyrex.Compiler.Main.compile(source)
    return result.num_errors

class PyrexExtension(Extension):
  def __init__(self, name, sources, **kwargs):
    pyx = sources[0]
    pxd = replace_suffix(pyx, '.pxd')
    includes = find_includes(pyx) + find_includes(pxd)

    try:
      kwargs['depends'] += includes
    except KeyError:
      kwargs['depends'] = includes

    Extension.__init__(self, name, sources, **kwargs)


On Thursday 10 November 2005 17:29, dunk wrote:
> hi,
> refering to the post entitled "pyrexc leaves bad C files, distutils doesn't
> clean" [
> http://lists.copyleft.no/pipermail/pyrex/2004-September/000928.html ]...
>
> the answer appears to be "You're right, this is not the best of situations.
> I'll add it to the list of things to fix."
>
> did that ever get fixed?
>
> it doesnt mention it in the post but shouldnt setup.py clean remove the .c
> files?
>
> cheers,
> dunk
>
> _______________________________________________
> Pyrex mailing list
> Pyrex at lists.copyleft.no
> http://lists.copyleft.no/mailman/listinfo/pyrex



More information about the Pyrex mailing list