From a1e88e83ae730e90f37f7f7c96cb6262ae79d0f7 Mon Sep 17 00:00:00 2001
From: Christoph Groth <christoph.groth@cea.fr>
Date: Fri, 2 Mar 2012 17:29:08 +0100
Subject: [PATCH] include cythonized files in source distribution, do not run
 cython by default

---
 MANIFEST.in |  1 +
 README.txt  | 14 ++++++++---
 setup.py    | 68 +++++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 62 insertions(+), 21 deletions(-)

diff --git a/MANIFEST.in b/MANIFEST.in
index fbf40cfd..50cb427a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,7 @@
 # This file specifies the files to be included in the source distribution
 # in addition to the default ones.
 
+recursive-include kwant *.pyx
 recursive-include kwant *.pxd
 recursive-include kwant *.h
 recursive-include kwant test_*.py
diff --git a/README.txt b/README.txt
index c09a78aa..7550f095 100644
--- a/README.txt
+++ b/README.txt
@@ -11,15 +11,19 @@ The only exception to this is the ``doc/sphinxext`` subdirectory, which is free
 software.  (See the file ``LICENSE.txt`` in that subdirectory.)
 
 
-Installation
-============
+Installation from source
+========================
 
 The prerequisites are
 
  - More or less current versions of `Python <http://python.org>`_ and `SciPy
    <http://scipy.org>`_.  Python 2.6 and scipy 0.7.2 should be enough.
 
- - `Cython <http://cython.org/>`_ -- Version 0.13 works for us.
+ - An environment which allows to compile Python extensions written in C.  This
+   includes a C compiler and Python C headers.  The latter might be provided in
+   a separate package like ``python-dev``.
+
+ - Some incarnation of `LAPACK <http://www.netlib.org/lapack/>`_.
 
 optional:
 
@@ -100,6 +104,10 @@ Some conventions to keep in mind:
 * Write tests for all the important functionality you add.  Be sure not to
   break existing tests.
 
+Several modules are written in `Cython <http://cython.org/>`_ (.pyx file name
+extension).  You will need Cython if you want to modify them.  Turn on
+cythonization by passing the option ``--run-cython`` to setup.py.
+
 
 Tests
 =====
diff --git a/setup.py b/setup.py
index 3ff1a1e4..acf090e3 100755
--- a/setup.py
+++ b/setup.py
@@ -5,6 +5,13 @@ from distutils.core import setup
 from distutils.extension import Extension
 import numpy as np
 
+run_cython = '--run-cython' in sys.argv
+if run_cython:
+    sys.argv.remove('--run-cython')
+    from Cython.Distutils import build_ext
+    cmdclass = {'build_ext': build_ext}
+else:
+    cmdclass = {}
 
 # This is an exact copy of the function from kwant/version.py.  We can't import
 # it here (because kwant is not yet built when this scipt is run), so we just
@@ -33,13 +40,6 @@ def get_version_from_git():
             version += '-dirty'
     return version
 
-try:
-    from Cython.Distutils import build_ext
-except ImportError:
-    use_cython = False
-else:
-    use_cython = True
-
 def get_static_version():
     try:
         with open('kwant/_static_version.py') as f:
@@ -66,21 +66,29 @@ else:
 # replacing ".pyx" with ".c" if Cython is not to be used.
 extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]],
                #  {"libraries" : ["scotch", "scotcherr"]}),
-               (["kwant.graph.core", ["kwant/graph/core.pyx"]], {}),
-               (["kwant.graph.utils", ["kwant/graph/utils.pyx"]], {}),
+               (["kwant.graph.core", ["kwant/graph/core.pyx"]],
+                {"depends" : ["kwant/graph/core.pxd", "kwant/graph/defs.h",
+                              "kwant/graph/defs.pxd"]}),
+               (["kwant.graph.utils", ["kwant/graph/utils.pyx"]],
+                {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd",
+                              "kwant/graph/core.pxd"]}),
                (["kwant.graph.slicer", ["kwant/graph/slicer.pyx",
                                         "kwant/graph/c_slicer/partitioner.cc",
                                         "kwant/graph/c_slicer/slicer.cc"]],
-                {}),
+                {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd",
+                              "kwant/graph/core.pxd",
+                              "kwant/graph/c_slicer.pxd",
+                              "kwant/graph/c_slicer/bucket_list.h",
+                              "kwant/graph/c_slicer/graphwrap.h",
+                              "kwant/graph/c_slicer/partitioner.h",
+                              "kwant/graph/c_slicer/slicer.h"]}),
                (["kwant.linalg.lapack", ["kwant/linalg/lapack.pyx"]],
-                {"libraries" : ["lapack", "blas"]}) ]
+                {"libraries" : ["lapack", "blas"],
+                 "depends" : ["kwant/linalg/f_lapack.pxd"]}) ]
 
-cmdclass = {}
 ext_modules = []
-include_dirs = [np.get_include()]
-
 for args, keywords in extensions:
-    if not use_cython:
+    if not run_cython:
         if 'language' in keywords:
             if keywords['language'] == 'c':
                 ext = '.c'
@@ -91,10 +99,34 @@ for args, keywords in extensions:
                 exit(1)
         else:
             ext = '.c'
-        args[1] = [s.replace('.pyx', ext) for s in args[1]]
+        pyx_files = []
+        cythonized_files = []
+        sources = []
+        for f in args[1]:
+            if f[-4:] == '.pyx':
+                pyx_files.append(f)
+                f = f[:-4] + ext
+                cythonized_files.append(f)
+            sources.append(f)
+        args[1] = sources
+
+        try:
+            cythonized_oldest = min(os.stat(f).st_mtime
+                                    for f in cythonized_files)
+        except OSError:
+            msg = "{0} is missing. Run `./setup.py --run-cython build'."
+            print >>sys.stderr, msg.format(f)
+            exit(1)
+        for f in pyx_files + keywords.get('depends', []):
+            if os.stat(f).st_mtime > cythonized_oldest:
+                msg = "{0} has been modified. " \
+                "Run `./setup.py --run-cython build'."
+                print >>sys.stderr, msg.format(f)
+                exit(1)
+
     ext_modules.append(Extension(*args, **keywords))
-if use_cython:
-    cmdclass.update({'build_ext': build_ext})
+
+include_dirs = [np.get_include()]
 
 setup(name='kwant',
       version=version,
-- 
GitLab