Skip to content

Commit cf2f525

Browse files
committed
[WORKSPACE, etc.] New repository rule to compute local Python repo.
This replaces the hard-coded `python.BUILD` BUILD file with an active step that runs the system's active Python interpreter in order to determine the system's Python installation's include paths.
1 parent 30dc04c commit cf2f525

File tree

6 files changed

+82
-117
lines changed

6 files changed

+82
-117
lines changed

.github/workflows/precommit.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
sudo apt-get install gettext python2-dev python3-dev libsdl2-dev libosmesa6-dev python-numpy-dev python3-numpy-dev python-pil python3-pil python-enum34
3939
sudo find /usr -type f -name Python.h -o -name arrayobject.h -o -name functional -o -name -filesystem
4040
sudo ln -s /usr/lib/llvm-10/include/c++/v1 /usr/include/c++/v1
41+
sed -i -e 's/py_version = "PY3"/py_version = "PY2AND3"/' WORKSPACE
4142
- name: build
4243
run: |
4344
bazel --bazelrc=.precommit.bazelrc build ${{matrix.cfg.config}} --copt=-Wno-sign-compare //...

BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ cc_binary(
10271027
],
10281028
deps = [
10291029
":dmlablib",
1030-
"@python_system//:python",
1030+
"@python_system//:python_headers",
10311031
],
10321032
)
10331033

WORKSPACE

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
workspace(name = "org_deepmind_lab")
22

33
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
4+
load("@//:python_system.bzl", "python_repo")
45

