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