Fixed unsound issue in wheel examples
diff --git a/examples/wheel/BUILD b/examples/wheel/BUILD
index f745dc3..28268b5 100644
--- a/examples/wheel/BUILD
+++ b/examples/wheel/BUILD
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("//examples/wheel/private:wheel_utils.bzl", "directory_writer")
 load("//python:defs.bzl", "py_library", "py_test")
 load("//python:packaging.bzl", "py_package", "py_wheel")
 load("//python:versions.bzl", "gen_python_config_settings")
@@ -40,10 +41,10 @@
     ],
 )
 
-genrule(
+directory_writer(
     name = "gen_dir",
-    outs = ["someDir"],
-    cmd = "mkdir -p $@ && touch $@/foo.py",
+    out = "someDir",
+    files = {"foo.py": ""},
 )
 
 # Package just a specific py_libraries, without their dependencies
@@ -188,8 +189,8 @@
 )
 
 py_wheel(
-    name = "use_genrule_with_dir_in_outs",
-    distribution = "use_genrule_with_dir_in_outs",
+    name = "use_rule_with_dir_in_outs",
+    distribution = "use_rule_with_dir_in_outs",
     python_tag = "py3",
     version = "0.0.1",
     deps = [
@@ -240,6 +241,6 @@
         ":minimal_with_py_package",
         ":python_abi3_binary_wheel",
         ":python_requires_in_a_package",
-        ":use_genrule_with_dir_in_outs",
+        ":use_rule_with_dir_in_outs",
     ],
 )
diff --git a/examples/wheel/private/BUILD b/examples/wheel/private/BUILD
new file mode 100644
index 0000000..3462d35
--- /dev/null
+++ b/examples/wheel/private/BUILD
@@ -0,0 +1,7 @@
+load("@rules_python//python:defs.bzl", "py_binary")
+
+py_binary(
+    name = "directory_writer",
+    srcs = ["directory_writer.py"],
+    visibility = ["//:__subpackages__"],
+)
diff --git a/examples/wheel/private/directory_writer.py b/examples/wheel/private/directory_writer.py
new file mode 100644
index 0000000..dd604c6
--- /dev/null
+++ b/examples/wheel/private/directory_writer.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+"""The action executable of the `@rules_python//examples/wheel/private:wheel_utils.bzl%directory_writer` rule."""
+
+import argparse
+import json
+from pathlib import Path
+from typing import Tuple
+
+
+def _file_input(value) -> Tuple[Path, str]:
+    path, content = value.split("=", maxsplit=1)
+    return (Path(path), json.loads(content))
+
+
+def parse_args() -> argparse.Namespace:
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument(
+        "--output", type=Path, required=True, help="The output directory to create."
+    )
+    parser.add_argument(
+        "--file",
+        dest="files",
+        type=_file_input,
+        action="append",
+        help="Files to create within the `output` directory.",
+    )
+
+    return parser.parse_args()
+
+
+def main() -> None:
+    args = parse_args()
+
+    args.output.mkdir(parents=True, exist_ok=True)
+
+    for (path, content) in args.files:
+        new_file = args.output / path
+        new_file.parent.mkdir(parents=True, exist_ok=True)
+        new_file.write_text(content)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/examples/wheel/private/wheel_utils.bzl b/examples/wheel/private/wheel_utils.bzl
new file mode 100644
index 0000000..25ef9b4
--- /dev/null
+++ b/examples/wheel/private/wheel_utils.bzl
@@ -0,0 +1,42 @@
+"""Helper rules for demonstrating `py_wheel` examples"""
+
+def _directory_writer_impl(ctx):
+    output = ctx.actions.declare_directory(ctx.attr.out)
+
+    args = ctx.actions.args()
+    args.add("--output", output.path)
+
+    for path, content in ctx.attr.files.items():
+        args.add("--file={}={}".format(
+            path,
+            json.encode(content),
+        ))
+
+    ctx.actions.run(
+        outputs = [output],
+        arguments = [args],
+        executable = ctx.executable._writer,
+    )
+
+    return [DefaultInfo(
+        files = depset([output]),
+        runfiles = ctx.runfiles(files = [output]),
+    )]
+
+directory_writer = rule(
+    implementation = _directory_writer_impl,
+    doc = "A rule for generating a directory with the requested content.",
+    attrs = {
+        "files": attr.string_dict(
+            doc = "A mapping of file name to content to create relative to the generated `out` directory.",
+        ),
+        "out": attr.string(
+            doc = "The name of the directory to create",
+        ),
+        "_writer": attr.label(
+            executable = True,
+            cfg = "exec",
+            default = Label("//examples/wheel/private:directory_writer"),
+        ),
+    },
+)