Add flags for ccache

This add support of toggling on ccache.

A rebuild of @portage//target/sys-apps/attr, after modifying
things like build_package, takes 2600 seconds with ccache
instead of 4000 seconds on my workstation.

Some stats after 1 cold + 1 warm cache build:
% CCACHE_DIR=$HOME/ccache ccache --print-stats
autoconf_test   3596
bad_compiler_arguments  174
bad_output_file 0
cache_miss      43037
cache_size_kibibyte     1117400
called_for_link 4210
called_for_preprocessing        3144
cleanups_performed      0
compile_failed  820
compiler_check_failed   0
compiler_produced_empty_output  24
compiler_produced_no_output     0
compiler_produced_stdout        0
could_not_find_compiler 0
could_not_use_modules   0
could_not_use_precompiled_header        0
direct_cache_hit        48125
direct_cache_miss       47024
disabled        2
error_hashing_extra_file        0
files_in_cache  84016
internal_error  0
local_storage_hit       51048
local_storage_miss      43037
local_storage_read_hit  100823
local_storage_read_miss 89221
local_storage_write     86388
missing_cache_file      0
multiple_source_files   4
no_input_file   6732
output_to_stdout        6
preprocessed_cache_hit  2923
preprocessed_cache_miss 43881
preprocessor_error      216
recache 0
remote_storage_error    0
remote_storage_hit      0
remote_storage_miss     0
remote_storage_read_hit 0
remote_storage_read_miss        0
remote_storage_timeout  0
remote_storage_write    0
stats_updated_timestamp 1705452543
stats_zeroed_timestamp  0
unsupported_code_directive      4
unsupported_compiler_option     152
unsupported_environment_variable        0
unsupported_source_language     4

BUG=b:308409836
TEST=BOARD=amd64-generic bazel build @portage//target/sys-apps/attr --//bazel/portage:ccache --//bazel/portage:ccache_dir=$HOME/ccache

Cq-Depend: chromium:4999889
Change-Id: I8a5d483221e128d5f99efa7ed91e303817404b05
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/bazel/+/5009669
Commit-Queue: Li-Yu Yu <aaronyu@google.com>
Tested-by: Li-Yu Yu <aaronyu@google.com>
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
diff --git a/portage/BUILD.bazel b/portage/BUILD.bazel
index 2b41148..7d16963 100644
--- a/portage/BUILD.bazel
+++ b/portage/BUILD.bazel
@@ -129,3 +129,15 @@
         ":omit_ebuild_src": "False",
     },
 )
+
+bool_flag(
+    name = "ccache",
+    build_setting_default = False,
+    visibility = ["//visibility:public"],
+)
+
+string_flag(
+    name = "ccache_dir",
+    build_setting_default = "",
+    visibility = ["//visibility:public"],
+)
diff --git a/portage/build_defs/ebuild.bzl b/portage/build_defs/ebuild.bzl
index 79d844f..9175540 100644
--- a/portage/build_defs/ebuild.bzl
+++ b/portage/build_defs/ebuild.bzl
@@ -12,6 +12,9 @@
 load("//bazel/portage/build_defs:package_contents.bzl", "generate_contents")
 load("//bazel/transitions:primordial.bzl", "primordial_transition")
 
+_CCACHE_LABEL = "//bazel/portage:ccache"
+_CCACHE_DIR_LABEL = "//bazel/portage:ccache_dir"
+
 # The stage1 SDK will need to be built with ebuild_primordial.
 # After that, they can use the ebuild rule.
 # This ensures that we don't build the stage1 targets twice.
@@ -190,6 +193,14 @@
         executable = True,
         cfg = "exec",
     ),
+    _ccache = attr.label(
+        default = Label(_CCACHE_LABEL),
+        providers = [BuildSettingInfo],
+    ),
+    _ccache_dir = attr.label(
+        default = Label(_CCACHE_DIR_LABEL),
+        providers = [BuildSettingInfo],
+    ),
 )
 
 def _bashrc_to_path(bashrc):
@@ -328,6 +339,24 @@
         caches_dir = paths.dirname(cache_marker_path)
         args.add("--incremental-cache-dir=%s/portage" % caches_dir)
 
+    # --ccache-dir
+    ccache_dir = ctx.attr._ccache_dir[BuildSettingInfo].value
+    if ccache_dir:
+        if not ccache_dir.startswith("/"):
+            fail("%s=%r is not an absolute path" % (_CCACHE_DIR_LABEL, ccache_dir))
+
+        # Always pass --ccache-dir regardless of --ccache.
+        # So people can also enable ccache with the ebuld_debug script,
+        # without worrying about the ccache directory.
+        args.add(ccache_dir, format = "--ccache-dir=%s")
+
+    # --ccache
+    ccache = ctx.attr._ccache[BuildSettingInfo].value
+    if ccache:
+        if not ccache_dir:
+            fail("%s set but %s not set" % (_CCACHE_LABEL, _CCACHE_DIR_LABEL))
+        args.add("--ccache")
+
     # --use-flags
     if ctx.attr.inject_use_flags:
         args.add_joined("--use-flags", ctx.attr.use_flags, join_with = ",")