-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathffi-builder.py
83 lines (65 loc) · 2.48 KB
/
ffi-builder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""
FFI builder module for minpack for usage from meson and from setup.py.
Since meson has the full knowledge about the build, it will handle
the generation of the C definitions in the meson.build file rather
than in the FFI builder. This allows to correctly keep track of
dependencies and updates in the build process.
For setup.py we have to do the preprocessing ourselves here, this
requires us to use the C compiler to preprocess the header file
of minpack because the CFFI C parser cannot handle certain C
preprocessor constructs. Also, we cannot rely on an external build
system fixing dependencies for us and therefore have to find those
ourselves using pkg-config.
"""
import os
import cffi
library = "minpack"
include_header = '#include "minpack.h"'
prefix_var = "MINPACK_PREFIX"
if prefix_var not in os.environ:
prefix_var = "CONDA_PREFIX"
if __name__ == "__main__":
import sys
kwargs = dict(libraries=[library])
header_file = sys.argv[1]
module_name = sys.argv[2]
with open(header_file) as f:
cdefs = f.read()
else:
import subprocess
try:
import pkgconfig
if not pkgconfig.exists(library):
raise ModuleNotFoundError("Unable to find pkg-config package 'minpack'")
if pkgconfig.installed(library, "< 2.0.0"):
raise Exception(
"Installed 'minpack' version is too old, 2.0.0 or newer is required"
)
kwargs = pkgconfig.parse(library)
cflags = pkgconfig.cflags(library).split()
except ModuleNotFoundError:
kwargs = dict(libraries=[library])
cflags = []
if prefix_var in os.environ:
prefix = os.environ[prefix_var]
kwargs.update(
include_dirs=[os.path.join(prefix, "include")],
library_dirs=[os.path.join(prefix, "lib")],
runtime_library_dirs=[os.path.join(prefix, "lib")],
)
cflags.append("-I" + os.path.join(prefix, "include"))
cc = os.environ["CC"] if "CC" in os.environ else "cc"
module_name = "minpack._libminpack"
p = subprocess.Popen(
[cc, *cflags, "-DMINPACK_CFFI=1", "-E", "-"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
out, err = p.communicate(include_header.encode())
cdefs = out.decode()
ffibuilder = cffi.FFI()
ffibuilder.set_source(module_name, include_header, **kwargs)
ffibuilder.cdef(cdefs)
if __name__ == "__main__":
ffibuilder.distutils_extension(".")