Add remaining changes for bootstrap build on OpenBSD.

I have tested these changes via a bootstrap build on OpenBSD 6.6-current (amd64 architecture). The resulting `bazel` binary appeared to work in some simple testing involving `cc_library`, `cc_binary`, `java_library`, and `java_binary`.

Known issues/limitations:

- Building a `java_binary`'s deploy JAR fails because the `singlejar` tool fails to build. I intend to investigate soon.

- Running Bazel requires a `--host_javabase=@local_jdk//:jdk` flag.

- Sandboxing is unsupported.

This change, split out of the larger PR https://github.com/bazelbuild/bazel/pull/10274, is part of the OpenBSD port in https://github.com/bazelbuild/bazel/issues/10250. Most of the changes in that larger PR have already been committed via several smaller PRs (see the PRs linked from https://github.com/bazelbuild/bazel/issues/10250). This PR collects the remaining changes.

Closes #10567.

PiperOrigin-RevId: 290745757
diff --git a/scripts/bootstrap/buildenv.sh b/scripts/bootstrap/buildenv.sh
index a807af4..5f0c003 100755
--- a/scripts/bootstrap/buildenv.sh
+++ b/scripts/bootstrap/buildenv.sh
@@ -93,6 +93,11 @@
   JAVA_HOME="${JAVA_HOME:-/usr/local/openjdk8}"
   ;;
 
+openbsd)
+  # JAVA_HOME must point to a Java installation.
+  JAVA_HOME="${JAVA_HOME:-/usr/local/jdk-1.8.0}"
+  ;;
+
 darwin)
   if [[ -z "$JAVA_HOME" ]]; then
     JAVA_HOME="$(/usr/libexec/java_home -v ${JAVA_VERSION}+ 2> /dev/null)" \
diff --git a/scripts/packages/BUILD b/scripts/packages/BUILD
index 8a8a4c7..71d1705 100644
--- a/scripts/packages/BUILD
+++ b/scripts/packages/BUILD
@@ -1,3 +1,5 @@
+load(":self_extract_binary.bzl", "self_extract_binary")
+
 package(default_visibility = ["//scripts/packages:__subpackages__"])
 
 filegroup(
@@ -20,6 +22,7 @@
             ":zip-bazel-exe_nojdk",
         ],
         "//src/conditions:freebsd": [],
+        "//src/conditions:openbsd": [],
         "//src/conditions:darwin": [
             ":with-jdk/install.sh",
             ":without-jdk/install.sh",
@@ -120,8 +123,6 @@
     cmd = "mkdir -p $$(dirname $@); cp $< $@",
 )
 
-load(":self_extract_binary.bzl", "self_extract_binary")
-
 [self_extract_binary(
     name = "%s/install.sh" % kind,
     flatten_resources = [
diff --git a/scripts/packages/template_bin.sh b/scripts/packages/template_bin.sh
index ca97e72..0c27a4d 100755
--- a/scripts/packages/template_bin.sh
+++ b/scripts/packages/template_bin.sh
@@ -115,6 +115,10 @@
       JAVA_HOME="/usr/local/openjdk8"
       BASHRC="~/.bashrc"
       ;;
+    openbsd)
+      JAVA_HOME="/usr/local/jdk-1.8.0"
+      BASHRC="~/.bashrc"
+      ;;
     darwin)
       JAVA_HOME="$(/usr/libexec/java_home -v ${JAVA_VERSION}+ 2> /dev/null)" || true
       BASHRC="~/.bash_profile"
diff --git a/src/BUILD b/src/BUILD
index a85a9ac..ab7c6a3 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -6,8 +6,9 @@
 
 exports_files(["jdeps_modules.golden"])
 
-# Keep only the first 32 chars (a hex md5sum) and no trailing newline.
-md5_cmd = "set -e -o pipefail && echo $(SRCS) | sort | xargs %s | %s | head -c 32 > $@"
+# We avoid using the `head` tool's `-c` option, since it does not exist on
+# OpenBSD; here we use `dd` instead.
+md5_cmd = "set -e -o pipefail && echo $(SRCS) | sort | xargs %s | %s | dd bs=32 count=1 > $@"
 
 # TODO(bazel-team): find a better way to handle dylib extensions.
 filegroup(
@@ -40,6 +41,7 @@
         "//src/conditions:darwin": md5_cmd % ("/sbin/md5", "/sbin/md5"),
         "//src/conditions:darwin_x86_64": md5_cmd % ("/sbin/md5", "/sbin/md5"),
         "//src/conditions:freebsd": md5_cmd % ("/sbin/md5", "/sbin/md5"),
+        "//src/conditions:openbsd": md5_cmd % ("/bin/md5", "/bin/md5"),
         "//conditions:default": md5_cmd % ("md5sum", "md5sum"),
     }),
 ) for suffix, embedded_tools_target in {
@@ -354,8 +356,8 @@
         ],
     }),
     outs = ["package" + suffix + ".zip"],
