diff --git a/tensorflow/lite/c/BUILD b/tensorflow/lite/c/BUILD
index 19cdd37ed4f..b4253b49a61 100644
--- a/tensorflow/lite/c/BUILD
+++ b/tensorflow/lite/c/BUILD
@@ -119,10 +119,7 @@ cc_library_with_tflite_with_c_headers_test(
tflite_deps = [
":c_api",
],
- deps = [
- "//tensorflow/lite/core/c:c_api_experimental",
- "//tensorflow/lite/core/c:c_api_opaque",
- ],
+ deps = ["//tensorflow/lite/core/c:c_api_experimental"],
)
# Same as ":c_api_experimental", but without linking in the default CreateOpResolver implementation.
@@ -143,10 +140,7 @@ cc_library_with_tflite_with_c_headers_test(
tflite_deps = [
":c_api_without_op_resolver",
],
- deps = [
- "//tensorflow/lite/core/c:c_api_experimental_without_op_resolver",
- "//tensorflow/lite/core/c:c_api_opaque_without_op_resolver",
- ],
+ deps = ["//tensorflow/lite/core/c:c_api_experimental_without_op_resolver"],
)
# Same as ":c_api_experimental", but without linking in the default CreateOpResolver implementation,
@@ -183,6 +177,7 @@ cc_library_with_tflite_with_c_headers_test(
copts = tflite_copts() + tflite_copts_warnings(),
generate_opaque_delegate_target = True,
tflite_deps = [":c_api"],
+ linkstatic = 1,
deps = ["//tensorflow/lite/core/c:c_api_opaque"],
)
@@ -209,7 +204,7 @@ cc_library_with_tflite_with_c_headers_test(
tflite_deps = [
":c_api_without_op_resolver_without_alwayslink",
],
- deps = ["//tensorflow/lite/core/c:c_api_opaque_without_op_resolver_without_alwayslink"],
+ deps = ["//tensorflow/lite/core/c:c_api_experimental_without_op_resolver_without_alwayslink"],
)
cc_library_with_tflite_with_c_headers_test(
@@ -457,7 +452,6 @@ cc_test(
":c_api_experimental",
"//tensorflow/lite/core/c:c_api",
"//tensorflow/lite/core/c:c_api_experimental",
- "//tensorflow/lite/core/c:c_api_opaque",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
],
diff --git a/tensorflow/lite/core/c/BUILD b/tensorflow/lite/core/c/BUILD
index 018b6e1004c..cf355612386 100644
--- a/tensorflow/lite/core/c/BUILD
+++ b/tensorflow/lite/core/c/BUILD
@@ -378,7 +378,6 @@ tflite_cc_library_with_c_headers_test(
deps = [
":c_api",
":c_api_experimental_without_op_resolver",
- ":c_api_opaque",
":c_api_types",
":common",
":operator",
@@ -399,6 +398,7 @@ tflite_cc_library_with_c_headers_test(
name = "c_api_experimental_without_op_resolver",
srcs = [
"c_api_experimental.cc",
+ "c_api_opaque.cc",
],
hdrs = [
"c_api_experimental.h",
@@ -413,7 +413,6 @@ tflite_cc_library_with_c_headers_test(
copts = tflite_copts(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
deps = [
- ":c_api_opaque_without_op_resolver",
":c_api_types",
":c_api_without_op_resolver",
":common",
@@ -451,6 +450,7 @@ tflite_cc_library_with_c_headers_test(
name = "c_api_experimental_without_op_resolver_without_alwayslink",
srcs = [
"c_api_experimental.cc",
+ "c_api_opaque.cc",
],
hdrs = [
"c_api_experimental.h",
@@ -467,7 +467,6 @@ tflite_cc_library_with_c_headers_test(
copts = tflite_copts(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
deps = [
- ":c_api_opaque_without_op_resolver_without_alwayslink",
":c_api_types",
":c_api_without_op_resolver_without_alwayslink",
":common",
diff --git a/tensorflow/tools/toolchains/cpus/aarch64/aarch64_compiler_configure.bzl b/tensorflow/tools/toolchains/cpus/aarch64/aarch64_compiler_configure.bzl
index 00cd6983ca3..d9c5ef16f9b 100644
--- a/tensorflow/tools/toolchains/cpus/aarch64/aarch64_compiler_configure.bzl
+++ b/tensorflow/tools/toolchains/cpus/aarch64/aarch64_compiler_configure.bzl
@@ -1,7 +1,7 @@
"""Configurations of AARCH64 builds used with Docker container."""
load("//tensorflow/tools/toolchains:cpus/aarch64/aarch64.bzl", "remote_aarch64_configure")
-load("//third_party/py:python_configure.bzl", "remote_python_configure")
+load("//third_party/py/non_hermetic:python_configure.bzl", "remote_python_configure")
load("//third_party/remote_config:remote_platform_configure.bzl", "remote_platform_configure")
def ml2014_tf_aarch64_configs(name_container_map, env):
diff --git a/tensorflow/tools/toolchains/remote_config/rbe_config.bzl b/tensorflow/tools/toolchains/remote_config/rbe_config.bzl
index ae776c2a2fd..108e79edbd7 100644
--- a/tensorflow/tools/toolchains/remote_config/rbe_config.bzl
+++ b/tensorflow/tools/toolchains/remote_config/rbe_config.bzl
@@ -4,7 +4,7 @@ load("//tensorflow/tools/toolchains/remote_config:containers.bzl", "containers")
load("//third_party/gpus:cuda_configure.bzl", "remote_cuda_configure")
load("//third_party/gpus:rocm_configure.bzl", "remote_rocm_configure")
load("//third_party/nccl:nccl_configure.bzl", "remote_nccl_configure")
-load("//third_party/py:python_configure.bzl", "local_python_configure", "remote_python_configure")
+load("//third_party/py/non_hermetic:python_configure.bzl", "local_python_configure", "remote_python_configure")
load("//third_party/remote_config:remote_platform_configure.bzl", "remote_platform_configure")
load("//third_party/tensorrt:tensorrt_configure.bzl", "remote_tensorrt_configure")
diff --git a/tensorflow/workspace2.bzl b/tensorflow/workspace2.bzl
index 380a1a93585..3f3e12a0617 100644
--- a/tensorflow/workspace2.bzl
+++ b/tensorflow/workspace2.bzl
@@ -44,7 +44,7 @@ load("//third_party/nasm:workspace.bzl", nasm = "repo")
load("//third_party/nccl:nccl_configure.bzl", "nccl_configure")
load("//third_party/opencl_headers:workspace.bzl", opencl_headers = "repo")
load("//third_party/pasta:workspace.bzl", pasta = "repo")
-load("//third_party/py:python_configure.bzl", "python_configure")
+load("//third_party/py/non_hermetic:python_configure.bzl", "python_configure")
load("//third_party/py/ml_dtypes:workspace.bzl", ml_dtypes = "repo")
load("//third_party/pybind11_abseil:workspace.bzl", pybind11_abseil = "repo")
load("//third_party/pybind11_bazel:workspace.bzl", pybind11_bazel = "repo")
diff --git a/third_party/py/non_hermetic/BUILD b/third_party/py/non_hermetic/BUILD
new file mode 100644
index 00000000000..d14731cafcd
--- /dev/null
+++ b/third_party/py/non_hermetic/BUILD
@@ -0,0 +1,2 @@
+# Empty BUILD file
+
diff --git a/third_party/py/non_hermetic/BUILD.tpl b/third_party/py/non_hermetic/BUILD.tpl
new file mode 100644
index 00000000000..0d2d06da29a
--- /dev/null
+++ b/third_party/py/non_hermetic/BUILD.tpl
@@ -0,0 +1,80 @@
+licenses(["restricted"])
+
+package(default_visibility = ["//visibility:public"])
+
+# Point both runtimes to the same python binary to ensure we always
+# use the python binary specified by ./configure.py script.
+load("@bazel_tools//tools/python:toolchain.bzl", "py_runtime_pair")
+
+py_runtime(
+ name = "py2_runtime",
+ interpreter_path = "%{PYTHON_BIN_PATH}",
+ python_version = "PY2",
+)
+
+py_runtime(
+ name = "py3_runtime",
+ interpreter_path = "%{PYTHON_BIN_PATH}",
+ python_version = "PY3",
+)
+
+py_runtime_pair(
+ name = "py_runtime_pair",
+ py2_runtime = ":py2_runtime",
+ py3_runtime = ":py3_runtime",
+)
+
+toolchain(
+ name = "py_toolchain",
+ toolchain = ":py_runtime_pair",
+ toolchain_type = "@bazel_tools//tools/python:toolchain_type",
+ target_compatible_with = [%{PLATFORM_CONSTRAINT}],
+ exec_compatible_with = [%{PLATFORM_CONSTRAINT}],
+)
+
+# To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib
+# See https://docs.python.org/3/extending/windows.html
+cc_import(
+ name = "python_lib",
+ interface_library = select({
+ ":windows": ":python_import_lib",
+ # A placeholder for Unix platforms which makes --no_build happy.
+ "//conditions:default": "not-existing.lib",
+ }),
+ system_provided = 1,
+)
+
+cc_library(
+ name = "python_headers",
+ hdrs = [":python_include"],
+ deps = select({
+ ":windows": [":python_lib"],
+ "//conditions:default": [],
+ }),
+ includes = ["python_include"],
+)
+
+# This alias is exists for the use of targets in the @llvm-project dependency,
+# which expect a python_headers target called @python_runtime//:headers. We use
+# a repo_mapping to alias python_runtime to this package, and an alias to create
+# the correct target.
+alias(
+ name = "headers",
+ actual = ":python_headers",
+)
+
+cc_library(
+ name = "numpy_headers",
+ hdrs = [":numpy_include"],
+ includes = ["numpy_include"],
+)
+
+config_setting(
+ name = "windows",
+ values = {"cpu": "x64_windows"},
+ visibility = ["//visibility:public"],
+)
+
+%{PYTHON_INCLUDE_GENRULE}
+%{NUMPY_INCLUDE_GENRULE}
+%{PYTHON_IMPORT_LIB_GENRULE}
diff --git a/third_party/py/non_hermetic/python_configure.bzl b/third_party/py/non_hermetic/python_configure.bzl
new file mode 100644
index 00000000000..e6eeb02641a
--- /dev/null
+++ b/third_party/py/non_hermetic/python_configure.bzl
@@ -0,0 +1,313 @@
+"""Repository rule for Python autoconfiguration.
+
+`python_configure` depends on the following environment variables:
+
+ * `PYTHON_BIN_PATH`: location of python binary.
+ * `PYTHON_LIB_PATH`: Location of python libraries.
+"""
+
+load(
+ "//third_party/remote_config:common.bzl",
+ "BAZEL_SH",
+ "PYTHON_BIN_PATH",
+ "PYTHON_LIB_PATH",
+ "TF_PYTHON_CONFIG_REPO",
+ "auto_config_fail",
+ "config_repo_label",
+ "execute",
+ "get_bash_bin",
+ "get_host_environ",
+ "get_python_bin",
+ "is_windows",
+ "raw_exec",
+ "read_dir",
+)
+
+def _genrule(src_dir, genrule_name, command, outs):
+ """Returns a string with a genrule.
+
+ Genrule executes the given command and produces the given outputs.
+ """
+ return (
+ "genrule(\n" +
+ ' name = "' +
+ genrule_name + '",\n' +
+ " outs = [\n" +
+ outs +
+ "\n ],\n" +
+ ' cmd = """\n' +
+ command +
+ '\n """,\n' +
+ ")\n"
+ )
+
+def _norm_path(path):
+ """Returns a path with '/' and remove the trailing slash."""
+ path = path.replace("\\", "/")
+ if path[-1] == "/":
+ path = path[:-1]
+ return path
+
+def _symlink_genrule_for_dir(
+ repository_ctx,
+ src_dir,
+ dest_dir,
+ genrule_name,
+ src_files = [],
+ dest_files = []):
+ """Returns a genrule to symlink(or copy if on Windows) a set of files.
+
+ If src_dir is passed, files will be read from the given directory; otherwise
+ we assume files are in src_files and dest_files
+ """
+ if src_dir != None:
+ src_dir = _norm_path(src_dir)
+ dest_dir = _norm_path(dest_dir)
+ files = "\n".join(read_dir(repository_ctx, src_dir))
+
+ # Create a list with the src_dir stripped to use for outputs.
+ dest_files = files.replace(src_dir, "").splitlines()
+ src_files = files.splitlines()
+ command = []
+ outs = []
+ for i in range(len(dest_files)):
+ if dest_files[i] != "":
+ # If we have only one file to link we do not want to use the dest_dir, as
+ # $(@D) will include the full path to the file.
+ dest = "$(@D)/" + dest_dir + dest_files[i] if len(dest_files) != 1 else "$(@D)/" + dest_files[i]
+
+ # Copy the headers to create a sandboxable setup.
+ cmd = "cp -f"
+ command.append(cmd + ' "%s" "%s"' % (src_files[i], dest))
+ outs.append(' "' + dest_dir + dest_files[i] + '",')
+ genrule = _genrule(
+ src_dir,
+ genrule_name,
+ " && ".join(command),
+ "\n".join(outs),
+ )
+ return genrule
+
+def _get_python_lib(repository_ctx, python_bin):
+ """Gets the python lib path."""
+ python_lib = get_host_environ(repository_ctx, PYTHON_LIB_PATH)
+ if python_lib != None:
+ return python_lib
+
+ # The interesting program to execute.
+ print_lib = [
+ "from __future__ import print_function",
+ "import site",
+ "import os",
+ "python_paths = []",
+ "if os.getenv('PYTHONPATH') is not None:",
+ " python_paths = os.getenv('PYTHONPATH').split(':')",
+ "try:",
+ " library_paths = site.getsitepackages()",
+ "except AttributeError:",
+ " from distutils.sysconfig import get_python_lib",
+ " library_paths = [get_python_lib()]",
+ "all_paths = set(python_paths + library_paths)",
+ "paths = []",
+ "for path in all_paths:",
+ " if os.path.isdir(path):",
+ " paths.append(path)",
+ "if len(paths) >=1:",
+ " print(paths[0])",
+ ]
+
+ # The below script writes the above program to a file
+ # and executes it. This is to work around the limitation
+ # of not being able to upload files as part of execute.
+ cmd = "from os import linesep;"
+ cmd += "f = open('script.py', 'w');"
+ for line in print_lib:
+ cmd += "f.write(\"%s\" + linesep);" % line
+ cmd += "f.close();"
+ cmd += "from subprocess import call;"
+ cmd += "call([\"%s\", \"script.py\"]);" % python_bin
+
+ result = execute(repository_ctx, [python_bin, "-c", cmd])
+ return result.stdout.strip()
+
+def _check_python_lib(repository_ctx, python_lib):
+ """Checks the python lib path."""
+ cmd = 'test -d "%s" -a -x "%s"' % (python_lib, python_lib)
+ result = raw_exec(repository_ctx, [get_bash_bin(repository_ctx), "-c", cmd])
+ if result.return_code == 1:
+ auto_config_fail("Invalid python library path: %s" % python_lib)
+
+def _check_python_bin(repository_ctx, python_bin):
+ """Checks the python bin path."""
+ cmd = '[[ -x "%s" ]] && [[ ! -d "%s" ]]' % (python_bin, python_bin)
+ result = raw_exec(repository_ctx, [get_bash_bin(repository_ctx), "-c", cmd])
+ if result.return_code == 1:
+ auto_config_fail("--define %s='%s' is not executable. Is it the python binary?" % (
+ PYTHON_BIN_PATH,
+ python_bin,
+ ))
+
+def _get_python_include(repository_ctx, python_bin):
+ """Gets the python include path."""
+ result = execute(
+ repository_ctx,
+ [
+ python_bin,
+ "-Wignore",
+ "-c",
+ "import sysconfig; " +
+ "print(sysconfig.get_path('include'))",
+ ],
+ error_msg = "Problem getting python include path.",
+ error_details = ("Is the Python binary path set up right? " +
+ "(See ./configure or " + PYTHON_BIN_PATH + ".) " +
+ "Is distutils installed?"),
+ )
+ return result.stdout.splitlines()[0]
+
+def _get_python_import_lib_name(repository_ctx, python_bin):
+ """Get Python import library name (pythonXY.lib) on Windows."""
+ result = execute(
+ repository_ctx,
+ [
+ python_bin,
+ "-c",
+ "import sys;" +
+ 'print("python" + str(sys.version_info[0]) + ' +
+ ' str(sys.version_info[1]) + ".lib")',
+ ],
+ error_msg = "Problem getting python import library.",
+ error_details = ("Is the Python binary path set up right? " +
+ "(See ./configure or " + PYTHON_BIN_PATH + ".) "),
+ )
+ return result.stdout.splitlines()[0]
+
+def _get_numpy_include(repository_ctx, python_bin):
+ """Gets the numpy include path."""
+ return execute(
+ repository_ctx,
+ [
+ python_bin,
+ "-c",
+ "from __future__ import print_function;" +
+ "import numpy;" +
+ " print(numpy.get_include());",
+ ],
+ error_msg = "Problem getting numpy include path.",
+ error_details = "Is numpy installed?",
+ ).stdout.splitlines()[0]
+
+def _create_local_python_repository(repository_ctx):
+ """Creates the repository containing files set up to build with Python."""
+
+ # Resolve all labels before doing any real work. Resolving causes the
+ # function to be restarted with all previous state being lost. This
+ # can easily lead to a O(n^2) runtime in the number of labels.
+ build_tpl = repository_ctx.path(Label("//third_party/py/non_hermetic:BUILD.tpl"))
+
+ python_bin = get_python_bin(repository_ctx)
+ _check_python_bin(repository_ctx, python_bin)
+ python_lib = _get_python_lib(repository_ctx, python_bin)
+ _check_python_lib(repository_ctx, python_lib)
+ python_include = _get_python_include(repository_ctx, python_bin)
+ numpy_include = _get_numpy_include(repository_ctx, python_bin) + "/numpy"
+ python_include_rule = _symlink_genrule_for_dir(
+ repository_ctx,
+ python_include,
+ "python_include",
+ "python_include",
+ )
+ python_import_lib_genrule = ""
+
+ # To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib
+ # See https://docs.python.org/3/extending/windows.html
+ if is_windows(repository_ctx):
+ python_bin = python_bin.replace("\\", "/")
+ python_include = _norm_path(python_include)
+ python_import_lib_name = _get_python_import_lib_name(repository_ctx, python_bin)
+ python_import_lib_src = python_include.rsplit("/", 1)[0] + "/libs/" + python_import_lib_name
+ python_import_lib_genrule = _symlink_genrule_for_dir(
+ repository_ctx,
+ None,
+ "",
+ "python_import_lib",
+ [python_import_lib_src],
+ [python_import_lib_name],
+ )
+ numpy_include_rule = _symlink_genrule_for_dir(
+ repository_ctx,
+ numpy_include,
+ "numpy_include/numpy",
+ "numpy_include",
+ )
+
+ platform_constraint = ""
+ if repository_ctx.attr.platform_constraint:
+ platform_constraint = "\"%s\"" % repository_ctx.attr.platform_constraint
+ repository_ctx.template("BUILD", build_tpl, {
+ "%{PYTHON_BIN_PATH}": python_bin,
+ "%{PYTHON_INCLUDE_GENRULE}": python_include_rule,
+ "%{PYTHON_IMPORT_LIB_GENRULE}": python_import_lib_genrule,
+ "%{NUMPY_INCLUDE_GENRULE}": numpy_include_rule,
+ "%{PLATFORM_CONSTRAINT}": platform_constraint,
+ })
+
+def _create_remote_python_repository(repository_ctx, remote_config_repo):
+ """Creates pointers to a remotely configured repo set up to build with Python.
+ """
+ repository_ctx.template("BUILD", config_repo_label(remote_config_repo, ":BUILD"), {})
+
+def _python_autoconf_impl(repository_ctx):
+ """Implementation of the python_autoconf repository rule."""
+ if get_host_environ(repository_ctx, TF_PYTHON_CONFIG_REPO) != None:
+ _create_remote_python_repository(
+ repository_ctx,
+ get_host_environ(repository_ctx, TF_PYTHON_CONFIG_REPO),
+ )
+ else:
+ _create_local_python_repository(repository_ctx)
+
+_ENVIRONS = [
+ BAZEL_SH,
+ PYTHON_BIN_PATH,
+ PYTHON_LIB_PATH,
+]
+
+local_python_configure = repository_rule(
+ implementation = _create_local_python_repository,
+ environ = _ENVIRONS,
+ attrs = {
+ "environ": attr.string_dict(),
+ "platform_constraint": attr.string(),
+ },
+)
+
+remote_python_configure = repository_rule(
+ implementation = _create_local_python_repository,
+ environ = _ENVIRONS,
+ remotable = True,
+ attrs = {
+ "environ": attr.string_dict(),
+ "platform_constraint": attr.string(),
+ },
+)
+
+python_configure = repository_rule(
+ implementation = _python_autoconf_impl,
+ environ = _ENVIRONS + [TF_PYTHON_CONFIG_REPO],
+ attrs = {
+ "platform_constraint": attr.string(),
+ },
+)
+"""Detects and configures the local Python.
+
+Add the following to your WORKSPACE FILE:
+
+```python
+python_configure(name = "local_config_python")
+```
+
+Args:
+ name: A unique name for this workspace rule.
+"""
+