Skip to content

Commit 8e0d6f1

Browse files
Automated rollback of change 153736477
Change: 153825726
1 parent 858e0af commit 8e0d6f1

8 files changed

Lines changed: 274 additions & 102 deletions

File tree

configure

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ while true; do
8686
PYTHON_BIN_PATH=""
8787
# Retry
8888
done
89+
export PYTHON_BIN_PATH
90+
write_action_env_to_bazelrc "PYTHON_BIN_PATH" "$PYTHON_BIN_PATH"
91+
# TODO(ngiraldo): allow the user to optionally set PYTHON_INCLUDE_PATH and NUMPY_INCLUDE_PATH
8992

9093
## Set up MKL related environment settings
9194
if false; then # Disable building with MKL for now
@@ -243,7 +246,7 @@ fi
243246

244247

245248
# Invoke python_config and set up symlinks to python includes
246-
./util/python/python_config.sh --setup "$PYTHON_BIN_PATH"
249+
./util/python/python_config.sh "$PYTHON_BIN_PATH"
247250

248251
# Append CC optimization flags to bazel.rc
249252
echo >> tools/bazel.rc

tensorflow/workspace.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ load("//third_party/sycl:sycl_configure.bzl", "sycl_configure")
55
load("@io_bazel_rules_closure//closure/private:java_import_external.bzl", "java_import_external")
66
load("@io_bazel_rules_closure//closure:defs.bzl", "filegroup_external")
77
load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles_external")
8+
load("//third_party/py:python_configure.bzl", "python_configure")
89

910

1011
# Parse the bazel version string from `native.bazel_version`.
@@ -119,6 +120,7 @@ def tf_workspace(path_prefix="", tf_repo_name=""):
119120
check_version("0.4.5")
120121
cuda_configure(name="local_config_cuda")
121122
sycl_configure(name="local_config_sycl")
123+
python_configure(name="local_config_python")
122124
if path_prefix:
123125
print("path_prefix was specified to tf_workspace but is no longer used " +
124126
"and will be removed in the future.")

third_party/py/BUILD

Whitespace-only changes.

third_party/py/BUILD.tpl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
licenses(["restricted"])
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
cc_library(
6+
name = "python_headers",
7+
hdrs = select({
8+
"windows" : [
9+
"python_include_windows",
10+
],
11+
"//conditions:default" : [
12+
"python_include",
13+
],
14+
}),
15+
includes = select({
16+
"windows" : [
17+
"python_include_windows",
18+
],
19+
"//conditions:default" : [
20+
"python_include",
21+
],
22+
}),
23+
)
24+
25+
cc_library(
26+
name = "numpy_headers",
27+
hdrs = select({
28+
"windows" : [
29+
"numpy_include_windows",
30+
],
31+
"//conditions:default" : [
32+
"numpy_include",
33+
],
34+
}),
35+
includes = select({
36+
"windows" : [
37+
"numpy_include_windows",
38+
],
39+
"//conditions:default" : [
40+
"numpy_include",
41+
],
42+
}),
43+
)
44+
45+
config_setting(
46+
name = "windows",
47+
values = {"cpu": "x64_windows"},
48+
visibility = ["//visibility:public"],
49+
)
50+
51+
%{PYTHON_INCLUDE_GENRULE}
52+
53+
%{NUMPY_INCLUDE_GENRULE}

third_party/py/numpy/BUILD

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ py_library(
88
srcs_version = "PY2AND3",
99
)
1010

