Permalink
Browse files

ENH: Use hashes of .pyx files to see whether re-compilation is needed…

… or not.
  • Loading branch information...
1 parent e7f0fe9 commit 57294c2ff9d468a1a8f42f97f9bc6778e0563c4c @stefanv stefanv committed Oct 27, 2011
Showing with 35 additions and 43 deletions.
  1. +2 −0 .gitignore
  2. +1 −1 MANIFEST.in
  3. +32 −42 skimage/_build.py
View
@@ -6,6 +6,8 @@
*.bak
*.c
*.new
+*.md5
+*.old
doc/source/api
doc/build
source/api
View
@@ -3,7 +3,7 @@ include setup*.py
include MANIFEST.in
include *.txt
include Makefile
-recursive-include skimage *.pyx *.pxd *.pxi *.py *.c *.h *.ini
+recursive-include skimage *.pyx *.pxd *.pxi *.py *.c *.h *.ini *.md5
recursive-include skimage/data *
include doc/Makefile
View
@@ -15,7 +15,7 @@ def cython(pyx_files, working_path=''):
"""
# Do not build cython files if target is clean
- if sys.argv[1] == 'clean':
+ if len(sys.argv) >= 2 and sys.argv[1] == 'clean':
return
try:
@@ -27,62 +27,52 @@ def cython(pyx_files, working_path=''):
% " ".join([f.replace('.pyx', '.c') for f in pyx_files]))
else:
for pyxfile in [os.path.join(working_path, f) for f in pyx_files]:
- # make a backup of the good c files
+
+ # if the .pyx file stayed the same, we don't need to recompile
+ if not _changed(pyxfile):
+ continue
+
c_file = pyxfile[:-4] + '.c'
- c_file_new = c_file + '.new'
# run cython compiler
- cmd = 'cython -o %s %s' % (c_file_new, pyxfile)
+ cmd = 'cython -o %s %s' % (c_file, pyxfile)
print(cmd)
if platform.system() == 'Windows':
status = subprocess.call(
[sys.executable,
os.path.join(os.path.dirname(sys.executable),
'Scripts', 'cython.py'),
- '-o', c_file_new, pyxfile],
+ '-o', c_file, pyxfile],
shell=True)
else:
- status = subprocess.call(['cython', '-o', c_file_new, pyxfile])
-
- # if the resulting file is small, cython compilation failed
- if status != 0 or os.path.getsize(c_file_new) < 100:
- print("Cython compilation of %s failed. Falling back " \
- "on pre-generated file." % os.path.basename(pyxfile))
- elif not same_cython(c_file_new, c_file):
- # if the generated .c file differs from the one provided,
- # use that one instead
- shutil.copy(c_file_new, c_file)
- try:
- os.remove(c_file_new)
- except OSError:
- pass
-
+ status = subprocess.call(['cython', '-o', c_file, pyxfile])
-def same_cython(f0, f1):
- '''Compare two Cython generated C-files, based on their md5-sum.
+def _md5sum(f):
+ m = hashlib.new('md5')
+ while True:
+ # Hash one 8096 byte block at a time
+ d = f.read(8096)
+ if not d:
+ break
+ m.update(d)
+ return m.hexdigest()
- Returns True if the files are identical, False if not. The first
- lines are skipped, due to the timestamp printed there.
+def _changed(filename):
+ """Compare the hash of a Cython file to the cached hash value on disk.
- '''
- def md5sum(f):
- m = hashlib.new('md5')
- while True:
- d = f.read(8096)
- if not d:
- break
- m.update(d)
- return m.hexdigest()
-
- if not (os.path.isfile(f0) and os.path.isfile(f1)):
- return False
-
- f0 = open(f0, 'rb')
- f0.readline()
+ """
+ filename_cache = filename + '.md5'
+
+ try:
+ md5_cached = open(filename_cache, 'rb').read()
+ except IOError:
+ md5_cached = '0'
- f1 = open(f1, 'rb')
- f1.readline()
+ with open(filename, 'rb') as f:
+ md5_new = _md5sum(f)
- return md5sum(f0) == md5sum(f1)
+ with open(filename_cache, 'wb') as cf:
+ cf.write(md5_new)
+ return md5_cached != md5_new

0 comments on commit 57294c2

Please sign in to comment.