Merge tag 'upstream/0.0.10' into main

* tag 'upstream/0.0.10':
  Prepare for release 0.0.10 (#91)
  Add filegroup targets for .bzl files in the `host` package (#90)
  Implement local_config_platform in @platforms (#86)
  Define constraint for emscripten os (#84)
  platform_data implementation (#78)

Change-Id: I605244c108cd53826dc01d2b0056bb6d846df7da
Signed-off-by: Matthias Maennich <maennich@google.com>
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index b24af0f..98f0619 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -1,46 +1,35 @@
----
-#
-# Bazel releases
-#
-lts: &lts
-  bazel: latest
-
-rolling: &rolling
-  bazel: rolling
-
-
-targets: &targets
-  build_targets:
-  - "//..."
-
-
 tasks:
-  ubuntu_lts:
-    name: ubuntu_lts
+  ubuntu:
     platform: ubuntu2004
-    <<: *lts
-    <<: *targets
-  ubuntu_rolling:
-    name: ubuntu_rolling
-    platform: ubuntu2004
-    <<: *rolling
-    <<: *targets
-  macos_lts:
-    name: macos_lts
+    build_targets:
+    - "//..."
+    test_targets:
+    - "//..."
+    environment:
+      EXPECTED_HOST_CONSTRAINTS: '["@platforms//cpu:x86_64", "@platforms//os:linux"]'
+  macos:
     platform: macos
-    <<: *lts
-    <<: *targets
-  windows_lts:
-    name: windows_lts
+    build_targets:
+    - "//..."
+    test_targets:
+    - "//..."
+    environment:
+      EXPECTED_HOST_CONSTRAINTS: '["@platforms//cpu:x86_64", "@platforms//os:osx"]'
+  macos_arm64:
+    platform: macos_arm64
+    build_targets:
+    - "//..."
+    test_targets:
+    - "//..."
+    environment:
+      EXPECTED_HOST_CONSTRAINTS: '["@platforms//cpu:aarch64", "@platforms//os:osx"]'
+  windows:
     platform: windows
-    <<: *lts
-    <<: *targets
-  check_bzlmod:
-    name: check_bzlmod
-    # No need to check bzlmod on every platform. This repository only holds
-    # constants and has no per-platform behavior.
-    platform: ubuntu2004
-    <<: *rolling
-    <<: *targets
-    build_flags:
-    - "--enable_bzlmod"
+    build_targets:
+    - "//..."
+    # We don't run this test on Windows, because amazingly, sh_test doesn't work on Windows for exactly
+    # the @platforms repo (see https://github.com/bazelbuild/platforms/pull/86#issuecomment-2011954684)
+    #test_targets:
+    #- "//..."
+    #environment:
+    #  EXPECTED_HOST_CONSTRAINTS: '["@platforms//cpu:x86_64", "@platforms//os:windows"]'
diff --git a/BUILD b/BUILD
index 4ab75c5..ed29fc3 100644
--- a/BUILD
+++ b/BUILD
@@ -25,6 +25,7 @@
         "WORKSPACE",
         "//cpu:srcs",
         "//os:srcs",
+        "//host:srcs",
     ],
 )
 
diff --git a/METADATA b/METADATA
index 33d7a68..fb04cbd 100644
--- a/METADATA
+++ b/METADATA
@@ -7,7 +7,7 @@
     type: "Git"
     value: "https://github.com/bazelbuild/platforms"
   }
-  version: "0.0.8"
-  last_upgrade_date { year: 2024 month: 1 day: 16 }
+  version: "0.0.10"
+  last_upgrade_date { year: 2024 month: 5 day: 17 }
   license_type: NOTICE
 }
diff --git a/MODULE.bazel b/MODULE.bazel
index 617a84a..23ab980 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,7 +1,10 @@
 module(
     name = "platforms",
-    version = "0.0.8",  # keep in sync with version.bzl
+    version = "0.0.10",  # keep in sync with version.bzl
     compatibility_level = 1,
 )
 
 bazel_dep(name = "rules_license", version = "0.0.7")
+
+host_platform = use_extension("//host:extension.bzl", "host_platform")
+use_repo(host_platform, "host_platform")
diff --git a/distro/makerel.sh b/distro/makerel.sh
index 20c2f0b..063226a 100755
--- a/distro/makerel.sh
+++ b/distro/makerel.sh
@@ -19,7 +19,7 @@
 
 
 dist_file="/tmp/platforms-${version}.tar.gz"
-tar czf "$dist_file" BUILD LICENSE MODULE.bazel WORKSPACE WORKSPACE.bzlmod version.bzl cpu os
+tar czf "$dist_file" BUILD LICENSE MODULE.bazel WORKSPACE WORKSPACE.bzlmod version.bzl cpu os host
 sha256=$(shasum -a256 "$dist_file" | cut -d' ' -f1)
 
 path="github.com/bazelbuild/platforms/releases/download/$version/platforms-$version.tar.gz"
diff --git a/experimental/platform_data/BUILD.bazel b/experimental/platform_data/BUILD.bazel
new file mode 100644
index 0000000..94ececc
--- /dev/null
+++ b/experimental/platform_data/BUILD.bazel
@@ -0,0 +1,3 @@
+exports_files([
+    "defs.bzl",
+])
diff --git a/experimental/platform_data/defs.bzl b/experimental/platform_data/defs.bzl
new file mode 100644
index 0000000..0e739b0
--- /dev/null
+++ b/experimental/platform_data/defs.bzl
@@ -0,0 +1,85 @@
+"""
+The platform_data rule can be used to change the target platform of a target,
+and then depend on that elsewhere in the build tree. For example:
+load("@platforms//experimental/platform_data:defs.bzl", "platform_data")
+
+cc_binary(name = "foo")
+
+platform_data(
+    name = "foo_embedded",
+    target = ":foo",
+    platform = "//my/new:platform",
+)
+
+py_binary(
+    name = "flasher",
+    srcs = ...,
+    data = [
+        ":foo_embedded",
+    ],
+)
+
+Regardless of what platform the top-level :flasher binary is built for,
+the :foo_embedded target will be built for //my/new:platform. 
+
+Note that if you depend on :foo_embedded it's not exactly the same as depending on :foo, since it won't forward all the same providers. In the future, we can extend this to add some common providers as needed."""
+
+def _target_platform_transition_impl(attr):
+    return {
+        "//command_line_option:platforms": str(attr.platform),
+    }
+
+_target_platform_transition = transition(
+    implementation = _target_platform_transition_impl,
+    inputs = [],
+    outputs = [
+        "//command_line_option:platforms",
+    ],
+)
+
+def _platform_data_impl(ctx):
+    target = ctx.attr.target
+
+    default_info = target[DefaultInfo]
+    files = default_info.files
+    original_executable = default_info.files_to_run.executable
+    runfiles = default_info.default_runfiles
+
+    new_executable = ctx.actions.declare_file(ctx.attr.name)
+
+    ctx.actions.symlink(
+        output = new_executable,
+        target_file = original_executable,
+        is_executable = True,
+    )
+
+    files = depset(direct = [new_executable], transitive = [files])
+    runfiles = runfiles.merge(ctx.runfiles([new_executable]))
+
+    return [
+	DefaultInfo(
+            files = files,
+            runfiles = runfiles,
+            executable = new_executable,
+	)
+    ]
+
+platform_data = rule(
+    implementation = _platform_data_impl,
+    attrs = {
+        "target": attr.label(
+            allow_files = False,
+            executable = True,
+            mandatory = True,
+            cfg = _target_platform_transition,
+        ),
+        "platform": attr.label(
+            mandatory = True,
+        ),
+        "_allowlist_function_transition": attr.label(
+            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+        ),
+    },
+    executable = True,
+)
+
diff --git a/host/BUILD.bazel b/host/BUILD.bazel
new file mode 100644
index 0000000..48531bc
--- /dev/null
+++ b/host/BUILD.bazel
@@ -0,0 +1,34 @@
+# Host platform detection
+
+load("@host_platform//:constraints.bzl", "HOST_CONSTRAINTS")
+
+package(default_visibility = ["//visibility:public"])
+
+exports_files(["constraints.bzl", "extension.bzl"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+)
+
+platform(
+    name = "host",
+    constraint_values = HOST_CONSTRAINTS,
+)
+
+# The following filegroup targets are essentially bzl_library targets.
+# We don't directly use bzl_library to avoid a dependency on bazel-skylib.
+filegroup(
+    name = "constraints_lib",
+    srcs = [
+        "constraints.bzl",
+        "@host_platform//:constraints.bzl",
+    ],
+)
+
+filegroup(
+    name = "extension_lib",
+    srcs = [
+        "extension.bzl",
+    ],
+)
diff --git a/host/constraints.bzl b/host/constraints.bzl
new file mode 100644
index 0000000..776c1d9
--- /dev/null
+++ b/host/constraints.bzl
@@ -0,0 +1,4 @@
+load("@host_platform//:constraints.bzl", _host_constraints = "HOST_CONSTRAINTS")
+
+HOST_CONSTRAINTS = _host_constraints
+
diff --git a/host/extension.bzl b/host/extension.bzl
new file mode 100644
index 0000000..8756c59
--- /dev/null
+++ b/host/extension.bzl
@@ -0,0 +1,67 @@
+def _translate_cpu(arch):
+    if arch in ["i386", "i486", "i586", "i686", "i786", "x86"]:
+        return "x86_32"
+    if arch in ["amd64", "x86_64", "x64"]:
+        return "x86_64"
+    if arch in ["ppc", "ppc64", "ppc64le"]:
+        return "ppc"
+    if arch in ["arm", "armv7l"]:
+        return "arm"
+    if arch in ["aarch64"]:
+        return "aarch64"
+    if arch in ["s390x", "s390"]:
+        return "s390x"
+    if arch in ["mips64el", "mips64"]:
+        return "mips64"
+    if arch in ["riscv64"]:
+        return "riscv64"
+    return None
+
+def _translate_os(os):
+    if os.startswith("mac os"):
+        return "osx"
+    if os.startswith("freebsd"):
+        return "freebsd"
+    if os.startswith("openbsd"):
+        return "openbsd"
+    if os.startswith("linux"):
+        return "linux"
+    if os.startswith("windows"):
+        return "windows"
+    return None
+
+def _host_platform_repo_impl(rctx):
+    cpu = _translate_cpu(rctx.os.arch)
+    os = _translate_os(rctx.os.name)
+
+    cpu = "" if cpu == None else "  '@platforms//cpu:%s',\n" % cpu
+    os = "" if os == None else "  '@platforms//os:%s',\n" % os
+
+    rctx.file("BUILD.bazel", """
+# DO NOT EDIT: automatically generated BUILD file
+exports_files(["constraints.bzl"])
+""")
+
+    rctx.file("constraints.bzl", """
+# DO NOT EDIT: automatically generated constraints list
+HOST_CONSTRAINTS = [
+%s%s]
+""" % (cpu, os))
+
+host_platform_repo = repository_rule(
+    implementation = _host_platform_repo_impl,
+    doc = """Generates constraints for the host platform. The constraints.bzl
+file contains a single <code>HOST_CONSTRAINTS</code> variable, which is a
+list of strings, each of which is a label to a <code>constraint_value</code>
+for the host platform.""",
+)
+
+def _host_platform_impl(_mctx):
+    host_platform_repo(name = "host_platform")
+
+host_platform = module_extension(
+    implementation = _host_platform_impl,
+    doc = """Generates a <code>host_platform_repo</code> repo named
+<code>host_platform</code>, containing constraints for the host platform.""",
+)
+
diff --git a/os/BUILD b/os/BUILD
index ae6e8b0..8e9f990 100644
--- a/os/BUILD
+++ b/os/BUILD
@@ -106,6 +106,11 @@
     constraint_setting = ":os",
 )
 
+constraint_value(
+    name = "emscripten",
+    constraint_setting = ":os",
+)
+
 # WASI (WebAssembly System Interface)
 # https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-overview.md
 constraint_value(
diff --git a/tests/BUILD b/tests/BUILD
index e0c7526..66a9d38 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -1,4 +1,5 @@
 load("//:version.bzl", "version")
+load("//host:constraints.bzl", "HOST_CONSTRAINTS")
 
 package(default_visibility = ["//visibility:private"])
 
@@ -19,3 +20,10 @@
         "//:MODULE.bazel",
     ],
 )
+
+sh_test(
+    name = "host_constraints_test",
+    srcs = ["host_constraints_test.sh"],
+    env = {"ACTUAL_HOST_CONSTRAINTS": repr(HOST_CONSTRAINTS)},
+    env_inherit = ["EXPECTED_HOST_CONSTRAINTS"],
+)
diff --git a/tests/host_constraints_test.sh b/tests/host_constraints_test.sh
new file mode 100755
index 0000000..40535b8
--- /dev/null
+++ b/tests/host_constraints_test.sh
@@ -0,0 +1,3 @@
+echo actual host constraints: ${ACTUAL_HOST_CONSTRAINTS}
+echo expected host constraints: ${EXPECTED_HOST_CONSTRAINTS}
+test "${ACTUAL_HOST_CONSTRAINTS}" == "${EXPECTED_HOST_CONSTRAINTS}"
diff --git a/version.bzl b/version.bzl
index 2068e00..a9fce33 100644
--- a/version.bzl
+++ b/version.bzl
@@ -13,4 +13,4 @@
 # limitations under the License.
 """The version of bazelbuild/platforms."""
 
-version = "0.0.8"
+version = "0.0.10"