56
http_archive(
67
name = "com_google_googletest",
@@ -158,8 +159,7 @@ new_local_repository(
158159
path = "/usr",
159160
)
160161

161-
new_local_repository(
162+
python_repo(
162163
name = "python_system",
163-
build_file = "@//bazel:python.BUILD",
164-
path = "/",
164+
py_version = "PY3",
165165
)

bazel/python.BUILD

Lines changed: 0 additions & 58 deletions
This file was deleted.

docs/users/build.md

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ If Python 3 support is not required, omit the packages that mention `python3`.
6868

6969
3. [Clone or download *DeepMind Lab*](https://github.com/deepmind/lab).
7070

71-
4. If necessary, edit `python.BUILD` according to the [Python
72-
instructions](#python-dependencies) below.
73-
74-
5. Build *DeepMind Lab* and run a random agent. (Use the `-c opt` flag to enable
71+
4. Build *DeepMind Lab* and run a random agent. (Use the `-c opt` flag to enable
7572
optimizations.)
7673

7774
```shell
@@ -97,9 +94,9 @@ arguments. Run `bazel run :random_agent -- --help` to see those.
9794

9895
*DeepMind Lab* does not include every dependency hermetically. In particular,
9996
Python is not included, but instead it must already be installed on your system.
100-
This means that depending on the details of where that library is installed, you
101-
may need to adjust the Bazel build rules in
102-
[`python.BUILD`](../../bazel/python.BUILD) to locate it correctly.
97+
Our Bazel workspace includes a mechanism to discover the location of the
98+
system's Python paths automatically by running the `python2` and `python3`
99+
interpreters. Additionally, NumPy must be available on your system, too.
103100
104101
Bazel can build Python code using either Python 2 or Python 3. The default is
105102
Python 3, but each individual `py_binary` and `py_test` target can specify the
@@ -108,57 +105,10 @@ desired version using the
108105
argument. The build rules need to make the local installation path of correct
109106
version of Python available.
110107
111-
If you only intend to use one of the two versions (e.g. on an older system where
112-
Python 3 with NumPy is not available), you only need to provide paths for that
113-
version; however, the codebase includes tests that run under both Python 2 and
114-
Python 3.
115-
116108
The default build rules should work for Debian and Ubuntu. They use Bazel's
117109
[configurable attributes](https://docs.bazel.build/versions/master/be/common-definitions.html#configurable-attributes)
118110
to provide paths for Python 2 and Python 3, respectively, based on which version
119-
is required during a particular build. Note that paths in the build rules are
120-
relative to the root path specified in the [`WORKSPACE`](../../WORKSPACE) file
121-
(which is `"/usr"` by default).
122-
123-
Python requires two separate dependencies: The CPython extension API, and NumPy.
124-
If, say, NumPy is installed in a custom location, like it is on SUSE Linux and
125-
RedHat Linux, you need to add the files from that location and set an include
126-
search path accordingly. For example:
127-
128-
```python
129-
cc_library(
130-
name = "python",
131-
hdrs = select(
132-
{
133-
"@bazel_tools//tools/python:PY2": glob([
134-
"include/python2.7/*.h",
135-
"lib64/python2.7/site-packages/numpy/core/include/**/*.h",
136-
]),
137-
"@bazel_tools//tools/python:PY3": glob([
138-
"include/python3.6m/*.h",
139-
"lib64/python3.6/site-packages/numpy/core/include/**/*.h",
140-
]),
141-
},
142-
no_match_error = "Internal error, Python version should be one of PY2 or PY3",
143-
),
144-
includes = select(
145-
{
146-
"@bazel_tools//tools/python:PY2": [
147-
"include/python2.7",
148-
"lib64/python2.7/site-packages/numpy/core/include",
149-
],
150-
"@bazel_tools//tools/python:PY3": [
151-
"include/python3.6m",
152-
"lib64/python3.6/site-packages/numpy/core/include",
153-
],
154-
},
155-
no_match_error = "Internal error, Python version should be one of PY2 or PY3",
156-
),
157-
visibility = ["//visibility:public"],
158-
)
159-
```
160-
The outputs of `rpm -ql python` and `rpm -ql python-numpy-devel` might be
161-
helpful to find the right include directories on Red-Hat-like systems.
111+
is required during a particular build.
162112

163113
If you have installed NumPy locally via PIP and would like to use the *DeepMind
164114
Lab* PIP module, then you should build the module against the version of NumPy

python_system.bzl

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Copyright 2021 DeepMind Technologies Limited.
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation; either version 2 of the License, or
6+
# (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License along
14+
# with this program; if not, write to the Free Software Foundation, Inc.,
15+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16+
# ============================================================================
17+
18+
"""Generates a local repository that points at the system's Python installation."""
19+
20+
_BUILD_FILE = '''# Description:
21+
# Build rule for Python
22+
23+
exports_files(["defs.bzl"])
24+
25+
cc_library(
26+
name = "python_headers",
27+
hdrs = select({
28+
"@bazel_tools//tools/python:PY2": glob(["python2/**/*.h", "numpy2/**/*.h"]),
29+
"@bazel_tools//tools/python:PY3": glob(["python3/**/*.h", "numpy3/**/*.h"]),
30+
}),
31+
includes = select({
32+
"@bazel_tools//tools/python:PY2": ["python2", "numpy2"],
33+
"@bazel_tools//tools/python:PY3": ["python3", "numpy3"],
34+
}),
35+
visibility = ["//visibility:public"],
36+
)
37+
'''
38+
39+
_GET_PYTHON_INCLUDE_DIR = """
40+
import sys
41+
from distutils.sysconfig import get_python_inc
42+
from numpy import get_include
43+
sys.stdout.write("{}\\n{}\\n".format(get_python_inc(), get_include()))
44+
""".strip()
45+
46+
def _python_repo_impl(repository_ctx):
47+
"""Creates external/<reponame>/BUILD, a python3 symlink, and other files."""
48+
49+
repository_ctx.file("BUILD", _BUILD_FILE)
50+
51+
if repository_ctx.attr.py_version in ["PY2", "PY2AND3"]:
52+
result = repository_ctx.execute(["python2", "-c", _GET_PYTHON_INCLUDE_DIR])
53+
if result.return_code:
54+
fail("Failed to run local Python2 interpreter: %s" % result.stderr)
55+
pypath, nppath = result.stdout.splitlines()
56+
repository_ctx.symlink(pypath, "python2")
57+
repository_ctx.symlink(nppath, "numpy2")
58+
59+
if repository_ctx.attr.py_version in ["PY3", "PY2AND3"]:
60+
result = repository_ctx.execute(["python3", "-c", _GET_PYTHON_INCLUDE_DIR])
61+
if result.return_code:
62+
fail("Failed to run local Python3 interpreter: %s" % result.stderr)
63+
pypath, nppath = result.stdout.splitlines()
64+
repository_ctx.symlink(pypath, "python3")
65+
repository_ctx.symlink(nppath, "numpy3")
66+
67+
python_repo = repository_rule(
68+
implementation = _python_repo_impl,
69+
configure = True,
70+
local = True,
71+
attrs = {"py_version": attr.string(default = "PY2AND3", values = ["PY2", "PY3", "PY2AND3"])},
72+
)

0 commit comments

Comments
 (0)