Initial support for Bzlmod. (#55)

diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..e270b8a
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,8 @@
+# Bazel extensions for pybind11
+module(
+    name = "pybind11_bazel",
+    version = "2.11.1",
+)
+
+bazel_dep(name = "platforms", version = "0.0.7")
+bazel_dep(name = "rules_cc", version = "0.0.8")
diff --git a/README.md b/README.md
index ad1a86c..daf12c2 100644
--- a/README.md
+++ b/README.md
@@ -69,3 +69,24 @@
   python_interpreter_target = "@python_interpreter//:python_bin",
 )
 ```
+
+## Bzlmod
+
+In your `MODULE.bazel` file:
+
+```starlark
+python_configure = use_extension("@pybind11_bazel//:python_configure.bzl", "extension")
+use_repo(python_configure, "local_config_python", "pybind11")
+```
+
+The `toolchain` tag can only be used by the root module (that is, not by a
+module which is being used as a dependency) to set `python_version` or
+`python_interpreter_target`. For example:
+
+```starlark
+python_configure = use_extension("@pybind11_bazel//:python_configure.bzl", "extension")
+python_configure.toolchain(python_version = "3")
+use_repo(python_configure, "local_config_python", "pybind11")
+```
+
+Usage in your `BUILD` file is as described previously.
diff --git a/python_configure.bzl b/python_configure.bzl
index 51c267e..abaf69a 100644
--- a/python_configure.bzl
+++ b/python_configure.bzl
@@ -6,6 +6,8 @@
   * `PYTHON_LIB_PATH`: Location of python libraries.
 """
 
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
 _BAZEL_SH = "BAZEL_SH"
 _PYTHON_BIN_PATH = "PYTHON_BIN_PATH"
 _PYTHON_CONFIG_BIN_PATH = "PYTHON_CONFIG_BIN_PATH"
@@ -441,3 +443,62 @@
       will configure for that Python version instead of the installed
       binary. This configuration takes precedence over python_version.
 """
+
+def _parse_my_own_version_from_module_dot_bazel(ctx):
+    lines = ctx.read(Label("//:MODULE.bazel")).split("\n")
+    for line in lines:
+        parts = line.split("\"")
+        if parts[0] == "    version = ":
+            return parts[1]
+    _fail("Failed to parse my own version from `MODULE.bazel`! " +
+          "This should never happen!")
+
+def _extension_impl(ctx):
+    toolchain = None
+    for module in ctx.modules:
+        if module.is_root:
+            if not module.tags.toolchain:
+                pass
+            elif len(module.tags.toolchain) == 1:
+                toolchain = module.tags.toolchain[0]
+            else:
+                _fail("The root module may not specify multiple `toolchain` " +
+                      "tags. Found %r `toolchain` tags specified." % (
+                          len(module.tags.toolchain),
+                      ))
+        elif module.tags.toolchain:
+            _fail("A non-root module may not specify any `toolchain` tags. " +
+                  "Found %r `toolchain` tags specified by module %r." % (
+                      len(module.tags.toolchain),
+                      module.name,
+                  ))
+    if toolchain == None:
+        python_configure(
+            name = "local_config_python",
+        )
+    else:
+        python_configure(
+            name = "local_config_python",
+            python_version = toolchain.python_version,
+            python_interpreter_target = toolchain.python_interpreter_target,
+        )
+
+    version = _parse_my_own_version_from_module_dot_bazel(ctx)
+    http_archive(
+        name = "pybind11",
+        build_file = "//:pybind11.BUILD",
+        strip_prefix = "pybind11-%s" % version,
+        urls = ["https://github.com/pybind/pybind11/archive/v%s.zip" % version],
+    )
+
+extension = module_extension(
+    implementation = _extension_impl,
+    tag_classes = {
+        "toolchain": tag_class(
+            attrs = {
+                "python_version": attr.string(default = ""),
+                "python_interpreter_target": attr.label(),
+            },
+        ),
+    },
+)