contrib/python-zstandard/make_cffi.py
changeset 30435 b86a448a2965
child 30822 b54a2984cdd4
equal deleted inserted replaced
30434:2e484bdea8c4 30435:b86a448a2965
       
     1 # Copyright (c) 2016-present, Gregory Szorc
       
     2 # All rights reserved.
       
     3 #
       
     4 # This software may be modified and distributed under the terms
       
     5 # of the BSD license. See the LICENSE file for details.
       
     6 
       
     7 from __future__ import absolute_import
       
     8 
       
     9 import cffi
       
    10 import os
       
    11 
       
    12 
       
    13 HERE = os.path.abspath(os.path.dirname(__file__))
       
    14 
       
    15 SOURCES = ['zstd/%s' % p for p in (
       
    16     'common/entropy_common.c',
       
    17     'common/error_private.c',
       
    18     'common/fse_decompress.c',
       
    19     'common/xxhash.c',
       
    20     'common/zstd_common.c',
       
    21     'compress/fse_compress.c',
       
    22     'compress/huf_compress.c',
       
    23     'compress/zbuff_compress.c',
       
    24     'compress/zstd_compress.c',
       
    25     'decompress/huf_decompress.c',
       
    26     'decompress/zbuff_decompress.c',
       
    27     'decompress/zstd_decompress.c',
       
    28     'dictBuilder/divsufsort.c',
       
    29     'dictBuilder/zdict.c',
       
    30 )]
       
    31 
       
    32 INCLUDE_DIRS = [os.path.join(HERE, d) for d in (
       
    33     'zstd',
       
    34     'zstd/common',
       
    35     'zstd/compress',
       
    36     'zstd/decompress',
       
    37     'zstd/dictBuilder',
       
    38 )]
       
    39 
       
    40 with open(os.path.join(HERE, 'zstd', 'zstd.h'), 'rb') as fh:
       
    41     zstd_h = fh.read()
       
    42 
       
    43 ffi = cffi.FFI()
       
    44 ffi.set_source('_zstd_cffi', '''
       
    45 /* needed for typedefs like U32 references in zstd.h */
       
    46 #include "mem.h"
       
    47 #define ZSTD_STATIC_LINKING_ONLY
       
    48 #include "zstd.h"
       
    49 ''',
       
    50     sources=SOURCES, include_dirs=INCLUDE_DIRS)
       
    51 
       
    52 # Rather than define the API definitions from zstd.h inline, munge the
       
    53 # source in a way that cdef() will accept.
       
    54 lines = zstd_h.splitlines()
       
    55 lines = [l.rstrip() for l in lines if l.strip()]
       
    56 
       
    57 # Strip preprocessor directives - they aren't important for our needs.
       
    58 lines = [l for l in lines
       
    59          if not l.startswith((b'#if', b'#else', b'#endif', b'#include'))]
       
    60 
       
    61 # Remove extern C block
       
    62 lines = [l for l in lines if l not in (b'extern "C" {', b'}')]
       
    63 
       
    64 # The version #defines don't parse and aren't necessary. Strip them.
       
    65 lines = [l for l in lines if not l.startswith((
       
    66     b'#define ZSTD_H_235446',
       
    67     b'#define ZSTD_LIB_VERSION',
       
    68     b'#define ZSTD_QUOTE',
       
    69     b'#define ZSTD_EXPAND_AND_QUOTE',
       
    70     b'#define ZSTD_VERSION_STRING',
       
    71     b'#define ZSTD_VERSION_NUMBER'))]
       
    72 
       
    73 # The C parser also doesn't like some constant defines referencing
       
    74 # other constants.
       
    75 # TODO we pick the 64-bit constants here. We should assert somewhere
       
    76 # we're compiling for 64-bit.
       
    77 def fix_constants(l):
       
    78     if l.startswith(b'#define ZSTD_WINDOWLOG_MAX '):
       
    79         return b'#define ZSTD_WINDOWLOG_MAX 27'
       
    80     elif l.startswith(b'#define ZSTD_CHAINLOG_MAX '):
       
    81         return b'#define ZSTD_CHAINLOG_MAX 28'
       
    82     elif l.startswith(b'#define ZSTD_HASHLOG_MAX '):
       
    83         return b'#define ZSTD_HASHLOG_MAX 27'
       
    84     elif l.startswith(b'#define ZSTD_CHAINLOG_MAX '):
       
    85         return b'#define ZSTD_CHAINLOG_MAX 28'
       
    86     elif l.startswith(b'#define ZSTD_CHAINLOG_MIN '):
       
    87         return b'#define ZSTD_CHAINLOG_MIN 6'
       
    88     elif l.startswith(b'#define ZSTD_SEARCHLOG_MAX '):
       
    89         return b'#define ZSTD_SEARCHLOG_MAX 26'
       
    90     elif l.startswith(b'#define ZSTD_BLOCKSIZE_ABSOLUTEMAX '):
       
    91         return b'#define ZSTD_BLOCKSIZE_ABSOLUTEMAX 131072'
       
    92     else:
       
    93         return l
       
    94 lines = map(fix_constants, lines)
       
    95 
       
    96 # ZSTDLIB_API isn't handled correctly. Strip it.
       
    97 lines = [l for l in lines if not l.startswith(b'#  define ZSTDLIB_API')]
       
    98 def strip_api(l):
       
    99     if l.startswith(b'ZSTDLIB_API '):
       
   100         return l[len(b'ZSTDLIB_API '):]
       
   101     else:
       
   102         return l
       
   103 lines = map(strip_api, lines)
       
   104 
       
   105 source = b'\n'.join(lines)
       
   106 ffi.cdef(source.decode('latin1'))
       
   107 
       
   108 
       
   109 if __name__ == '__main__':
       
   110     ffi.compile()