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
84
85
86
| | import distutils.ccompiler
import distutils.log
import distutils.sysconfig
import os
import shutil
import tempfile
import cffi
# Also look in these directories for include files, i.e. notmuch.h (-I)
INCLUDE_DIRS = ["../../lib"]
# Also look in these directories for libraries, i.e. libnotmuch.so.5 (-L)
LIBRARY_DIRS = ["../../lib"]
# Add extra linker flags, e.g. -Wl,--enable-new-dtags,-R/path/to/notmuch/libdir
EXTRA_LINK_ARGS = ["-Wl,--enable-new-dtags,-R/home/flub/Projects/notmuch/lib"]
def extract_functions():
"""Extract the function definitions from notmuch.h.
This creates a .h file with a single `#include <notmuch.h>` line
in it. It then runs the C preprocessor with the PY_CFFI symbol
defined to create an output file which contains all function
definitions found in `notmuch.h`.
"""
distutils.log.set_verbosity(distutils.log.INFO)
cc = distutils.ccompiler.new_compiler(force=True)
distutils.sysconfig.customize_compiler(cc)
tmpdir = tempfile.mkdtemp()
try:
src_name = os.path.join(tmpdir, "include.h")
dst_name = os.path.join(tmpdir, "expanded.h")
with open(src_name, "w") as src_fp:
src_fp.write("#include <notmuch.h>")
cc.preprocess(
source=src_name,
output_file=dst_name,
include_dirs=INCLUDE_DIRS,
macros=[("PY_CFFI", "1")],
)
with open(dst_name, "r") as dst_fp:
return dst_fp.read()
finally:
shutil.rmtree(tmpdir)
ffibuilder = cffi.FFI()
ffibuilder.set_source(
"notmuch2._capi",
r"""
#include <stdlib.h>
#include <time.h>
#include <notmuch.h>
#if LIBNOTMUCH_MAJOR_VERSION < 5
#error libnotmuch version not supported by notmuch2 python bindings
#endif
#if LIBNOTMUCH_MINOR_VERSION < 1
#ERROR libnotmuch version < 5.1 not supported
#endif
""",
include_dirs=INCLUDE_DIRS,
library_dirs=LIBRARY_DIRS,
extra_link_args=EXTRA_LINK_ARGS,
libraries=["notmuch"],
)
ffibuilder.cdef(
r"""
void free(void *ptr);
typedef int... time_t;
#define LIBNOTMUCH_MAJOR_VERSION ...
#define LIBNOTMUCH_MINOR_VERSION ...
#define LIBNOTMUCH_MICRO_VERSION ...
#define NOTMUCH_TAG_MAX ...
"""
)
ffibuilder.cdef(extract_functions())
if __name__ == "__main__":
ffibuilder.compile(verbose=True)
|