11-
cc_library(
11+
alias(
1212
name = "headers",
13-
hdrs = glob(["numpy_include/**/*.h"]),
14-
data = ["//util/python:python_checked"],
15-
includes = ["numpy_include"],
13+
actual = "@local_config_python//:numpy_headers",
1614
)
1715

1816
genrule(
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# -*- Python -*-
2+
"""Repository rule for Python autoconfiguration.
3+
4+
`python_configure` depends on the following environment variables:
5+
6+
* `NUMPY_INCLUDE_PATH`: Location of Numpy libraries.
7+
* `PYTHON_BIN_PATH`: location of python binary.
8+
* `PYTHON_INCLUDE_PATH`: Location of python binaries.
9+
"""
10+
11+
_NUMPY_INCLUDE_PATH = "NUMPY_INCLUDE_PATH"
12+
_PYTHON_BIN_PATH = "PYTHON_BIN_PATH"
13+
_PYTHON_INCLUDE_PATH = "PYTHON_INCLUDE_PATH"
14+
15+
16+
def _tpl(repository_ctx, tpl, substitutions={}, out=None):
17+
if not out:
18+
out = tpl
19+
repository_ctx.template(
20+
out,
21+
Label("//third_party/py:%s.tpl" % tpl),
22+
substitutions)
23+
24+
25+
def _python_configure_warning(msg):
26+
"""Output warning message during auto configuration."""
27+
yellow = "\033[1;33m"
28+
no_color = "\033[0m"
29+
print("\n%sPython Configuration Warning:%s %s\n" % (yellow, no_color, msg))
30+
31+
32+
def _python_configure_fail(msg):
33+
"""Output failure message when auto configuration fails."""
34+
red = "\033[0;31m"
35+
no_color = "\033[0m"
36+
fail("\n%sPython Configuration Error:%s %s\n" % (red, no_color, msg))
37+
38+
39+
def _get_env_var(repository_ctx, name, default = None, enable_warning = True):
40+
"""Find an environment variable in system path."""
41+
if name in repository_ctx.os.environ:
42+
return repository_ctx.os.environ[name]
43+
if default != None:
44+
if enable_warning:
45+
_python_configure_warning(
46+
"'%s' environment variable is not set, using '%s' as default" % (name, default))
47+
return default
48+
_python_configure_fail("'%s' environment variable is not set" % name)
49+
50+
51+
def _is_windows(repository_ctx):
52+
"""Returns true if the host operating system is windows."""
53+
os_name = repository_ctx.os.name.lower()
54+
if os_name.find("windows") != -1:
55+
return True
56+
return False
57+
58+
59+
def _symlink_genrule_for_dir(repository_ctx, src_dir, dest_dir, genrule_name):
60+
"""returns a genrule to symlink all files in a directory."""
61+
# Get the list of files under this directory
62+
find_result = None
63+
if _is_windows(repository_ctx):
64+
find_result = repository_ctx.execute([
65+
"dir", src_dir, "/b", "/s", "/a-d",
66+
])
67+
else:
68+
find_result = repository_ctx.execute([
69+
"find", src_dir, "-follow", "-type", "f",
70+
])
71+
# Create a list with the src_dir stripped to use for outputs.
72+
dest_files = find_result.stdout.replace(src_dir, '').splitlines()
73+
src_files = find_result.stdout.splitlines()
74+
command = []
75+
command_windows = []
76+
outs = []
77+
outs_windows = []
78+
for i in range(len(dest_files)):
79+
if dest_files[i] != "":
80+
command.append('ln -s ' + src_files[i] + ' $(@D)/' +
81+
dest_dir + dest_files[i])
82+
# ln -sf is actually implemented as copying in msys since creating
83+
# symbolic links is privileged on Windows. But copying is too slow, so
84+
# invoke mklink to create junctions on Windows.
85+
command_windows.append('mklink /J ' + src_files[i] + ' $(@D)/' +
86+
dest_dir + dest_files[i])
87+
outs.append(' "' + dest_dir + dest_files[i] + '",')
88+
outs_windows.append(' "' + dest_dir + '_windows' +
89+
dest_files[i] + '",')
90+
genrule = _genrule(src_dir, genrule_name, ' && '.join(command),
91+
'\n'.join(outs))
92+
genrule_windows = _genrule(src_dir, genrule_name + '_windows',
93+
"cmd /c \"" + ' && '.join(command_windows) + "\"",
94+
'\n'.join(outs_windows))
95+
return genrule + '\n' + genrule_windows
96+
97+
98+
def _genrule(src_dir, genrule_name, command, outs):
99+
"""Returns a string with a genrule.
100+
101+
Genrule executes the given command and produces the given outputs.
102+
"""
103+
return (
104+
'genrule(\n' +
105+
' name = "' +
106+
genrule_name + '",\n' +
107+
' outs = [\n' +
108+
outs +
109+
' ],\n' +
110+
' cmd = """\n' +
111+
command +
112+
' """,\n' +
113+
')\n'
114+
)
115+
116+
117+
def _check_python_bin(repository_ctx, python_bin):
118+
"""Checks the python bin path."""
119+
cmd = '[[ -x "%s" ]] && [[ ! -d "%s" ]]' % (python_bin, python_bin)
120+
result = repository_ctx.execute(["bash", "-c", cmd])
121+
if result.return_code == 1:
122+
_python_configure_fail(
123+
"PYTHON_BIN_PATH is not executable. Is it the python binary?")
124+
125+
126+
def _get_python_include(repository_ctx, python_bin):
127+
"""Gets the python include path."""
128+
result = repository_ctx.execute([python_bin, "-c",
129+
'from __future__ import print_function;' +
130+
'from distutils import sysconfig;' +
131+
'print(sysconfig.get_python_inc())'])
132+
if result == "":
133+
_python_configure_fail(
134+
"Problem getting python include path. Is distutils installed?")
135+
return result.stdout.splitlines()[0]
136+
137+
138+
def _get_numpy_include(repository_ctx, python_bin):
139+
"""Gets the numpy include path."""
140+
result = repository_ctx.execute([python_bin, "-c",
141+
'from __future__ import print_function;' +
142+
'import numpy;' +
143+
' print(numpy.get_include());'])
144+
if result == "":
145+
_python_configure_fail(
146+
"Problem getting numpy include path. Is numpy installed?")
147+
return result.stdout.splitlines()[0]
148+
149+
150+
def _create_python_repository(repository_ctx):
151+
"""Creates the repository containing files set up to build with Python."""
152+
python_include = None
153+
numpy_include = None
154+
# If local checks were requested, the python and numpy include will be auto
155+
# detected on the host config (using _PYTHON_BIN_PATH).
156+
if repository_ctx.attr.local_checks:
157+
python_bin = _get_env_var(repository_ctx, _PYTHON_BIN_PATH)
158+
_check_python_bin(repository_ctx, python_bin)
159+
python_include = _get_python_include(repository_ctx, python_bin)
160+
numpy_include = _get_numpy_include(repository_ctx, python_bin) + '/numpy'
161+
else:
162+
# Otherwise, we assume user provides all paths (via ENV or attrs)
163+
python_include = _get_env_var(repository_ctx, _PYTHON_INCLUDE_PATH,
164+
repository_ctx.attr.python_include)
165+
numpy_include = _get_env_var(repository_ctx, _NUMPY_INCLUDE_PATH,
166+
repository_ctx.attr.numpy_include) + '/numpy'
167+
168+
python_include_rule = _symlink_genrule_for_dir(
169+
repository_ctx, python_include, 'python_include', 'python_include')
170+
numpy_include_rule = _symlink_genrule_for_dir(
171+
repository_ctx, numpy_include, 'numpy_include/numpy', 'numpy_include')
172+
_tpl(repository_ctx, "BUILD", {
173+
"%{PYTHON_INCLUDE_GENRULE}": python_include_rule,
174+
"%{NUMPY_INCLUDE_GENRULE}": numpy_include_rule,
175+
})
176+
177+
178+
def _python_autoconf_impl(repository_ctx):
179+
"""Implementation of the python_autoconf repository rule."""
180+
_create_python_repository(repository_ctx)
181+
182+
183+
python_configure = repository_rule(
184+
implementation = _python_autoconf_impl,
185+
attrs = {
186+
"local_checks": attr.bool(mandatory = False, default = True),
187+
"python_include": attr.string(mandatory = False),
188+
"numpy_include": attr.string(mandatory = False),
189+
},
190+
environ = [
191+
_PYTHON_BIN_PATH,
192+
_PYTHON_INCLUDE_PATH,
193+
_NUMPY_INCLUDE_PATH,
194+
],
195+
)
196+
"""Detects and configures the local Python.
197+
198+
Add the following to your WORKSPACE FILE:
199+
200+
```python
201+
python_configure(name = "local_config_python")
202+
```
203+
204+
Args:
205+
name: A unique name for this workspace rule.
206+
"""

util/python/BUILD

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,7 @@ licenses(["restricted"])
22

33
package(default_visibility = ["//visibility:public"])
44

5-
cc_library(
5+
alias(
66
name = "python_headers",
7-
hdrs = glob([
8-
"python_include/**/*.h",
9-
]),
10-
data = [":python_checked"],
11-
includes = ["python_include"],
12-
)
13-
14-
genrule(
15-
name = "python_check",
16-
srcs = [
17-
"python_config.sh",
18-
"configure_files",
19-
],
20-
outs = [
21-
"python_checked",
22-
],
23-
cmd = "OUTPUTDIR=\"$(@D)/\"; $(location :python_config.sh) --check && touch $$OUTPUTDIR/python_checked",
24-
local = 1,
25-
)
26-
27-
filegroup(
28-
name = "configure_files",
29-
data = glob([
30-
"*",
31-
]),
7+
actual = "@local_config_python//:python_headers",
328
)

0 commit comments

Comments
 (0)