Merge "Make matplotlibcpp work with upstream Python"
diff --git a/third_party/matplotlib-cpp/BUILD b/third_party/matplotlib-cpp/BUILD
index 6221abb..bd10366 100644
--- a/third_party/matplotlib-cpp/BUILD
+++ b/third_party/matplotlib-cpp/BUILD
@@ -5,16 +5,28 @@
hdrs = [
"matplotlibcpp.h",
],
- data = [
- "@matplotlib_repo//:matplotlib3",
- "@python_repo//:all_files",
+ data = select({
+ "//tools/platforms/python:debian_bundled_python": [
+ "@matplotlib_repo//:matplotlib3",
+ ],
+ "//tools/platforms/python:upstream_bundled_python": [
+ "@pip//matplotlib",
+ "@pip//pygobject",
+ ],
+ }) + [
+ "//third_party/python:python_runtime",
],
# While this is technically compatible with "linux", the
# "@python_repo//:all_files" has x86 binaries in it.
target_compatible_with = ["@platforms//cpu:x86_64"],
visibility = ["//visibility:public"],
- deps = [
- "@python_repo//:python3.9_lib",
+ deps = select({
+ "//tools/platforms/python:debian_bundled_python": [],
+ "//tools/platforms/python:upstream_bundled_python": [
+ "//third_party/python:numpy_cc",
+ ],
+ }) + [
+ "//third_party/python",
],
)
diff --git a/third_party/matplotlib-cpp/matplotlibcpp.h b/third_party/matplotlib-cpp/matplotlibcpp.h
index 35aeb54..1c8bdc1 100644
--- a/third_party/matplotlib-cpp/matplotlibcpp.h
+++ b/third_party/matplotlib-cpp/matplotlibcpp.h
@@ -144,6 +144,7 @@
_interpreter() {
// Force PYTHONHOME and PYTHONPATH to our sandboxed python.
+#if defined(FRC971_DEBIAN_BUNDLED_PYTHON)
wchar_t python_home[] = L"../python_repo/usr/";
wchar_t python_path[] =
L"../matplotlib_repo/3:../python_repo/usr/lib/python35.zip:../"
@@ -153,6 +154,23 @@
Py_SetPath(python_path);
Py_SetPythonHome(python_home);
+#elif defined(FRC971_UPSTREAM_BUNDLED_PYTHON)
+ wchar_t python_home[] = L"../python3_9_x86_64-unknown-linux-gnu/";
+ Py_SetPythonHome(python_home);
+
+ char python_path[] = "PYTHONPATH="
+ "../pip_deps_matplotlib/site-packages/:"
+ "../pip_deps_numpy/site-packages/:"
+ "../pip_deps_pillow/site-packages/:"
+ "../pip_deps_pycairo/site-packages/:"
+ "../pip_deps_pygobject/site-packages/:"
+ "../pip_deps_python_dateutil/site-packages/:"
+ "../pip_deps_six/site-packages/:"
+ "../";
+ putenv(python_path);
+#else
+#error Need one of the two defined.
+#endif
// We fail really poorly if DISPLAY isn't set. We can do better.
if (getenv("DISPLAY") == nullptr) {
@@ -195,6 +213,13 @@
throw std::runtime_error("Error loading module matplotlib!");
}
+#if defined(FRC971_UPSTREAM_BUNDLED_PYTHON)
+ // We don't support tkinter with Python from rules_python. We use the
+ // GTK backend instead.
+ // https://github.com/matplotlib/matplotlib/issues/23074
+ s_backend = "GTK3Agg";
+#endif
+
// matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
// or matplotlib.backends is imported for the first time
if (!s_backend.empty()) {
diff --git a/third_party/python/BUILD b/third_party/python/BUILD
new file mode 100644
index 0000000..325870c
--- /dev/null
+++ b/third_party/python/BUILD
@@ -0,0 +1,58 @@
+load(":defs.bzl", "extract_numpy_headers")
+
+cc_library(
+ name = "python",
+ deps = select({
+ "//tools/platforms/python:debian_bundled_python": [
+ "@python_repo//:python3.9_lib",
+ ],
+ "//tools/platforms/python:upstream_bundled_python": [
+ "@python3_9_x86_64-unknown-linux-gnu//:python_headers",
+ "@python3_9_x86_64-unknown-linux-gnu//:libpython",
+ ],
+ }),
+ defines = select({
+ "//tools/platforms/python:debian_bundled_python": [
+ "FRC971_DEBIAN_BUNDLED_PYTHON",
+ ],
+ "//tools/platforms/python:upstream_bundled_python": [
+ "FRC971_UPSTREAM_BUNDLED_PYTHON",
+ "FRC971_PYTHON_HOME=../python3_9_x86_64-unknown-linux-gnu/",
+ ],
+ }),
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "python_runtime",
+ data = select({
+ "//tools/platforms/python:debian_bundled_python": [
+ "@python_repo//:all_files",
+ ],
+ "//tools/platforms/python:upstream_bundled_python": [
+ "@python3_9_x86_64-unknown-linux-gnu//:files",
+ ],
+ }),
+ visibility = ["//visibility:public"],
+)
+
+extract_numpy_headers(
+ name = "numpy_headers",
+ numpy = "@pip//numpy",
+ header_prefix = "numpy_headers",
+ visibility = ["//visibility:private"],
+)
+
+cc_library(
+ name = "numpy_cc",
+ hdrs = [
+ ":numpy_headers",
+ ],
+ includes = [
+ "numpy_headers",
+ ],
+ deps = [
+ ":python",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/third_party/python/defs.bzl b/third_party/python/defs.bzl
new file mode 100644
index 0000000..f49d0ba
--- /dev/null
+++ b/third_party/python/defs.bzl
@@ -0,0 +1,34 @@
+def _extract_numpy_headers_impl(ctx):
+ files = ctx.attr.numpy[DefaultInfo].default_runfiles.files.to_list()
+ prefix = ctx.attr.header_prefix
+
+ hdrs = []
+ for file in files:
+ _, partition, include_file = file.path.partition("/numpy/core/include/numpy/")
+ if partition:
+ hdr = ctx.actions.declare_file("%s/numpy/%s" % (prefix, include_file))
+ ctx.actions.run(
+ inputs = [file],
+ outputs = [hdr],
+ executable = "cp",
+ arguments = [file.path, hdr.path],
+ )
+ hdrs.append(hdr)
+
+ return [DefaultInfo(files=depset(hdrs))]
+
+extract_numpy_headers = rule(
+ implementation = _extract_numpy_headers_impl,
+ doc = "Extracts the numpy headers from the corresponding py_library target.",
+ attrs = {
+ "numpy": attr.label(
+ mandatory = True,
+ providers = [PyInfo],
+ doc = "The label for the numpy py_library target.",
+ ),
+ "header_prefix": attr.string(
+ mandatory = True,
+ doc = "The directory to copy the headers into.",
+ ),
+ },
+)