Fork fdo rules bzl files
PiperOrigin-RevId: 791601077
Change-Id: Ie1fada81a29a228ba03ce9f328c77f405648f0a2
diff --git a/cc/extensions.bzl b/cc/extensions.bzl
index 4b06794..11abe00 100644
--- a/cc/extensions.bzl
+++ b/cc/extensions.bzl
@@ -41,6 +41,10 @@
load("@rules_cc//cc/private/rules_impl:cc_test.bzl", _cc_test = "cc_test")
load("@rules_cc//cc/private/rules_impl:objc_import.bzl", _objc_import = "objc_import")
load("@rules_cc//cc/private/rules_impl:objc_library.bzl", _objc_library = "objc_library")
+load("@rules_cc//cc/private/rules_impl:fdo/fdo_prefetch_hints.bzl", _fdo_prefetch_hints = "fdo_prefetch_hints")
+load("@rules_cc//cc/private/rules_impl:fdo/fdo_profile.bzl", _fdo_profile = "fdo_profile")
+load("@rules_cc//cc/private/rules_impl:fdo/memprof_profile.bzl", _memprof_profile = "memprof_profile")
+load("@rules_cc//cc/private/rules_impl:fdo/propeller_optimize.bzl", _propeller_optimize = "propeller_optimize")
cc_binary = _cc_binary
cc_import = _cc_import
@@ -50,6 +54,10 @@
cc_test = _cc_test
objc_import = _objc_import
objc_library = _objc_library
+fdo_prefetch_hints = _fdo_prefetch_hints
+fdo_profile = _fdo_profile
+memprof_profile = _memprof_profile
+propeller_optimize = _propeller_optimize
""",
)
else:
@@ -64,6 +72,10 @@
cc_test = native.cc_test
objc_import = native.objc_import
objc_library = native.objc_library
+fdo_prefetch_hints = native.fdo_prefetch_hints
+fdo_profile = native.fdo_profile
+memprof_profile = getattr(native, "memprof_profile", None) # only in Bazel 7+
+propeller_optimize = native.propeller_optimize
""",
)
diff --git a/cc/private/rules_impl/fdo/fdo_context.bzl b/cc/private/rules_impl/fdo/fdo_context.bzl
new file mode 100644
index 0000000..4f4bc97
--- /dev/null
+++ b/cc/private/rules_impl/fdo/fdo_context.bzl
@@ -0,0 +1,469 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""FDO context describes how C++ FDO compilation should be done."""
+
+load("@bazel_skylib//lib:paths.bzl", "paths")
+load("//cc/common:cc_common.bzl", "cc_common")
+load(":fdo/fdo_prefetch_hints.bzl", "FdoPrefetchHintsInfo")
+load(":fdo/fdo_profile.bzl", "FdoProfileInfo")
+load(":fdo/memprof_profile.bzl", "MemProfProfileInfo")
+load(":fdo/propeller_optimize.bzl", "PropellerOptimizeInfo")
+
+def _create_fdo_context(
+ ctx,
+ *,
+ llvm_profdata,
+ all_files,
+ zipper,
+ cc_toolchain_config_info,
+ coverage_enabled,
+ _fdo_prefetch_hints,
+ _propeller_optimize,
+ _memprof_profile,
+ _fdo_optimize,
+ _fdo_profile,
+ _xfdo_profile,
+ _csfdo_profile,
+ _proto_profile):
+ """Creates FDO context when it should be available.
+
+ When `-c opt` is used it parses values of FDO related flags, processes the
+ input Files and return Files ready to be used for FDO.
+
+ Args:
+ ctx: (SubruleContext) used to create actions and obtain configuration
+ llvm_profdata: (File) llvm-profdata executable
+ all_files: (depset(File)) Files needed to run llvm-profdata
+ zipper: (File) zip tool, used to unpact the profiles
+ cc_toolchain_config_info: (CcToolchainConfigInfo) Used to check CPU value, should be removed
+ coverage_enabled: (bool) Is code coverage enabled
+ _fdo_prefetch_hints: (Target) Pointed to by --fdo_prefetch_hints
+ _propeller_optimize: (Target) Pointed to by --propeller_optimize
+ _memprof_profile: (Target) Pointed to by --memprof_profile
+ _fdo_optimize: (Target) Pointed to by --fdo_optimize
+ _fdo_profile: (Target) Pointed to by --fdo_profile
+ _xfdo_profile: (Target) Pointed to by --xbinary_fdo
+ _csfdo_profile: (Target) Pointed to by --cs_fdo_profile
+ _proto_profile: (Target) Pointed to by --proto_profile_path
+ Returns:
+ (FDOContext) A structure with following fields:
+ - branch_fdo_profile (struct|None)
+ - branch_fdo_mode ("auto_fdo"|"xbinary_fdo"|"llvm_fdo"|llvm_cs_fdo")
+ - profile_artifact (File)
+ - proto_profile_artifact (File)
+ - prefetch_hints_artifact (File),
+ - propeller_optimize_info (PropellerOptimizeInfo)
+ - memprof_profile_artifact (File)
+ """
+ cpp_config = ctx.fragments.cpp
+ if cpp_config.compilation_mode() != "opt":
+ return struct()
+
+ # Propeller optimize cc and ld profiles
+ cc_profile = _symlink_to(
+ ctx,
+ name_prefix = "fdo",
+ absolute_path = cpp_config.propeller_optimize_absolute_cc_profile(),
+ progress_message = "Symlinking LLVM Propeller Profile %{input}",
+ )
+ ld_profile = _symlink_to(
+ ctx,
+ name_prefix = "fdo",
+ absolute_path = cpp_config.propeller_optimize_absolute_ld_profile(),
+ progress_message = "Symlinking LLVM Propeller Profile %{input}",
+ )
+ if cc_profile or ld_profile:
+ propeller_optimize_info = PropellerOptimizeInfo(
+ cc_profile = cc_profile,
+ ld_profile = ld_profile,
+ )
+ elif _propeller_optimize:
+ propeller_optimize_info = _propeller_optimize[PropellerOptimizeInfo]
+ else:
+ propeller_optimize_info = None
+
+ # Attempt to fetch the memprof profile input from an explicit flag or as part of the
+ # fdo_profile rule. The former overrides the latter. Also handle the case where the
+ # fdo_profile rule is specified using fdo_optimize.
+ mem_prof_profile = None
+ if _memprof_profile:
+ mem_prof_profile = _memprof_profile[MemProfProfileInfo]
+ elif _fdo_profile and _fdo_profile[FdoProfileInfo].memprof_artifact:
+ mem_prof_profile = MemProfProfileInfo(artifact = _fdo_profile[FdoProfileInfo].memprof_artifact)
+ elif _fdo_optimize and FdoProfileInfo in _fdo_optimize and _fdo_optimize[FdoProfileInfo].memprof_artifact:
+ mem_prof_profile = MemProfProfileInfo(artifact = _fdo_optimize[FdoProfileInfo].memprof_artifact)
+ elif _xfdo_profile and FdoProfileInfo in _xfdo_profile and _xfdo_profile[FdoProfileInfo].memprof_artifact:
+ # This is needed for configless AutoFDO which supplies the profile via a select statement in the XFDO profile.
+ # We don't intend to support actual XFDO with memprof.
+ mem_prof_profile = MemProfProfileInfo(artifact = _xfdo_profile[FdoProfileInfo].memprof_artifact)
+
+ fdo_inputs = None
+ if cpp_config.fdo_path():
+ # TODO(b/333997009): computation of cpp_config.fdo_path in CppConfiguration class is convoluted, simplify it
+ # fdoZip should be set if the profile is a path, fdoInputFile if it is an artifact, but never both
+ fdo_inputs = FdoProfileInfo(absolute_path = cpp_config.fdo_path())
+ elif _fdo_optimize:
+ if FdoProfileInfo in _fdo_optimize:
+ fdo_inputs = _fdo_optimize[FdoProfileInfo]
+ elif _fdo_optimize[DefaultInfo].files:
+ if len(_fdo_optimize[DefaultInfo].files.to_list()) != 1:
+ fail("--fdo_optimize does not point to a single target")
+ [fdo_optimize_artifact] = _fdo_optimize[DefaultInfo].files.to_list()
+ if fdo_optimize_artifact.short_path != _fdo_optimize.label.package + "/" + _fdo_optimize.label.name:
+ fail("--fdo_optimize points to a target that is not an input file or an fdo_profile rule")
+ fdo_inputs = FdoProfileInfo(artifact = fdo_optimize_artifact)
+ elif _fdo_profile:
+ fdo_inputs = _fdo_profile[FdoProfileInfo]
+ elif _xfdo_profile:
+ fdo_inputs = _xfdo_profile[FdoProfileInfo]
+
+ cs_fdo_input = None
+ if cpp_config.cs_fdo_path():
+ cs_fdo_input = FdoProfileInfo(absolute_path = cpp_config.cs_fdo_path())
+ elif _csfdo_profile:
+ cs_fdo_input = _csfdo_profile[FdoProfileInfo]
+
+ # If --noproto_profile is in effect, there is no proto profile.
+ # If --proto_profile_path=<label> is passed, that profile is used.
+ # If AutoFDO is not in effect, no profile is used.
+ # If AutoFDO is in effect, a file called proto.profile next to the AutoFDO
+ # profile is used, if it exists.
+ proto_profile_artifact = None
+ if not cpp_config.proto_profile() and _proto_profile:
+ fail("--proto_profile_path cannot be set if --proto_profile is false")
+ if _proto_profile:
+ proto_profile_artifact = _symlink_to(
+ ctx,
+ name_prefix = "fdo",
+ artifact = _proto_profile,
+ progress_message = "Symlinking protobuf profile %{input}",
+ )
+ elif cpp_config.proto_profile():
+ proto_profile_artifact = getattr(fdo_inputs, "proto_profile_artifact", None)
+
+ branch_fdo_profile = None
+ if fdo_inputs:
+ branch_fdo_modes = {
+ ".afdo": "auto_fdo",
+ ".profdata": "llvm_fdo",
+ ".profraw": "llvm_fdo",
+ ".xfdo": "xbinary_fdo",
+ ".zip": "llvm_fdo",
+ }
+ extension = paths.split_extension(_basename(fdo_inputs))[1]
+ if extension not in branch_fdo_modes:
+ fail("invalid extension for FDO profile file")
+ branch_fdo_mode = branch_fdo_modes[extension]
+
+ if branch_fdo_mode == "llvm_fdo":
+ # Check if this is LLVM_CS_FDO
+ if cs_fdo_input:
+ branch_fdo_mode = "llvm_cs_fdo"
+
+ if _xfdo_profile:
+ fail("--xbinary_fdo only accepts *.xfdo and *.afdo")
+
+ if coverage_enabled:
+ fail("coverage mode is not compatible with FDO optimization")
+
+ # This tries to convert LLVM profiles to the indexed format if necessary.
+ if branch_fdo_mode == "llvm_fdo":
+ profile_artifact = _convert_llvm_raw_profile_to_indexed(
+ ctx,
+ "fdo",
+ fdo_inputs,
+ llvm_profdata,
+ all_files,
+ zipper,
+ cc_toolchain_config_info,
+ )
+ elif branch_fdo_mode in ["auto_fdo", "xbinary_fdo"]:
+ profile_artifact = _symlink_input(
+ ctx,
+ "fdo",
+ fdo_inputs,
+ "Symlinking FDO profile %{input}",
+ )
+ else: # branch_fdo_mode == "llvm_cs_fdo":
+ non_cs_profile_artifact = _convert_llvm_raw_profile_to_indexed(
+ ctx,
+ "fdo",
+ fdo_inputs,
+ llvm_profdata,
+ all_files,
+ zipper,
+ cc_toolchain_config_info,
+ )
+ cs_profile_artifact = _convert_llvm_raw_profile_to_indexed(
+ ctx,
+ "csfdo",
+ cs_fdo_input,
+ llvm_profdata,
+ all_files,
+ zipper,
+ cc_toolchain_config_info,
+ )
+ profile_artifact = _merge_llvm_profiles(
+ ctx,
+ "mergedfdo",
+ llvm_profdata,
+ all_files,
+ non_cs_profile_artifact,
+ cs_profile_artifact,
+ "MergedCS.profdata",
+ )
+
+ branch_fdo_profile = struct(
+ branch_fdo_mode = branch_fdo_mode,
+ profile_artifact = profile_artifact,
+ )
+
+ prefetch_hints_artifact = None
+ if _fdo_prefetch_hints:
+ prefetch_hints_artifact = _symlink_input(
+ ctx,
+ "fdo",
+ _fdo_prefetch_hints[FdoPrefetchHintsInfo],
+ "Symlinking LLVM Cache Prefetch Hints Profile %{input}",
+ )
+
+ memprof_profile_artifact = _get_mem_prof_profile_artifact(zipper, mem_prof_profile, ctx)
+
+ return struct(
+ branch_fdo_profile = branch_fdo_profile,
+ prefetch_hints_artifact = prefetch_hints_artifact,
+ propeller_optimize_info = propeller_optimize_info,
+ memprof_profile_artifact = memprof_profile_artifact,
+ proto_profile_artifact = proto_profile_artifact,
+ )
+
+def _convert_llvm_raw_profile_to_indexed(
+ ctx,
+ name_prefix,
+ fdo_inputs,
+ llvm_profdata,
+ all_files,
+ zipper,
+ cc_toolchain_config_info):
+ """This function checks the input profile format and converts it to the indexed format (.profdata) if necessary."""
+ basename = _basename(fdo_inputs)
+ if basename.endswith(".profdata"):
+ return _symlink_input(ctx, name_prefix, fdo_inputs, "Symlinking LLVM Profile %{input}")
+
+ if basename.endswith(".zip"):
+ if not zipper:
+ fail("Zipped profiles are not supported with platforms/toolchains before toolchain-transitions are implemented.")
+
+ zip_profile_artifact = _symlink_input(ctx, name_prefix, fdo_inputs, "Symlinking LLVM ZIP Profile %{input}")
+
+ # TODO(b/333997009): find a way to avoid hard-coding cpu architecture here
+ cpu = cc_toolchain_config_info.target_cpu()
+ if "k8" == cpu:
+ raw_profile_file_name = name_prefix + "/" + ctx.label.name + "/" + "fdocontrolz_profile.profraw"
+ else:
+ raw_profile_file_name = name_prefix + "/" + ctx.label.name + "/" + "fdocontrolz_profile-" + cpu + ".profraw"
+
+ raw_profile_artifact = ctx.actions.declare_file(raw_profile_file_name)
+
+ # We invoke different binaries depending on whether the unzip_fdo tool
+ # is available. When it isn't, unzip_fdo is aliased to the generic
+ # zipper tool, which takes different command-line arguments.
+
+ args = ctx.actions.args()
+ if zipper.path.endswith("unzip_fdo"):
+ args.add("--profile_zip", zip_profile_artifact)
+ args.add("--cpu", cpu)
+ args.add("--output_file", raw_profile_artifact)
+ else:
+ args.add("xf", zip_profile_artifact)
+ args.add("-d", raw_profile_artifact.dirname)
+ ctx.actions.run(
+ mnemonic = "LLVMUnzipProfileAction",
+ executable = zipper,
+ arguments = [args],
+ inputs = [zip_profile_artifact],
+ outputs = [raw_profile_artifact],
+ progress_message = "LLVMUnzipProfileAction: Generating %{output}",
+ )
+ else: # .profraw
+ raw_profile_artifact = _symlink_input(ctx, name_prefix, fdo_inputs, "Symlinking LLVM Raw Profile %{input}")
+
+ if not llvm_profdata:
+ fail("llvm-profdata not available with this crosstool, needed for profile conversion")
+
+ name = name_prefix + "/" + ctx.label.name + "/" + paths.replace_extension(basename, ".profdata")
+ profile_artifact = ctx.actions.declare_file(name)
+ ctx.actions.run(
+ mnemonic = "LLVMProfDataAction",
+ executable = llvm_profdata,
+ tools = [all_files],
+ arguments = [ctx.actions.args().add("merge").add("-o").add(profile_artifact).add(raw_profile_artifact)],
+ inputs = [raw_profile_artifact],
+ outputs = [profile_artifact],
+ use_default_shell_env = True,
+ progress_message = "LLVMProfDataAction: Generating %{output}",
+ )
+
+ return profile_artifact
+
+def _merge_llvm_profiles(
+ ctx,
+ name_prefix,
+ llvm_profdata,
+ all_files,
+ profile1,
+ profile2,
+ merged_output_name):
+ """This function merges profile1 and profile2 and generates merged_output."""
+ profile_artifact = ctx.actions.declare_file(name_prefix + "/" + ctx.label.name + "/" + merged_output_name)
+
+ # Merge LLVM profiles.
+ ctx.actions.run(
+ mnemonic = "LLVMProfDataMergeAction",
+ executable = llvm_profdata,
+ tools = [all_files],
+ arguments = [ctx.actions.args().add("merge").add("-o").add(profile_artifact).add(profile1).add(profile2)],
+ inputs = [profile1, profile2],
+ outputs = [profile_artifact],
+ use_default_shell_env = True,
+ progress_message = "LLVMProfDataAction: Generating %{output}",
+ )
+ return profile_artifact
+
+def _basename(inputs):
+ if getattr(inputs, "artifact", None):
+ return inputs.artifact.basename
+ else:
+ return paths.basename(inputs.absolute_path)
+
+def _symlink_input(ctx, name_prefix, fdo_inputs, progress_message, basename = None):
+ return _symlink_to(
+ ctx,
+ name_prefix,
+ progress_message,
+ getattr(fdo_inputs, "artifact", None),
+ getattr(fdo_inputs, "absolute_path", None),
+ basename,
+ )
+
+def _symlink_to(ctx, name_prefix, progress_message, artifact = None, absolute_path = None, basename = None):
+ """Symlinks either an absolute path or file to a unique location."""
+ if artifact:
+ if not basename:
+ basename = artifact.basename
+ name = name_prefix + "/" + ctx.label.name + "/" + basename
+ output = ctx.actions.declare_file(name)
+ ctx.actions.symlink(
+ output = output,
+ target_file = artifact,
+ progress_message = progress_message,
+ )
+ return output
+ elif absolute_path:
+ if not basename:
+ basename = paths.basename(absolute_path)
+ name = name_prefix + "/" + ctx.label.name + "/" + basename
+ output = ctx.actions.declare_file(name)
+ cc_common.absolute_symlink(
+ ctx = ctx,
+ output = output,
+ target_path = absolute_path,
+ progress_message = progress_message,
+ )
+ return output
+ else:
+ return None
+
+def _get_mem_prof_profile_artifact(zipper, memprof_profile, ctx):
+ """This function symlinks the memprof profile (after unzipping as needed)."""
+ if not memprof_profile:
+ return None
+
+ basename = _basename(memprof_profile)
+
+ # If the profile file is already in the desired format, symlink to it and return.
+ if basename.endswith(".profdata"):
+ return _symlink_input(ctx, "memprof", memprof_profile, "Symlinking MemProf Profile %{input}", basename = "memprof.profdata")
+
+ if not basename.endswith(".zip"):
+ fail("Expected zipped memprof profile.")
+
+ if not zipper:
+ fail("Zipped profiles are not supported with platforms/toolchains before " +
+ "toolchain-transitions are implemented.")
+
+ zip_profile_artifact = _symlink_input(ctx, "memprof", memprof_profile, "Symlinking MemProf ZIP Profile %{input}")
+
+ profile_artifact = ctx.actions.declare_file("memprof/" + ctx.label.name + "/memprof.profdata")
+
+ # We invoke different binaries depending on whether the unzip_fdo tool
+ # is available. When it isn't, unzip_fdo is aliased to the generic
+ # zipper tool, which takes different command-line arguments.
+ args = ctx.actions.args()
+ if zipper.path.endswith("unzip_fdo"):
+ args.add("--profile_zip", zip_profile_artifact)
+ args.add("--memprof")
+ args.add("--output_file", profile_artifact)
+ else:
+ args.add("xf", zip_profile_artifact)
+ args.add("-d", profile_artifact.dirname)
+ ctx.actions.run(
+ mnemonic = "LLVMUnzipProfileAction",
+ executable = zipper,
+ arguments = [args],
+ inputs = [zip_profile_artifact],
+ outputs = [profile_artifact],
+ progress_message = "MemProfUnzipProfileAction: Generating %{output}",
+ )
+ return profile_artifact
+
+create_fdo_context = subrule(
+ implementation = _create_fdo_context,
+ fragments = ["cpp"],
+ attrs = {
+ "_fdo_optimize": attr.label(
+ default = configuration_field(fragment = "cpp", name = "fdo_optimize"),
+ allow_files = True,
+ providers = [[DefaultInfo], [FdoProfileInfo]],
+ ),
+ "_xfdo_profile": attr.label(
+ default = configuration_field(fragment = "cpp", name = "xbinary_fdo"),
+ providers = [FdoProfileInfo],
+ ),
+ "_fdo_profile": attr.label(
+ default = configuration_field(fragment = "cpp", name = "fdo_profile"),
+ providers = [FdoProfileInfo],
+ ),
+ "_csfdo_profile": attr.label(
+ default = configuration_field(fragment = "cpp", name = "cs_fdo_profile"),
+ providers = [FdoProfileInfo],
+ ),
+ "_fdo_prefetch_hints": attr.label(
+ default = configuration_field(fragment = "cpp", name = "fdo_prefetch_hints"),
+ providers = [FdoPrefetchHintsInfo],
+ ),
+ "_propeller_optimize": attr.label(
+ default = configuration_field(fragment = "cpp", name = "propeller_optimize"),
+ providers = [PropellerOptimizeInfo],
+ ),
+ "_memprof_profile": attr.label(
+ default = configuration_field(fragment = "cpp", name = "memprof_profile"),
+ providers = [MemProfProfileInfo],
+ ),
+ "_proto_profile": attr.label(
+ default = configuration_field(fragment = "cpp", name = "proto_profile_path"),
+ allow_single_file = True,
+ ),
+ }, # buildifier: disable=unsorted-dict-items
+)
diff --git a/cc/private/rules_impl/fdo/fdo_prefetch_hints.bzl b/cc/private/rules_impl/fdo/fdo_prefetch_hints.bzl
new file mode 100644
index 0000000..6696b7b
--- /dev/null
+++ b/cc/private/rules_impl/fdo/fdo_prefetch_hints.bzl
@@ -0,0 +1,47 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Starlark implementation of fdo_prefetch_hints rule."""
+
+FdoPrefetchHintsInfo = provider(
+ doc = "Contains the profile used for prefetch hints",
+ fields = ["artifact"],
+)
+
+def _impl(ctx):
+ return FdoPrefetchHintsInfo(artifact = ctx.file.profile)
+
+fdo_prefetch_hints = rule(
+ implementation = _impl,
+ doc = """
+<p>Represents an FDO prefetch hints profile that is either in the workspace.
+Examples:</p>
+
+<pre><code class="lang-starlark">
+fdo_prefetch_hints(
+ name = "hints",
+ profile = "//path/to/hints:profile.afdo",
+)
+</code></pre>""",
+ attrs = {
+ "profile": attr.label(
+ allow_single_file = [".afdo"],
+ mandatory = True,
+ doc = """
+Label of the hints profile. The hints file has the .afdo extension
+The label can also point to an fdo_absolute_path_profile rule.""",
+ ),
+ },
+ provides = [FdoPrefetchHintsInfo],
+)
diff --git a/cc/private/rules_impl/fdo/fdo_profile.bzl b/cc/private/rules_impl/fdo/fdo_profile.bzl
new file mode 100644
index 0000000..3d0ccb8
--- /dev/null
+++ b/cc/private/rules_impl/fdo/fdo_profile.bzl
@@ -0,0 +1,61 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Starlark implementation of fdo_profile rule."""
+
+FdoProfileInfo = provider(
+ doc = "Contains the profile used for FDO",
+ fields = ["artifact", "absolute_path", "proto_profile_artifact", "memprof_artifact"],
+)
+
+def _impl(ctx):
+ return FdoProfileInfo(
+ artifact = ctx.file.profile,
+ proto_profile_artifact = ctx.file.proto_profile,
+ memprof_artifact = ctx.file.memprof_profile,
+ )
+
+fdo_profile = rule(
+ implementation = _impl,
+ doc = """
+
+<p>Represents an FDO profile that is in the workspace.
+Example:</p>
+
+<pre><code class="lang-starlark">
+fdo_profile(
+ name = "fdo",
+ profile = "//path/to/fdo:profile.zip",
+)
+</code></pre>""",
+ attrs = {
+ "profile": attr.label(
+ allow_single_file = [".profraw", ".profdata", ".zip", ".afdo", ".xfdo"],
+ mandatory = True,
+ doc = """
+Label of the FDO profile or a rule which generates it. The FDO file can have one of the
+following extensions: .profraw for unindexed LLVM profile, .profdata for indexed LLVM
+profile, .zip that holds an LLVM profraw profile, .afdo for AutoFDO profile, .xfdo for
+XBinary profile. The label can also point to an fdo_absolute_path_profile rule.""",
+ ),
+ "proto_profile": attr.label(allow_single_file = True, doc = """
+Label of the protobuf profile."""),
+ "memprof_profile": attr.label(allow_single_file = [".profdata", ".zip"], doc = """
+Label of the MemProf profile. The profile is expected to have
+either a .profdata extension (for an indexed/symbolized memprof
+profile), or a .zip extension for a zipfile containing a memprof.profdata
+file."""),
+ }, # buildifier: disable=unsorted-dict-items
+ provides = [FdoProfileInfo],
+)
diff --git a/cc/private/rules_impl/fdo/memprof_profile.bzl b/cc/private/rules_impl/fdo/memprof_profile.bzl
new file mode 100644
index 0000000..a2489f0
--- /dev/null
+++ b/cc/private/rules_impl/fdo/memprof_profile.bzl
@@ -0,0 +1,51 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Starlark implementation of memprof_profile rule."""
+
+MemProfProfileInfo = provider(
+ doc = "Contains the memprof profile",
+ fields = ["artifact"],
+)
+
+def _impl(ctx):
+ return MemProfProfileInfo(artifact = ctx.file.profile)
+
+memprof_profile = rule(
+ implementation = _impl,
+ doc = """
+<p>Represents a MEMPROF profile that is in the workspace.
+Example:</p>
+
+<pre><code class="lang-starlark">
+memprof_profile(
+ name = "memprof",
+ profile = "//path/to/memprof:profile.afdo",
+)
+
+</code></pre>""",
+ attrs = {
+ "profile": attr.label(
+ allow_single_file = [".profdata", ".zip"],
+ mandatory = True,
+ doc = """
+Label of the MEMPROF profile. The profile is expected to have
+either a .profdata extension (for an indexed/symbolized memprof
+profile), or a .zip extension for a zipfile containing a memprof.profdata
+file.
+The label can also point to an fdo_absolute_path_profile rule.""",
+ ),
+ },
+ provides = [MemProfProfileInfo],
+)
diff --git a/cc/private/rules_impl/fdo/propeller_optimize.bzl b/cc/private/rules_impl/fdo/propeller_optimize.bzl
new file mode 100644
index 0000000..3e3e8ce
--- /dev/null
+++ b/cc/private/rules_impl/fdo/propeller_optimize.bzl
@@ -0,0 +1,58 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Starlark implementation of propeller_optimize rule."""
+
+PropellerOptimizeInfo = provider(
+ doc = "Contains the profile used for propeller",
+ fields = ["cc_profile", "ld_profile"],
+)
+
+def _impl(ctx):
+ return PropellerOptimizeInfo(
+ cc_profile = ctx.file.cc_profile,
+ ld_profile = ctx.file.ld_profile,
+ )
+
+propeller_optimize = rule(
+ implementation = _impl,
+ doc = """
+<p>Represents a Propeller optimization profile in the workspace.
+Example:</p>
+
+<pre><code class="lang-starlark">
+propeller_optimize(
+ name = "layout",
+ cc_profile = "//path:cc_profile.txt",
+ ld_profile = "//path:ld_profile.txt"
+)
+</code></pre>""",
+ attrs = {
+ "cc_profile": attr.label(
+ allow_single_file = [".txt"],
+ mandatory = True,
+ doc = """
+Label of the profile passed to the various compile actions. This file has
+the .txt extension.""",
+ ),
+ "ld_profile": attr.label(
+ allow_single_file = [".txt"],
+ mandatory = True,
+ doc = """
+Label of the profile passed to the link action. This file has
+the .txt extension.""",
+ ),
+ },
+ provides = [PropellerOptimizeInfo],
+)
diff --git a/cc/toolchains/fdo_prefetch_hints.bzl b/cc/toolchains/fdo_prefetch_hints.bzl
index 5bc5bed..7124d4d 100644
--- a/cc/toolchains/fdo_prefetch_hints.bzl
+++ b/cc/toolchains/fdo_prefetch_hints.bzl
@@ -13,4 +13,6 @@
# limitations under the License.
"""fdo_prefetch_hints rule"""
-fdo_prefetch_hints = native.fdo_prefetch_hints # buildifier: disable=native-cc-fdo-prefetch-hints
+load("@cc_compatibility_proxy//:proxy.bzl", _fdo_prefetch_hints = "fdo_prefetch_hints")
+
+fdo_prefetch_hints = _fdo_prefetch_hints
diff --git a/cc/toolchains/fdo_profile.bzl b/cc/toolchains/fdo_profile.bzl
index 1e23303..1046189 100644
--- a/cc/toolchains/fdo_profile.bzl
+++ b/cc/toolchains/fdo_profile.bzl
@@ -13,4 +13,6 @@
# limitations under the License.
"""fdo_profile rule"""
-fdo_profile = native.fdo_profile # buildifier: disable=native-cc-fdo-profile
+load("@cc_compatibility_proxy//:proxy.bzl", _fdo_profile = "fdo_profile")
+
+fdo_profile = _fdo_profile
diff --git a/cc/toolchains/memprof_profile.bzl b/cc/toolchains/memprof_profile.bzl
index 1e0014b..302e698 100644
--- a/cc/toolchains/memprof_profile.bzl
+++ b/cc/toolchains/memprof_profile.bzl
@@ -13,4 +13,6 @@
# limitations under the License.
"""memprof_profile rule"""
-memprof_profile = native.memprof_profile
+load("@cc_compatibility_proxy//:proxy.bzl", _memprof_profile = "memprof_profile")
+
+memprof_profile = _memprof_profile
diff --git a/cc/toolchains/propeller_optimize.bzl b/cc/toolchains/propeller_optimize.bzl
index 153388f..fd8549c 100644
--- a/cc/toolchains/propeller_optimize.bzl
+++ b/cc/toolchains/propeller_optimize.bzl
@@ -13,4 +13,6 @@
# limitations under the License.
"""propeller_optimize rule"""
-propeller_optimize = native.propeller_optimize
+load("@cc_compatibility_proxy//:proxy.bzl", _propeller_optimize = "propeller_optimize")
+
+propeller_optimize = _propeller_optimize