-    cmd = "$(location :package-bazel.sh) $@ " + ("" if embed else "''") + " $(SRCS)",
-    tools = ["package-bazel.sh"],
+    cmd = "$(location :package_bazel_on_host_platform) $@ " + ("" if embed else "''") + " $(SRCS)",
+    tools = [":package_bazel_on_host_platform"],
 ) for suffix, embed in [
     ("_jdk_allmodules", True),
     ("_jdk_minimal", True),
@@ -365,6 +367,16 @@
 ]]
 
 genrule(
+    name = "package_bazel_on_host_platform",
+    srcs = ["package-bazel.sh"],
+    outs = ["package-bazel-on-host-platform.sh"],
+    cmd = select({
+        "//src/conditions:openbsd": "cat $(SRCS) | sed -e 's@#!/bin/bash@#!/usr/local/bin/bash@' > $@",
+        "//conditions:default": "cp $(SRCS) $@",
+    }),
+)
+
+genrule(
     name = "platforms_archive",
     srcs = ["@platforms//:srcs"],
     outs = ["platforms.zip"],
diff --git a/src/main/cpp/blaze_util_bsd.cc b/src/main/cpp/blaze_util_bsd.cc
index 7b8da01..954c8f0 100644
--- a/src/main/cpp/blaze_util_bsd.cc
+++ b/src/main/cpp/blaze_util_bsd.cc
@@ -128,7 +128,7 @@
   // Otherwise, if argv[0] contains a slash, then it's a relative path. Prepend
   // the current directory to form an absolute path.
   if (argv0str.length() > 0 && argv0str.find('/') != std::string::npos) {
-    return GetCwd() + "/" + argv0str;
+    return blaze_util::GetCwd() + "/" + argv0str;
   }
 
   // TODO(aldersondrive): Try to find the executable by inspecting the PATH.
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE
index 4ece3d9..8a0c823 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/jdk.WORKSPACE
@@ -45,6 +45,11 @@
 )
 
 bind(
+    name = "jni_md_header-openbsd",
+    actual = "@local_jdk//:jni_md_header-openbsd",
+)
+
+bind(
     name = "java",
     actual = "@local_jdk//:java",
 )
diff --git a/src/main/tools/BUILD b/src/main/tools/BUILD
index aa29cd4..cb2548c 100644
--- a/src/main/tools/BUILD
+++ b/src/main/tools/BUILD
@@ -1,7 +1,7 @@
-package(default_visibility = ["//src:__subpackages__"])
-
 load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
 
