tflite: Add Bazel skeleton with empty sample delegate

BUG=b:314854484
TEST=bazel build --config=host_clang \
  //delegate/sample:tensorflowlite_cros_sample_delegate

Change-Id: Ie54f034a16e9c62562284e84c15d35ee349a8d82
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/tflite/+/5267424
Reviewed-by: Tommy Chiang <ototot@google.com>
Commit-Queue: Shik Chen <shik@chromium.org>
Tested-by: Shik Chen <shik@chromium.org>
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..a5a3d60
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,13 @@
+# cros-bazel.eclass does not support bzlmod yet.
+# Disable it to avoid generating MODULE.bazel file.
+common --noexperimental_enable_bzlmod
+
+# Required by TensorFlow.
+common --experimental_repo_remote_exec
+
+# Use --config=host_clang to build things with clang on host.
+build:host_clang --cxxopt=-std=gnu++20
+build:host_clang --repo_env=CC=clang
+
+# Ignore warnings from dependencies.
+build:host_clang --per_file_copt=external/.*@-Wno-everything
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b3c6256
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+# Compilation database for clangd
+/compile_commands.json
+
+# Artifacts from bazel
+/.cache
+/bazel-*
+/external
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..f0fb825
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,6 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# We don't have a root level rule yet. This is currently just an empty package
+# marker file.
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
new file mode 100644
index 0000000..65139ed
--- /dev/null
+++ b/WORKSPACE.bazel
@@ -0,0 +1,53 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+workspace(name = "cros_tflite")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+# Update `bazel_external_uris` in ebuild as well when upgrading TensorFlow, and
+# all the required dependencies need to be upload to our mirror first.
+TENSORFLOW_VERSION = "2.15.0"
+
+http_archive(
+    name = "org_tensorflow",
+    sha256 = "f771db8d96ca13c72f73c85c9cfb6f5358e2de3dd62a97a9ae4b672fe4c6d094",
+    strip_prefix = "tensorflow-{}".format(TENSORFLOW_VERSION),
+    url = "https://github.com/tensorflow/tensorflow/archive/v{}.zip".format(TENSORFLOW_VERSION),
+)
+
+# Python is required before initializing TensorFlow.
+http_archive(
+    name = "rules_python",
+    sha256 = "9d04041ac92a0985e344235f5d946f71ac543f1b1565f2cdbc9a2aaee8adf55b",
+    strip_prefix = "rules_python-0.26.0",
+    url = "https://github.com/bazelbuild/rules_python/releases/download/0.26.0/rules_python-0.26.0.tar.gz",
+)
+
+load("@rules_python//python:repositories.bzl", "py_repositories")
+py_repositories()
+
+load(
+    "@org_tensorflow//tensorflow/tools/toolchains/python:python_repo.bzl",
+    "python_repository",
+)
+python_repository(name = "python_version_repo")
+
+load("@python_version_repo//:py_version.bzl", "HERMETIC_PYTHON_VERSION")
+load("@rules_python//python:repositories.bzl", "python_register_toolchains")
+python_register_toolchains(
+    name = "python",
+    ignore_root_user_error = True,
+    python_version = HERMETIC_PYTHON_VERSION,
+)
+
+# Initialize TensorFlow and its external dependencies.
+load("@org_tensorflow//tensorflow:workspace3.bzl", "tf_workspace3")
+tf_workspace3()
+load("@org_tensorflow//tensorflow:workspace2.bzl", "tf_workspace2")
+tf_workspace2()
+load("@org_tensorflow//tensorflow:workspace1.bzl", "tf_workspace1")
+tf_workspace1()
+load("@org_tensorflow//tensorflow:workspace0.bzl", "tf_workspace0")
+tf_workspace0()
diff --git a/delegate/sample/BUILD.bazel b/delegate/sample/BUILD.bazel
new file mode 100644
index 0000000..7509002
--- /dev/null
+++ b/delegate/sample/BUILD.bazel
@@ -0,0 +1,34 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+load("@org_tensorflow//tensorflow/lite:build_def.bzl", "tflite_cc_shared_object", "tflite_copts")
+load("@org_tensorflow//tensorflow/lite/core/shims:cc_library_with_tflite.bzl", "cc_library_with_tflite")
+
+cc_library_with_tflite(
+    name = "external",
+    srcs = [
+        "external.cc",
+    ],
+    copts = tflite_copts(),
+    generate_opaque_delegate_target = True,
+    tflite_deps = [
+        "@org_tensorflow//tensorflow/lite/acceleration/configuration/c:delegate_plugin",
+        "@org_tensorflow//tensorflow/lite/acceleration/configuration/c:stable_delegate",
+        "@org_tensorflow//tensorflow/lite/c:common",
+        "@org_tensorflow//tensorflow/lite/delegates/utils/experimental/stable_delegate:stable_delegate_interface",
+    ],
+)
+
+tflite_cc_shared_object(
+    name = "tensorflowlite_cros_sample_delegate",
+    linkopts = [
+        "-Wl,--no-undefined",
+        # Expose necessary symbols only.
+        "-Wl,--version-script,$(location @org_tensorflow//tensorflow/lite/delegates/utils/experimental/stable_delegate:version_script.lds)",
+    ],
+    deps = [
+        ":external_opaque_delegate",
+        "@org_tensorflow//tensorflow/lite/delegates/utils/experimental/stable_delegate:version_script.lds",
+    ],
+)
diff --git a/delegate/sample/README.md b/delegate/sample/README.md
new file mode 100644
index 0000000..a329976
--- /dev/null
+++ b/delegate/sample/README.md
@@ -0,0 +1,5 @@
+# ChromeOS Sample Delegate
+
+This is a sample stable delegate tailored for ChromeOS. Some implementation are
+adapted from the sample in upstream TensorFlow
+https://github.com/tensorflow/tensorflow/tree/HEAD/tensorflow/lite/delegates/utils/experimental/sample_stable_delegate.
diff --git a/delegate/sample/external.cc b/delegate/sample/external.cc
new file mode 100644
index 0000000..6b78682
--- /dev/null
+++ b/delegate/sample/external.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tensorflow/lite/core/acceleration/configuration/c/delegate_plugin.h"
+#include "tensorflow/lite/core/acceleration/configuration/c/stable_delegate.h"
+#include "tensorflow/lite/core/c/common.h"
+#include "tensorflow/lite/delegates/utils/experimental/stable_delegate/stable_delegate_interface.h"
+
+namespace tflite::cros {
+
+namespace {
+
+TfLiteOpaqueDelegate* CreateFunc(const void* tflite_settings) {
+  // TODO(shik): Implement this.
+  return nullptr;
+}
+
+void DestroyFunc(TfLiteOpaqueDelegate* delegate) {
+  // TODO(shik): Implement this.
+}
+
+int ErrnoFunc(TfLiteOpaqueDelegate* delegate) {
+  // TODO(shik): Implement this.
+  return 0;
+}
+
+constexpr TfLiteOpaqueDelegatePlugin plugin = {
+    .create = CreateFunc,
+    .destroy = DestroyFunc,
+    .get_delegate_errno = ErrnoFunc,
+};
+
+constexpr TfLiteStableDelegate cros_sample_delegate = {
+    .delegate_abi_version = TFL_STABLE_DELEGATE_ABI_VERSION,
+    .delegate_name = "cros_sample_delegate",
+    .delegate_version = "0.0.1",
+    .delegate_plugin = &plugin,
+};
+
+}  // namespace
+
+}  // namespace tflite::cros
+
+extern "C" constexpr TfLiteStableDelegate TFL_TheStableDelegate =
+    tflite::cros::cros_sample_delegate;