##// END OF EJS Templates
merge: drop now-unused "abort" argument from hg.merge()...
merge: drop now-unused "abort" argument from hg.merge() Differential Revision: https://phab.mercurial-scm.org/D7997

File last commit:

r44605:5e84a96d default
r44639:bd4f666b default
Show More
make_cffi.py
228 lines | 6.9 KiB | text/x-python | PythonLexer
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435 # Copyright (c) 2016-present, Gregory Szorc
# All rights reserved.
#
# This software may be modified and distributed under the terms
# of the BSD license. See the LICENSE file for details.
from __future__ import absolute_import
import cffi
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 import distutils.ccompiler
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435 import os
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 import re
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 import subprocess
import tempfile
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
HERE = os.path.abspath(os.path.dirname(__file__))
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 SOURCES = [
"zstd/%s" % p
for p in (
"common/debug.c",
"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",
"compress/hist.c",
"compress/huf_compress.c",
"compress/zstd_compress.c",
"compress/zstd_compress_literals.c",
"compress/zstd_compress_sequences.c",
"compress/zstd_double_fast.c",
"compress/zstd_fast.c",
"compress/zstd_lazy.c",
"compress/zstd_ldm.c",
"compress/zstd_opt.c",
"compress/zstdmt_compress.c",
"decompress/huf_decompress.c",
"decompress/zstd_ddict.c",
"decompress/zstd_decompress.c",
"decompress/zstd_decompress_block.c",
"dictBuilder/cover.c",
"dictBuilder/fastcover.c",
"dictBuilder/divsufsort.c",
"dictBuilder/zdict.c",
)
]
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # Headers whose preprocessed output will be fed into cdef().
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 HEADERS = [
Gregory Szorc
python-zstandard: blacken at 80 characters...
r44605 os.path.join(HERE, "zstd", *p)
for p in (("zstd.h",), ("dictBuilder", "zdict.h"),)
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 ]
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 INCLUDE_DIRS = [
os.path.join(HERE, d)
for d in (
"zstd",
"zstd/common",
"zstd/compress",
"zstd/decompress",
"zstd/dictBuilder",
)
]
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 # 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.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if hasattr(compiler, "initialize"):
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 compiler.initialize()
# Distutils doesn't set compiler.preprocessor, so invoke the preprocessor
# manually.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if compiler.compiler_type == "unix":
args = list(compiler.executables["compiler"])
args.extend(
["-E", "-DZSTD_STATIC_LINKING_ONLY", "-DZDICT_STATIC_LINKING_ONLY",]
)
elif compiler.compiler_type == "msvc":
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 args = [compiler.cc]
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 args.extend(
["/EP", "/DZSTD_STATIC_LINKING_ONLY", "/DZDICT_STATIC_LINKING_ONLY",]
)
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 else:
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 raise Exception("unsupported compiler type: %s" % compiler.compiler_type)
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 def preprocess(path):
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 with open(path, "rb") as fh:
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 lines = []
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 it = iter(fh)
for l in it:
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # 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.
#
# The same things happens for including zstd.h, so give it the same
# treatment.
#
# We define ZSTD_STATIC_LINKING_ONLY, which is redundant with the inline
# #define in zstdmt_compress.h and results in a compiler warning. So drop
# the inline #define.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if l.startswith(
(
b"#include <stddef.h>",
b'#include "zstd.h"',
b"#define ZSTD_STATIC_LINKING_ONLY",
)
):
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 continue
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 # The preprocessor environment on Windows doesn't define include
# paths, so the #include of limits.h fails. We work around this
# by removing that import and defining INT_MAX ourselves. This is
# a bit hacky. But it gets the job done.
# TODO make limits.h work on Windows so we ensure INT_MAX is
# correct.
if l.startswith(b"#include <limits.h>"):
l = b"#define INT_MAX 2147483647\n"
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # ZSTDLIB_API may not be defined if we dropped zstd.h. It isn't
# important so just filter it out.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if l.startswith(b"ZSTDLIB_API"):
l = l[len(b"ZSTDLIB_API ") :]
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796
lines.append(l)
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 fd, input_file = tempfile.mkstemp(suffix=".h")
os.write(fd, b"".join(lines))
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 os.close(fd)
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 try:
Gregory Szorc
zstandard: vendor python-zstandard 0.12...
r43207 env = dict(os.environ)
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if getattr(compiler, "_paths", None):
env["PATH"] = compiler._paths
Gregory Szorc
python-zstandard: blacken at 80 characters...
r44605 process = subprocess.Popen(
args + [input_file], stdout=subprocess.PIPE, env=env
)
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 output = process.communicate()[0]
ret = process.poll()
if ret:
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 raise Exception("preprocessor exited with error")
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 return output
finally:
os.unlink(input_file)
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895
def normalize_output(output):
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 lines = []
for line in output.splitlines():
# CFFI's parser doesn't like __attribute__ on UNIX compilers.
if line.startswith(b'__attribute__ ((visibility ("default"))) '):
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 line = line[len(b'__attribute__ ((visibility ("default"))) ') :]
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if line.startswith(b"__attribute__((deprecated("):
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 continue
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 elif b"__declspec(deprecated(" in line:
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 continue
Gregory Szorc
zstd: vendor python-zstandard 0.6.0...
r30822 lines.append(line)
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 return b"\n".join(lines)
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435 ffi = cffi.FFI()
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 # zstd.h uses a possible undefined MIN(). Define it until
# https://github.com/facebook/zstd/issues/976 is fixed.
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # *_DISABLE_DEPRECATE_WARNINGS prevents the compiler from emitting a warning
# when cffi uses the function. Since we statically link against zstd, even
# if we use the deprecated functions it shouldn't be a huge problem.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 ffi.set_source(
"_zstd_cffi",
"""
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #define MIN(a,b) ((a)<(b) ? (a) : (b))
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435 #define ZSTD_STATIC_LINKING_ONLY
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #include <zstd.h>
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 #define ZDICT_STATIC_LINKING_ONLY
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 #define ZDICT_DISABLE_DEPRECATE_WARNINGS
Gregory Szorc
zstandard: vendor python-zstandard 0.9.0...
r37513 #include <zdict.h>
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 """,
sources=SOURCES,
include_dirs=INCLUDE_DIRS,
extra_compile_args=["-DZSTD_MULTITHREAD"],
)
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 DEFINE = re.compile(b"^\\#define ([a-zA-Z0-9_]+) ")
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895
sources = []
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # Feed normalized preprocessor output for headers into the cdef parser.
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 for header in HEADERS:
preprocessed = preprocess(header)
sources.append(normalize_output(preprocessed))
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # #define's are effectively erased as part of going through preprocessor.
# So perform a manual pass to re-add those to the cdef source.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 with open(header, "rb") as fh:
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 for line in fh:
line = line.strip()
m = DEFINE.match(line)
if not m:
continue
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if m.group(1) == b"ZSTD_STATIC_LINKING_ONLY":
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 continue
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 # The parser doesn't like some constants with complex values.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if m.group(1) in (b"ZSTD_LIB_VERSION", b"ZSTD_VERSION_STRING"):
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895 continue
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 # The ... is magic syntax by the cdef parser to resolve the
# value at compile time.
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 sources.append(m.group(0) + b" ...")
Gregory Szorc
zstd: vendor python-zstandard 0.7.0...
r30895
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 cdeflines = b"\n".join(sources).splitlines()
Gregory Szorc
zstd: vendor python-zstandard 0.8.0...
r31796 cdeflines = [l for l in cdeflines if l.strip()]
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 ffi.cdef(b"\n".join(cdeflines).decode("latin1"))
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435
Gregory Szorc
zstandard: vendor python-zstandard 0.13.0...
r44446 if __name__ == "__main__":
Gregory Szorc
zstd: vendor python-zstandard 0.5.0...
r30435 ffi.compile()