Provide Python 3 matplotlib

Once I get around to making numpy/scipy imported for Python 3, I'll
probably upgrade everything to Python 3 and drop Python 2 support from
the codebase, but I don't feel like doing that quite yet.

Change-Id: I164c8fbb3ce922a83b56e46f5cc432004c3a989c
diff --git a/debian/matplotlib.bzl b/debian/matplotlib.bzl
index b1687d6..a2c6683 100644
--- a/debian/matplotlib.bzl
+++ b/debian/matplotlib.bzl
@@ -90,6 +90,7 @@
     "python3-matplotlib_2.0.0+dfsg1-2_amd64.deb": "8f5d3509d4f5451468c6de44fc8dfe391c3df4120079adc01ab5f13ff4194f5a",
     "python3-pyparsing_2.1.10+dfsg1-1_all.deb": "ee8d7f04f841248127e81b3d356d37e623ed29da284b28c7d2b8a5b34f0eebba",
     "python3-six_1.10.0-3_all.deb": "597005e64cf70e4be97170a47c33287f70a1c87a2979d47a434c10c9201af3ca",
+    "python3-tk_3.5.3-1_amd64.deb": "67489a1c86a9e501dbe2989cd72b5b2c70511fe3829af3567a009271b61fdbb5",
     "python3-tz_2016.7-0.3_all.deb": "5f1c7db456aac5fe9b0ea66d7413c12660c7652ae382c640f71c517a05d39551",
     "shared-mime-info_1.8-1+deb9u1_amd64.deb": "d6591f13ee1200c4f0b5581c2299eb7b8097a6b04742dc333e34a7bb7ba47532",
     "tk8.6-blt2.5_2.5.3+dfsg-3_amd64.deb": "88587a928e2bd692650d98c1483b67f1dee1fed57730077c895e689462af1569",
@@ -97,3 +98,148 @@
     "tzdata_2019c-0+deb9u1_all.deb": "80c9809dafc62ec741cbf3024130253de6047af31a10f0c86bb17f2d12ad10d5",
     "ucf_3.0036_all.deb": "796a65e765d6045007175531d512c720f4eb04e7f3326b79b848bc6123947225",
 }
