• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Custom rules for gRPC Python"""
2
3# Adapted with modifications from
4# tensorflow/tensorflow/core/platform/default/build_config.bzl
5# Native Bazel rules don't exist yet to compile Cython code, but rules have
6# been written at cython/cython and tensorflow/tensorflow. We branch from
7# Tensorflow's version as it is more actively maintained and works for gRPC
8# Python's needs.
9def pyx_library(name, deps = [], py_deps = [], srcs = [], **kwargs):
10    """Compiles a group of .pyx / .pxd / .py files.
11
12    First runs Cython to create .cpp files for each input .pyx or .py + .pxd
13    pair. Then builds a shared object for each, passing "deps" to each cc_binary
14    rule (includes Python headers by default). Finally, creates a py_library rule
15    with the shared objects and any pure Python "srcs", with py_deps as its
16    dependencies; the shared objects can be imported like normal Python files.
17
18    Args:
19        name: Name for the rule.
20        deps: C/C++ dependencies of the Cython (e.g. Numpy headers).
21        py_deps: Pure Python dependencies of the final library.
22        srcs: .py, .pyx, or .pxd files to either compile or pass through.
23        **kwargs: Extra keyword arguments passed to the py_library.
24    """
25
26    # First filter out files that should be run compiled vs. passed through.
27    py_srcs = []
28    pyx_srcs = []
29    pxd_srcs = []
30    for src in srcs:
31        if src.endswith(".pyx") or (src.endswith(".py") and
32                                    src[:-3] + ".pxd" in srcs):
33            pyx_srcs.append(src)
34        elif src.endswith(".py"):
35            py_srcs.append(src)
36        else:
37            pxd_srcs.append(src)
38        if src.endswith("__init__.py"):
39            pxd_srcs.append(src)
40
41    # Invoke cython to produce the shared object libraries.
42    for filename in pyx_srcs:
43        native.genrule(
44            name = filename + "_cython_translation",
45            srcs = [filename],
46            outs = [filename.split(".")[0] + ".cpp"],
47            # Optionally use PYTHON_BIN_PATH on Linux platforms so that python 3
48            # works. Windows has issues with cython_binary so skip PYTHON_BIN_PATH.
49            cmd =
50                "PYTHONHASHSEED=0 $(location @cython//:cython_binary) --cplus $(SRCS) --output-file $(OUTS)",
51            tools = ["@cython//:cython_binary"] + pxd_srcs,
52        )
53
54    shared_objects = []
55    for src in pyx_srcs:
56        stem = src.split(".")[0]
57        shared_object_name = stem + ".so"
58        native.cc_binary(
59            name = shared_object_name,
60            srcs = [stem + ".cpp"],
61            deps = deps + ["@local_config_python//:python_headers"],
62            linkshared = 1,
63        )
64        shared_objects.append(shared_object_name)
65
66    data = shared_objects[:]
67    data += kwargs.pop("data", [])
68
69    # Now create a py_library with these shared objects as data.
70    native.py_library(
71        name = name,
72        srcs = py_srcs,
73        deps = py_deps,
74        srcs_version = "PY2AND3",
75        data = data,
76        **kwargs
77    )
78