--- a/contrib/python-zstandard/make_cffi.py Thu Feb 09 21:44:32 2017 -0500
+++ b/contrib/python-zstandard/make_cffi.py Tue Feb 07 23:24:47 2017 -0800
@@ -9,6 +9,7 @@
import cffi
import distutils.ccompiler
import os
+import re
import subprocess
import tempfile
@@ -19,6 +20,8 @@
'common/entropy_common.c',
'common/error_private.c',
'common/fse_decompress.c',
+ 'common/pool.c',
+ 'common/threading.c',
'common/xxhash.c',
'common/zstd_common.c',
'compress/fse_compress.c',
@@ -26,10 +29,17 @@
'compress/zstd_compress.c',
'decompress/huf_decompress.c',
'decompress/zstd_decompress.c',
+ 'dictBuilder/cover.c',
'dictBuilder/divsufsort.c',
'dictBuilder/zdict.c',
)]
+HEADERS = [os.path.join(HERE, 'zstd', *p) for p in (
+ ('zstd.h',),
+ ('common', 'pool.h'),
+ ('dictBuilder', 'zdict.h'),
+)]
+
INCLUDE_DIRS = [os.path.join(HERE, d) for d in (
'zstd',
'zstd/common',
@@ -53,56 +63,92 @@
args.extend([
'-E',
'-DZSTD_STATIC_LINKING_ONLY',
+ '-DZDICT_STATIC_LINKING_ONLY',
])
elif compiler.compiler_type == 'msvc':
args = [compiler.cc]
args.extend([
'/EP',
'/DZSTD_STATIC_LINKING_ONLY',
+ '/DZDICT_STATIC_LINKING_ONLY',
])
else:
raise Exception('unsupported compiler type: %s' % compiler.compiler_type)
-# zstd.h includes <stddef.h>, which is also included by cffi's boilerplate.
-# This can lead to duplicate declarations. So we strip this include from the
-# preprocessor invocation.
+def preprocess(path):
+ # zstd.h includes <stddef.h>, which is also included by cffi's boilerplate.
+ # This can lead to duplicate declarations. So we strip this include from the
+ # preprocessor invocation.
+ with open(path, 'rb') as fh:
+ lines = [l for l in fh if not l.startswith(b'#include <stddef.h>')]
-with open(os.path.join(HERE, 'zstd', 'zstd.h'), 'rb') as fh:
- lines = [l for l in fh if not l.startswith(b'#include <stddef.h>')]
-
-fd, input_file = tempfile.mkstemp(suffix='.h')
-os.write(fd, b''.join(lines))
-os.close(fd)
+ fd, input_file = tempfile.mkstemp(suffix='.h')
+ os.write(fd, b''.join(lines))
+ os.close(fd)
-args.append(input_file)
+ try:
+ process = subprocess.Popen(args + [input_file], stdout=subprocess.PIPE)
+ output = process.communicate()[0]
+ ret = process.poll()
+ if ret:
+ raise Exception('preprocessor exited with error')
-try:
- process = subprocess.Popen(args, stdout=subprocess.PIPE)
- output = process.communicate()[0]
- ret = process.poll()
- if ret:
- raise Exception('preprocessor exited with error')
-finally:
- os.unlink(input_file)
+ return output
+ finally:
+ os.unlink(input_file)
-def normalize_output():
+
+def normalize_output(output):
lines = []
for line in output.splitlines():
# CFFI's parser doesn't like __attribute__ on UNIX compilers.
if line.startswith(b'__attribute__ ((visibility ("default"))) '):
line = line[len(b'__attribute__ ((visibility ("default"))) '):]
+ if line.startswith(b'__attribute__((deprecated('):
+ continue
+ elif b'__declspec(deprecated(' in line:
+ continue
+
lines.append(line)
return b'\n'.join(lines)
+
ffi = cffi.FFI()
ffi.set_source('_zstd_cffi', '''
+#include "mem.h"
#define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h"
+#define ZDICT_STATIC_LINKING_ONLY
+#include "pool.h"
+#include "zdict.h"
''', sources=SOURCES, include_dirs=INCLUDE_DIRS)
-ffi.cdef(normalize_output().decode('latin1'))
+DEFINE = re.compile(b'^\\#define ([a-zA-Z0-9_]+) ')
+
+sources = []
+
+for header in HEADERS:
+ preprocessed = preprocess(header)
+ sources.append(normalize_output(preprocessed))
+
+ # Do another pass over source and find constants that were preprocessed
+ # away.
+ with open(header, 'rb') as fh:
+ for line in fh:
+ line = line.strip()
+ m = DEFINE.match(line)
+ if not m:
+ continue
+
+ # The parser doesn't like some constants with complex values.
+ if m.group(1) in (b'ZSTD_LIB_VERSION', b'ZSTD_VERSION_STRING'):
+ continue
+
+ sources.append(m.group(0) + b' ...')
+
+ffi.cdef(u'\n'.join(s.decode('latin1') for s in sources))
if __name__ == '__main__':
ffi.compile()