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