+package(default_visibility = ["//src:__subpackages__"])
+
 cc_binary(
     name = "daemonize",
     srcs = ["daemonize.c"],
@@ -67,6 +67,7 @@
         "//src/conditions:darwin": ["dummy-sandbox.c"],
         "//src/conditions:darwin_x86_64": ["dummy-sandbox.c"],
         "//src/conditions:freebsd": ["dummy-sandbox.c"],
+        "//src/conditions:openbsd": ["dummy-sandbox.c"],
         "//src/conditions:windows": ["dummy-sandbox.c"],
         "//conditions:default": [
             "linux-sandbox.cc",
@@ -82,6 +83,7 @@
         "//src/conditions:darwin": [],
         "//src/conditions:darwin_x86_64": [],
         "//src/conditions:freebsd": [],
+        "//src/conditions:openbsd": [],
         "//src/conditions:windows": [],
         "//conditions:default": [
             ":logging",
diff --git a/src/main/tools/jdk.BUILD b/src/main/tools/jdk.BUILD
index 47e3e00..0cd0b36 100644
--- a/src/main/tools/jdk.BUILD
+++ b/src/main/tools/jdk.BUILD
@@ -33,6 +33,12 @@
 )
 
 filegroup(
+    name = "jni_md_header-openbsd",
+    srcs = ["include/openbsd/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
     name = "jni_md_header-windows",
     srcs = ["include/win32/jni_md.h"],
     deprecation = DEPRECATION_MESSAGE,
diff --git a/src/main/tools/process-wrapper-legacy.h b/src/main/tools/process-wrapper-legacy.h
index 5cea547..943c4c1 100644
--- a/src/main/tools/process-wrapper-legacy.h
+++ b/src/main/tools/process-wrapper-legacy.h
@@ -21,7 +21,7 @@
 // The process-wrapper implementation that was used until and including Bazel
 // 0.4.5. Waits for the wrapped process to exit and then kills its process
 // group. Works on all POSIX operating systems (tested on Linux, macOS,
-// FreeBSD).
+// FreeBSD, and OpenBSD).
 //
 // Caveats:
 // - Killing just the process group of the spawned child means that daemons or
diff --git a/src/test/shell/bazel/remote/remote_execution_test.sh b/src/test/shell/bazel/remote/remote_execution_test.sh
index 6cd0426..822900f 100755
--- a/src/test/shell/bazel/remote/remote_execution_test.sh
+++ b/src/test/shell/bazel/remote/remote_execution_test.sh
@@ -97,7 +97,7 @@
 
 function test_remote_grpc_via_unix_socket() {
   case "$PLATFORM" in
-  darwin|freebsd|linux)
+  darwin|freebsd|linux|openbsd)
     ;;
   *)
     return 0
diff --git a/src/test/shell/shell_utils.sh b/src/test/shell/shell_utils.sh
index 8b0491b..8997d87 100755
--- a/src/test/shell/shell_utils.sh
+++ b/src/test/shell/shell_utils.sh
@@ -110,7 +110,7 @@
 function md5_file() {
   if [ $# -gt 0 ]; then
     local result=""
-    if [[ ${PLATFORM} == "darwin" ]] || [[ ${PLATFORM} == "freebsd" ]]; then
+    if [[ ${PLATFORM} == "darwin" ]] || [[ ${PLATFORM} == "freebsd" ]] || [[ ${PLATFORM} == "openbsd" ]]; then
       result=$(md5 -q $@ || echo)
     else
       result=$(md5sum $@ | awk '{print $1}' || echo)
diff --git a/src/test/shell/unittest.bash b/src/test/shell/unittest.bash
index d87d636..dbefe6d 100644
--- a/src/test/shell/unittest.bash
+++ b/src/test/shell/unittest.bash
@@ -734,9 +734,14 @@
     function timestamp() {
       echo $(($(date +%s%N)/1000000))
     }
+elif [[ "$UNAME" = "openbsd" ]]; then
+    function timestamp() {
+      # OpenBSD does not have %N, so Python is the best we can do.
+      python3 -c 'import time; print(int(round(time.time() * 1000)))'
+    }
 else
     function timestamp() {
-      # OS X and FreeBSD do not have %N so python is the best we can do
+      # OS X and FreeBSD do not have %N, so Python is the best we can do.
       python -c 'import time; print(int(round(time.time() * 1000)))'
     }
 fi
diff --git a/src/tools/singlejar/diag.h b/src/tools/singlejar/diag.h
index c4ac36b..9120911 100644
--- a/src/tools/singlejar/diag.h
+++ b/src/tools/singlejar/diag.h
@@ -19,7 +19,8 @@
  * Various useful diagnostics functions from Linux err.h file, wrapped
  * for portability.
  */
-#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
+#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || \
+    defined(__OpenBSD__)
 
 #include <err.h>
 #define diag_err(...) err(__VA_ARGS__)
diff --git a/src/tools/singlejar/mapped_file_posix.inc b/src/tools/singlejar/mapped_file_posix.inc
index ae29a3c..d59de00 100644
--- a/src/tools/singlejar/mapped_file_posix.inc
+++ b/src/tools/singlejar/mapped_file_posix.inc
@@ -24,8 +24,9 @@
 
 #include "src/tools/singlejar/diag.h"
 
-// The implementation is 64-bit Linux or OSX specific.
-#if !((defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)) && \
+// The implementation is specific to 64-bit Linux / OS X / BSD.
+#if !((defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+       defined(__OpenBSD__)) &&                                            \
       __SIZEOF_POINTER__ == 8)
 #error This code for 64 bit Unix.
 #endif
diff --git a/src/tools/singlejar/zip_headers.h b/src/tools/singlejar/zip_headers.h
index c76e15b..e8cd3e1 100644
--- a/src/tools/singlejar/zip_headers.h
+++ b/src/tools/singlejar/zip_headers.h
@@ -27,7 +27,7 @@
 
 #if defined(__linux__)
 #include <endian.h>
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
 #include <sys/endian.h>
 #elif defined(__APPLE__) || defined(_WIN32)
 // Hopefully OSX and Windows will keep running solely on little endian CPUs, so:
diff --git a/tools/jdk/default_java_toolchain.bzl b/tools/jdk/default_java_toolchain.bzl
index 09961c2..cf4a2ff 100644
--- a/tools/jdk/default_java_toolchain.bzl
+++ b/tools/jdk/default_java_toolchain.bzl
@@ -61,7 +61,10 @@
         "@bazel_tools//tools/jdk:jdk_compiler_jar",
     ],
     "javac_supports_workers": 1,
-    "jvm_opts": JDK9_JVM_OPTS,
+    "jvm_opts": select({
+        "@bazel_tools//src/conditions:openbsd": JDK8_JVM_OPTS,
+        "//conditions:default": JDK9_JVM_OPTS,
+    }),
     "misc": DEFAULT_JAVACOPTS,
     "singlejar": ["@bazel_tools//tools/jdk:singlejar"],
     "bootclasspath": ["@bazel_tools//tools/jdk:platformclasspath"],
diff --git a/tools/platforms/BUILD b/tools/platforms/BUILD
index aedc392..e372d62 100644
--- a/tools/platforms/BUILD
+++ b/tools/platforms/BUILD
@@ -74,6 +74,11 @@
 )
 
 alias(
+    name = "openbsd",
+    actual = "@platforms//os:openbsd",
+)
+
+alias(
     name = "android",
     actual = "@platforms//os:android",
 )
@@ -109,6 +114,7 @@
     os_constraints = [
         "@platforms//os:osx",
         "@platforms//os:freebsd",
+        "@platforms//os:openbsd",
         "@platforms//os:linux",
         "@platforms//os:windows",
     ],
@@ -129,6 +135,7 @@
     os_constraints = [
         "@platforms//os:osx",
         "@platforms//os:freebsd",
+        "@platforms//os:openbsd",
         "@platforms//os:linux",
         "@platforms//os:windows",
     ],
diff --git a/tools/platforms/BUILD.tools b/tools/platforms/BUILD.tools
index f7eece8..73011dab 100644
--- a/tools/platforms/BUILD.tools
+++ b/tools/platforms/BUILD.tools
@@ -62,6 +62,11 @@
 )
 
 alias(
+    name = "openbsd",
+    actual = "@platforms//os:openbsd",
+)
+
+alias(
     name = "android",
     actual = "@platforms//os:android",
 )
@@ -97,6 +102,7 @@
     os_constraints = [
         "@platforms//os:osx",
         "@platforms//os:freebsd",
+        "@platforms//os:openbsd",
         "@platforms//os:linux",
         "@platforms//os:windows",
     ],
@@ -117,6 +123,7 @@
     os_constraints = [
         "@platforms//os:osx",
         "@platforms//os:freebsd",
+        "@platforms//os:openbsd",
         "@platforms//os:linux",
         "@platforms//os:windows",
     ],