cython.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import re
  2. import SCons
  3. from SCons.Action import Action
  4. from SCons.Scanner import Scanner
  5. import numpy as np
  6. pyx_from_import_re = re.compile(r'^from\s+(\S+)\s+cimport', re.M)
  7. pyx_import_re = re.compile(r'^cimport\s+(\S+)', re.M)
  8. cdef_import_re = re.compile(r'^cdef extern from\s+.(\S+).:', re.M)
  9. np_version = SCons.Script.Value(np.__version__)
  10. def pyx_scan(node, env, path, arg=None):
  11. contents = node.get_text_contents()
  12. env.Depends(str(node).split('.')[0] + env['CYTHONCFILESUFFIX'], np_version)
  13. # from <module> cimport ...
  14. matches = pyx_from_import_re.findall(contents)
  15. # cimport <module>
  16. matches += pyx_import_re.findall(contents)
  17. # Modules can be either .pxd or .pyx files
  18. files = [m.replace('.', '/') + '.pxd' for m in matches]
  19. files += [m.replace('.', '/') + '.pyx' for m in matches]
  20. # cdef extern from <file>
  21. files += cdef_import_re.findall(contents)
  22. # Handle relative imports
  23. cur_dir = str(node.get_dir())
  24. files = [cur_dir + f if f.startswith('/') else f for f in files]
  25. # Filter out non-existing files (probably system imports)
  26. files = [f for f in files if env.File(f).exists()]
  27. return env.File(files)
  28. pyxscanner = Scanner(function=pyx_scan, skeys=['.pyx', '.pxd'], recursive=True)
  29. cythonAction = Action("$CYTHONCOM")
  30. def create_builder(env):
  31. try:
  32. cython = env['BUILDERS']['Cython']
  33. except KeyError:
  34. cython = SCons.Builder.Builder(
  35. action=cythonAction,
  36. emitter={},
  37. suffix=cython_suffix_emitter,
  38. single_source=1
  39. )
  40. env.Append(SCANNERS=pyxscanner)
  41. env['BUILDERS']['Cython'] = cython
  42. return cython
  43. def cython_suffix_emitter(env, source):
  44. return "$CYTHONCFILESUFFIX"
  45. def generate(env):
  46. env["CYTHON"] = "cythonize"
  47. env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE"
  48. env["CYTHONCFILESUFFIX"] = ".cpp"
  49. c_file, _ = SCons.Tool.createCFileBuilders(env)
  50. c_file.suffix['.pyx'] = cython_suffix_emitter
  51. c_file.add_action('.pyx', cythonAction)
  52. c_file.suffix['.py'] = cython_suffix_emitter
  53. c_file.add_action('.py', cythonAction)
  54. create_builder(env)
  55. def exists(env):
  56. return True