Mercurial > public > mercurial-scm > hg-stable
diff contrib/python-zstandard/make_cffi.py @ 30822:b54a2984cdd4
zstd: vendor python-zstandard 0.6.0
Commit 63c68d6f5fc8de4afd9bde81b13b537beb4e47e8 from
https://github.com/indygreg/python-zstandard is imported without
modifications (other than removing unwanted files).
This includes minor performance and feature improvements. It also
changes the vendored zstd library from 1.1.1 to 1.1.2.
# no-check-commit
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 14 Jan 2017 19:41:43 -0800 |
parents | b86a448a2965 |
children | c32454d69b85 |
line wrap: on
line diff
--- a/contrib/python-zstandard/make_cffi.py Sat Jan 14 20:05:15 2017 +0530 +++ b/contrib/python-zstandard/make_cffi.py Sat Jan 14 19:41:43 2017 -0800 @@ -7,7 +7,10 @@ from __future__ import absolute_import import cffi +import distutils.ccompiler import os +import subprocess +import tempfile HERE = os.path.abspath(os.path.dirname(__file__)) @@ -20,10 +23,8 @@ 'common/zstd_common.c', 'compress/fse_compress.c', 'compress/huf_compress.c', - 'compress/zbuff_compress.c', 'compress/zstd_compress.c', 'decompress/huf_decompress.c', - 'decompress/zbuff_decompress.c', 'decompress/zstd_decompress.c', 'dictBuilder/divsufsort.c', 'dictBuilder/zdict.c', @@ -37,74 +38,71 @@ 'zstd/dictBuilder', )] +# cffi can't parse some of the primitives in zstd.h. So we invoke the +# preprocessor and feed its output into cffi. +compiler = distutils.ccompiler.new_compiler() + +# Needed for MSVC. +if hasattr(compiler, 'initialize'): + compiler.initialize() + +# Distutils doesn't set compiler.preprocessor, so invoke the preprocessor +# manually. +if compiler.compiler_type == 'unix': + args = list(compiler.executables['compiler']) + args.extend([ + '-E', + '-DZSTD_STATIC_LINKING_ONLY', + ]) +elif compiler.compiler_type == 'msvc': + args = [compiler.cc] + args.extend([ + '/EP', + '/DZSTD_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. + with open(os.path.join(HERE, 'zstd', 'zstd.h'), 'rb') as fh: - zstd_h = fh.read() + 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) + +args.append(input_file) + +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) + +def normalize_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"))) '):] + + lines.append(line) + + return b'\n'.join(lines) ffi = cffi.FFI() ffi.set_source('_zstd_cffi', ''' -/* needed for typedefs like U32 references in zstd.h */ -#include "mem.h" #define ZSTD_STATIC_LINKING_ONLY #include "zstd.h" -''', - sources=SOURCES, include_dirs=INCLUDE_DIRS) - -# Rather than define the API definitions from zstd.h inline, munge the -# source in a way that cdef() will accept. -lines = zstd_h.splitlines() -lines = [l.rstrip() for l in lines if l.strip()] - -# Strip preprocessor directives - they aren't important for our needs. -lines = [l for l in lines - if not l.startswith((b'#if', b'#else', b'#endif', b'#include'))] - -# Remove extern C block -lines = [l for l in lines if l not in (b'extern "C" {', b'}')] - -# The version #defines don't parse and aren't necessary. Strip them. -lines = [l for l in lines if not l.startswith(( - b'#define ZSTD_H_235446', - b'#define ZSTD_LIB_VERSION', - b'#define ZSTD_QUOTE', - b'#define ZSTD_EXPAND_AND_QUOTE', - b'#define ZSTD_VERSION_STRING', - b'#define ZSTD_VERSION_NUMBER'))] +''', sources=SOURCES, include_dirs=INCLUDE_DIRS) -# The C parser also doesn't like some constant defines referencing -# other constants. -# TODO we pick the 64-bit constants here. We should assert somewhere -# we're compiling for 64-bit. -def fix_constants(l): - if l.startswith(b'#define ZSTD_WINDOWLOG_MAX '): - return b'#define ZSTD_WINDOWLOG_MAX 27' - elif l.startswith(b'#define ZSTD_CHAINLOG_MAX '): - return b'#define ZSTD_CHAINLOG_MAX 28' - elif l.startswith(b'#define ZSTD_HASHLOG_MAX '): - return b'#define ZSTD_HASHLOG_MAX 27' - elif l.startswith(b'#define ZSTD_CHAINLOG_MAX '): - return b'#define ZSTD_CHAINLOG_MAX 28' - elif l.startswith(b'#define ZSTD_CHAINLOG_MIN '): - return b'#define ZSTD_CHAINLOG_MIN 6' - elif l.startswith(b'#define ZSTD_SEARCHLOG_MAX '): - return b'#define ZSTD_SEARCHLOG_MAX 26' - elif l.startswith(b'#define ZSTD_BLOCKSIZE_ABSOLUTEMAX '): - return b'#define ZSTD_BLOCKSIZE_ABSOLUTEMAX 131072' - else: - return l -lines = map(fix_constants, lines) - -# ZSTDLIB_API isn't handled correctly. Strip it. -lines = [l for l in lines if not l.startswith(b'# define ZSTDLIB_API')] -def strip_api(l): - if l.startswith(b'ZSTDLIB_API '): - return l[len(b'ZSTDLIB_API '):] - else: - return l -lines = map(strip_api, lines) - -source = b'\n'.join(lines) -ffi.cdef(source.decode('latin1')) - +ffi.cdef(normalize_output().decode('latin1')) if __name__ == '__main__': ffi.compile()