+
+def build_matplotlib(version, tkinter_py_version = None, copy_shared_files = True):
+  """Creates a py_library rule for matplotlib for the given python version.
+
+  See debian/matplotlib.BUILD for the usage.
+
+  All the rules generated by this will be suffixed by version. Only one
+  instance of this macro should set copy_shared_files, which generate the
+  files that are shared between python versions.
+
+  tkinter_py_version is used because for the Python3 instance, some files
+  are in folders named python3 and some are in folders named python3.5...
+
+  version numbers should both be strings.
+  """
+  if tkinter_py_version == None:
+    tkinter_py_version = version
+
+  native.genrule(
+      name = "patch_init" + version,
+      srcs = [
+          "usr/lib/python" + version + "/dist-packages/matplotlib/__init__.py",
+          "@//debian:matplotlib_patches",
+      ],
+      outs = [version + "/matplotlib/__init__.py"],
+      cmd = " && ".join([
+          "cp $(location usr/lib/python" + version + "/dist-packages/matplotlib/__init__.py) $@",
+          "readonly PATCH=\"$$(readlink -f $(location @patch))\"",
+          "readonly FILE=\"$$(readlink -f $(location @//debian:matplotlib_patches))\"",
+          "(cd $(@D) && \"$${PATCH}\" -p1 < \"$${FILE}\") > /dev/null",
+      ]),
+      tools = [
+          "@patch",
+      ],
+  )
+
+  _src_files = native.glob(
+      include = ["usr/lib/python" + version + "/dist-packages/**/*.py"],
+      exclude = [
+          "usr/lib/python" + version + "/dist-packages/matplotlib/__init__.py",
+      ],
+  )
+
+  _data_files = native.glob([
+      "usr/share/matplotlib/mpl-data/**",
+      "usr/share/tcltk/**",
+  ])
+
+  _src_copied = ["/".join([version] + f.split("/")[4:]) for f in _src_files]
+
+  _builtin_so_files = native.glob([
+      "usr/lib/python" + version + "/dist-packages/**/*x86_64-linux-gnu.so",
+      "usr/lib/python" + tkinter_py_version + "/lib-dynload/*.so",
+  ])
+
+  _system_so_files = native.glob([
+      "usr/lib/**/*.so*",
+      "lib/x86_64-linux-gnu/**/*.so*",
+  ])
+
+  _builtin_so_copied = ["/".join([version] + f.split("/")[4:]) for f in _builtin_so_files]
+
+  rpath_prefix = "rpathed" + version + "/"
+
+  _system_so_copied = [rpath_prefix + f for f in _system_so_files]
+
+  _builtin_rpaths = [":".join([
+      "\\$$ORIGIN/%s" % rel,
+      "\\$$ORIGIN/%s/%s/usr/lib/x86_64-linux-gnu" % (rel, rpath_prefix),
+      "\\$$ORIGIN/%s/%s/usr/lib" % (rel, rpath_prefix),
+      "\\$$ORIGIN/%s/%s/lib/x86_64-linux-gnu" % (rel, rpath_prefix),
+  ]) for rel in ["/".join([".." for _ in so.split("/")[1:]]) for so in _builtin_so_copied]]
+
+  _system_rpaths = [":".join([
+      "\\$$ORIGIN/%s/%s/usr/lib/x86_64-linux-gnu" % (rel, rpath_prefix),
+      "\\$$ORIGIN/%s/%s/lib/x86_64-linux-gnu" % (rel, rpath_prefix),
+  ]) for rel in ["/".join([".." for _ in so.split("/")[1:]]) for so in _system_so_copied]]
+
+  native.genrule(
+      name = "run_patchelf_builtin" + version,
+      srcs = _builtin_so_files,
+      outs = _builtin_so_copied,
+      cmd = "\n".join(
+          [
+              "cp $(location %s) $(location %s)" % (src, dest)
+              for src, dest in zip(_builtin_so_files, _builtin_so_copied)
+          ] +
+          ["$(location @patchelf) --set-rpath %s $(location %s)" % (rpath, so) for rpath, so in zip(_builtin_rpaths, _builtin_so_copied)],
+      ),
+      tools = [
+          "@patchelf",
+      ],
+  )
+
+  native.genrule(
+      name = "run_patchelf_system" + version,
+      srcs = _system_so_files,
+      outs = _system_so_copied,
+      cmd = "\n".join(
+          [
+              "cp $(location %s) $(location %s)" % (src, dest)
+              for src, dest in zip(_system_so_files, _system_so_copied)
+          ] +
+          ["$(location @patchelf) --set-rpath %s $(location %s)" % (rpath, so) for rpath, so in zip(_system_rpaths, _system_so_copied)],
+      ),
+      tools = [
+          "@patchelf",
+      ],
+  )
+
+  native.genrule(
+      name = "copy_files" + version,
+      srcs = _src_files,
+      outs = _src_copied,
+      cmd = " && ".join(["cp $(location %s) $(location %s)" % (src, dest) for src, dest in zip(
+          _src_files,
+          _src_copied,
+      )]),
+  )
+
+  if copy_shared_files:
+    native.genrule(
+        name = "create_rc" + version,
+        outs = ["usr/share/matplotlib/mpl-data/matplotlibrc"],
+        cmd = "\n".join([
+            "cat > $@ << END",
+            # This is necessary to make matplotlib actually plot things to the
+            # screen by default.
+            "backend      : TkAgg",
+            "END",
+        ]),
+    )
+
+  native.py_library(
+      name = "matplotlib" + version,
+      srcs = _src_copied + [
+          version + "/matplotlib/__init__.py",
+      ],
+      data = _data_files + _builtin_so_copied + _system_so_copied + [
+          ":usr/share/matplotlib/mpl-data/matplotlibrc",
+      ],
+      imports = ["usr/lib/python" + version + "/dist-packages", version, "."],
+      restricted_to = ["@//tools:k8"],
+      visibility = ["//visibility:public"],
+  )