• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Project overview
2
3## Title
4
5Enable Building of gRPC Python with Bazel
6
7## Overview
8
9gRPC Python currently has a constellation of scripts written to build the
10project, but it has a lot of limitations in terms of speed and maintainability.
11[Bazel](https://bazel.build/) is the open-sourced variant of Google's internal
12system, Blaze, which is an ideal replacement for building such projects in a
13fast and declarative fashion. But Bazel in itself is still in active
14development, especially in terms of Python (amongst a few other languages).
15
16The project aimed to fill this gap and build gRPC Python with Bazel.
17
18[Project page](https://summerofcode.withgoogle.com/projects/#6482576244473856)
19
20[Link to proposal](https://storage.googleapis.com/summerofcode-prod.appspot.com/gsoc/core_project/doc/5316764725411840_1522049732_Naresh_Ramesh_-_GSoC_proposal.pdf)
21
22## Thoughts and challenges
23
24### State of Bazel for Python
25
26Although previously speculated, the project didn't require any contributions
27directly to [bazelbuild/bazel](https://github.com/bazelbuild/bazel). The Bazel
28rules for Python are currently being separated out into their own repo at
29[bazelbuild/rules_python](https://github.com/bazelbuild/rules_python/).
30
31Bazel is [still very much in active development for
32Python](https://groups.google.com/forum/#!topic/bazel-sig-python/iQjV9sfSufw)
33though. There's still challenges when it comes to building for Python 2 vs 3.
34Using pip packages is still in experimental. Bazel Python support is currently
35distributed across these two repositories and is yet to begin migration to one
36place (which will be
37[bazelbuild/rules_python](https://github.com/bazelbuild/rules_python/)).
38
39Bazel's roadmap for Python is publicly available [here as a Google
40doc](https://docs.google.com/document/d/1A6J3j3y1SQ0HliS86_mZBnB5UeBe7vExWL2Ryd_EONI/edit).
41
42### Cross collaboration between projects
43
44Cross contribution surprisingly came up because of building protobuf sources
45for Python, which is still not natively supported by Bazel. An existing
46repository, [pubref/rules_protobuf](https://github.com/pubref/rules_protobuf),
47which was maintained by an independent maintainer (i.e. not a part of Bazel)
48helped solve this problem, but had [one major blocking
49issue](https://github.com/pubref/rules_protobuf/issues/233) and could not be
50resolved at the source. But [a solution to the
51issue](https://github.com/pubref/rules_protobuf/pull/196) was proposed by user
52dududko, which was not merged because of failing golang tests but worked well
53for Python. Hence, a fork of this repo was made and is to be used with gRPC
54until the solution can be merged back at the source.
55
56### Building Cython code
57
58Building Cython code is still not supported by Bazel, but the team at
59[cython/cython](https://github.com/cython/cython) have added support for Bazel
60on their side. The way it works is by including Cython as a third-party Bazel
61dependency and using custom Bazel rules for building our Cython code using the
62binary within the dependency.
63
64### Packaging Python code using Bazel
65
66pip and PyPI still remain the de-facto standard for distributing Python
67packages. Although Bazel is pretty versatile and is amazing for it's
68reproducible and incremental build capabilities, these can only be still used
69by the contributors and developers for building and testing the gRPC code. But
70there's no way yet to build Python packages for distribution.
71
72### Building gRPC Python with Bazel on Kokoro (internal CI)
73
74Integration with the internal CI was one of the areas that highlighted how
75simple Bazel can be to use. gRPC was already using a dockerized Bazel setup to
76build some of it's core code (but not as the primary build setup). Adding a new
77job on the internal CI ended up being as simple as creating a new shell script
78to install the required dependencies (which were python-dev and Bazel) and a
79new configuration file which pointed to the subdirectiory (src/python) under
80which to look for targets and run the tests accordingly.
81
82### Handling imports in Python code
83
84When writing Python packages, imports in nested modules are typically made
85relative to the package root. But because of the way Bazel works, these paths
86wouldn't make sense from the Workspace root. So, the folks at Bazel have added
87a nifty `imports` parameter to all the Python rules which lets us specify for
88each target, which path to consider as the root. This parameter allows for
89relative paths like `imports = ["../",]`.
90
91### Fetching Python headers for Cython code to use
92
93Cython code makes use of `Python.h`, which pulls in the Python API for C
94extension modules to use, but it's location depending on the Python version and
95operating system the code is building on. To make this easier, the folks at
96Tensorflow wrote [repository rules for Python
97autoconfiguration](https://github.com/tensorflow/tensorflow/tree/e447ae4759317156d31a9421290716f0ffbffcd8/third_party/py).
98This has been [adapted with some some
99modifications](https://github.com/grpc/grpc/pull/15992) for use in gRPC Python
100as well.
101
102## How to use
103
104All the Bazel tests for gRPC Python can be run using a single command:
105
106```bash
107bazel test --spawn_strategy=standalone --genrule_strategy=standalone //src/python/...
108```
109
110If any specific test is to be run, like say `LoggingPoolTest` (which is present
111in
112`src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py`),
113the command to run would be:
114
115```bash
116bazel test --spawn_strategy=standalone --genrule_strategy=standalone //src/python/grpcio_tests/tests/unit/framework/foundation:logging_pool_test
117```
118
119where, `logging_pool_test` is the name of the Bazel target for this test.
120
121Similarly, to run a particular method, use:
122
123```bash
124bazel test --spawn_strategy=standalone --genrule_strategy=standalone //src/python/grpcio_tests/tests/unit/_rpc_test --test_arg=RPCTest.testUnrecognizedMethod
125```
126
127## Useful Bazel flags
128
129- Use `bazel build` with a `-s` flag to see the logs being printed out to
130    standard output while building.
131- Similarly, use `bazel test` with a `--test_output=streamed` to see the the
132    test logs while testing. Something to know while using this flag is that all
133    tests will be run locally, without sharding, one at a time.
134
135## Contributions
136
137### Related to the project
138
139- [435c6f8](https://github.com/grpc/grpc/commit/435c6f8d1e53783ec049b3482445813afd8bc514)
140    Update grpc_gevent cython files to include .pxi
141- [74426fd](https://github.com/grpc/grpc/commit/74426fd2164c51d6754732ebe372133c19ba718c)
142    Add gevent_util.h to grpc_base_c Bazel target
143- [b6518af](https://github.com/grpc/grpc/commit/b6518afdd610f0115b42aee1ffc71520c6b0d6b1)
144    Upgrade Bazel to 0.15.0
145- [ebcf04d](https://github.com/grpc/grpc/commit/ebcf04d075333c42979536c5dd2091d363f67e5a)
146    Kokoro setup for building gRPC Python with Bazel
147- [3af1aaa](https://github.com/grpc/grpc/commit/3af1aaadabf49bc6274711a11f81627c0f351a9a)
148    Basic setup to build gRPC Python with Bazel
149- [11f199e](https://github.com/grpc/grpc/commit/11f199e34dc416a2bd8b56391b242a867bedade4)
150    Workspace changes to build gRPC Python with Bazel
151- [848fd9d](https://github.com/grpc/grpc/commit/848fd9d75f6df10f00e8328ff052c0237b3002ab)
152    Minimal Bazel BUILD files for grpcio Python
153
154### Other contibutions
155
156- [89ce16b](https://github.com/grpc/grpc/commit/89ce16b6daaad4caeb1c9ba670c6c4b62ea1a93c)
157    Update Dockerfiles for python artifacts to use latest git version
158- [32f7c48](https://github.com/grpc/grpc/commit/32f7c48dad71cac7af652bf994ab1dde3ddb0607)
159    Revert removals from python artifact dockerfiles
160- [712eb9f](https://github.com/grpc/grpc/commit/712eb9ff91cde66af94e8381ec01ad512ed6d03c)
161    Make logging after success in jobset more apparent
162- [c6e4372](https://github.com/grpc/grpc/commit/c6e4372f8a93bb0eb996b5f202465785422290f2)
163    Create README for gRPC Python reflection package
164- [2e113ca](https://github.com/grpc/grpc/commit/2e113ca6b2cc31aa8a9687d40ee1bd759381654f)
165    Update logging in Python to use module-level logger
166
167### Pending PRs
168
169- BUILD files for all tests in
170    [tests.json](https://github.com/ghostwriternr/grpc/blob/70c8a58b2918a5369905e5a203d7ce7897b6207e/src/python/grpcio_tests/tests/tests.json).
171- BUILD files for gRPC testing, gRPC health checking, gRPC reflection.
172- (Yet to complete) BUILD files for grpcio_tools. One test depends on this.
173
174## Known issues
175
176- [grpc/grpc #16336](https://github.com/grpc/grpc/issues/16336) RuntimeError
177    for `_reconnect_test` Python unit test with Bazel
178- Some tests in Bazel pass despite throwing an exception. Example:
179    `testAbortedStreamStream` in
180    `src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py`.
181- [#14557](https://github.com/grpc/grpc/pull/14557) introduced a minor bug
182    where the module level loggers don't initialize a default logging handler.
183- Sanity test doesn't make sense in the context of Bazel, and thus fails.
184- There are some issues with Python2 vs Python3. Specifically,
185  - On some machines, “cygrpc.so: undefined symbol: _Py_FalseStruct” error
186    shows up. This is because of incorrect Python version being used to build
187    Cython.
188  - Some external packages like enum34 throw errors when used with Python 3 and
189    some extra packages are currently installed as Python version in current
190    build scripts. For now, the extra packages are added to a
191    `requirements.bazel.txt` file in the repository root.
192