1616import cffi
1717import packaging .tags
1818
19- HERE = os .path .abspath (os .path .dirname (__file__ ))
20-
21- SOURCES = [
22- "zstd/zstd.c" ,
23- ]
24-
25- # Headers whose preprocessed output will be fed into cdef().
26- HEADERS = [
27- os .path .join (HERE , "zstd" , p )
28- for p in ("zstd_errors.h" , "zstd.h" , "zdict.h" )
29- ]
30-
31- INCLUDE_DIRS = [
32- os .path .join (HERE , "zstd" ),
33- ]
34-
3519# cffi can't parse some of the primitives in zstd.h. So we invoke the
3620# preprocessor and feed its output into cffi.
3721compiler = distutils .ccompiler .new_compiler ()
@@ -168,21 +152,38 @@ def normalize_output(output):
168152 return b"\n " .join (lines )
169153
170154
171- # musl 1.1 doesn't define qsort_r. We need to force using the C90
172- # variant.
173- define_macros = []
174- for tag in packaging . tags . platform_tags ():
175- if tag . startswith ( "musllinux_1_1_" ):
176- define_macros . append (( "ZDICT_QSORT" , "ZDICT_QSORT_C90" ))
155+ def get_ffi ( system_zstd = False ):
156+ here = os . path . abspath ( os . path . dirname ( __file__ ))
157+
158+ zstd_sources = [
159+ "zstd/zstd.c" ,
160+ ]
177161
162+ # Headers whose preprocessed output will be fed into cdef().
163+ headers = [
164+ os .path .join (here , "zstd" , p )
165+ for p in ("zstd_errors.h" , "zstd.h" , "zdict.h" )
166+ ]
178167
179- ffi = cffi .FFI ()
180- # *_DISABLE_DEPRECATE_WARNINGS prevents the compiler from emitting a warning
181- # when cffi uses the function. Since we statically link against zstd, even
182- # if we use the deprecated functions it shouldn't be a huge problem.
183- ffi .set_source (
184- "zstandard._cffi" ,
185- """
168+ include_dirs = [
169+ os .path .join (here , "zstd" ),
170+ ]
171+
172+ # musl 1.1 doesn't define qsort_r. We need to force using the C90
173+ # variant.
174+ define_macros = []
175+ for tag in packaging .tags .platform_tags ():
176+ if tag .startswith ("musllinux_1_1_" ):
177+ define_macros .append (("ZDICT_QSORT" , "ZDICT_QSORT_C90" ))
178+
179+
180+ ffi = cffi .FFI ()
181+ # *_DISABLE_DEPRECATE_WARNINGS prevents the compiler from emitting a warning
182+ # when cffi uses the function. Since we statically link against zstd, even
183+ # if we use the deprecated functions it shouldn't be a huge problem.
184+ ffi .set_source (
185+ "zstandard._cffi" ,
186+ """
186187#define ZSTD_STATIC_LINKING_ONLY
187188#define ZSTD_DISABLE_DEPRECATE_WARNINGS
188189#include <zstd_errors.h>
@@ -191,48 +192,50 @@ def normalize_output(output):
191192#define ZDICT_DISABLE_DEPRECATE_WARNINGS
192193#include <zdict.h>
193194""" ,
194- sources = SOURCES ,
195- include_dirs = INCLUDE_DIRS ,
196- define_macros = define_macros ,
197- )
198-
199- DEFINE = re .compile (rb"^#define\s+([a-zA-Z0-9_]+)\s+(\S+)" )
200-
201- sources = []
202-
203- # Feed normalized preprocessor output for headers into the cdef parser.
204- for header in HEADERS :
205- preprocessed = preprocess (header )
206- sources .append (normalize_output (preprocessed ))
207-
208- # #define's are effectively erased as part of going through preprocessor.
209- # So perform a manual pass to re-add those to the cdef source.
210- with open (header , "rb" ) as fh :
211- for line in fh :
212- line = line .strip ()
213- m = DEFINE .match (line )
214- if not m :
215- continue
195+ sources = zstd_sources ,
196+ include_dirs = include_dirs ,
197+ define_macros = define_macros ,
198+ )
216199
217- if m .group (1 ) == b"ZSTD_STATIC_LINKING_ONLY" :
218- continue
200+ define = re .compile (rb"^#define\s+([a-zA-Z0-9_]+)\s+(\S+)" )
219201
220- # The parser doesn't like some constants with complex values.
221- if m .group (1 ) in (b"ZSTD_LIB_VERSION" , b"ZSTD_VERSION_STRING" ):
222- continue
202+ sources = []
223203
224- # These defines create aliases from old (camelCase) type names
225- # to the new PascalCase names, which breaks CFFI.
226- if m .group (1 ).lower () == m .group (2 ).lower ():
227- continue
204+ # Feed normalized preprocessor output for headers into the cdef parser.
205+ for header in headers :
206+ preprocessed = preprocess (header )
207+ sources .append (normalize_output (preprocessed ))
208+
209+ # #define's are effectively erased as part of going through preprocessor.
210+ # So perform a manual pass to re-add those to the cdef source.
211+ with open (header , "rb" ) as fh :
212+ for line in fh :
213+ line = line .strip ()
214+ m = define .match (line )
215+ if not m :
216+ continue
217+
218+ if m .group (1 ) == b"ZSTD_STATIC_LINKING_ONLY" :
219+ continue
220+
221+ # The parser doesn't like some constants with complex values.
222+ if m .group (1 ) in (b"ZSTD_LIB_VERSION" , b"ZSTD_VERSION_STRING" ):
223+ continue
224+
225+ # These defines create aliases from old (camelCase) type names
226+ # to the new PascalCase names, which breaks CFFI.
227+ if m .group (1 ).lower () == m .group (2 ).lower ():
228+ continue
229+
230+ # The ... is magic syntax by the cdef parser to resolve the
231+ # value at compile time.
232+ sources .append (b"#define " + m .group (1 ) + b" ..." )
228233
229- # The ... is magic syntax by the cdef parser to resolve the
230- # value at compile time.
231- sources .append (b"#define " + m .group (1 ) + b" ..." )
234+ cdeflines = b"\n " .join (sources ).splitlines ()
235+ cdeflines = [line for line in cdeflines if line .strip ()]
236+ ffi .cdef (b"\n " .join (cdeflines ).decode ("latin1" ))
237+ return ffi
232238
233- cdeflines = b"\n " .join (sources ).splitlines ()
234- cdeflines = [line for line in cdeflines if line .strip ()]
235- ffi .cdef (b"\n " .join (cdeflines ).decode ("latin1" ))
236239
237240if __name__ == "__main__" :
238- ffi .compile ()
241+ get_ffi () .compile ()
0 commit comments