Skip to content

Commit

Permalink
Support optional toolchains with find_cpp_toolchain
Browse files Browse the repository at this point in the history
Rules that want to use optional toolchains but still support builds that
don't use C++ toolchain resolution should point their `_cc_toolchain`
attribute to the new
`@bazel_tools//tools/cpp:optional_current_cc_toolchain` target.
  • Loading branch information
fmeum committed Dec 9, 2022
1 parent 563b225 commit 030ce8e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.Type;
import javax.annotation.Nullable;

/** Implementation of the {@code cc_toolchain_alias} rule. */
Expand All @@ -50,6 +54,7 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
.add(
attr(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, NODEP_LABEL)
.value(CppRuleClasses.ccToolchainTypeAttribute(env)))
.add(attr("mandatory", Type.BOOLEAN).value(true))
.requiresConfigurationFragments(PlatformConfiguration.class)
.addToolchainTypes(CppRuleClasses.ccToolchainTypeRequirement(env))
.build();
Expand All @@ -72,7 +77,14 @@ public ConfiguredTarget create(RuleContext ruleContext)
throws InterruptedException, RuleErrorException, ActionConflictException {

CcToolchainProvider ccToolchainProvider =
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext,
ruleContext.attributes().get("mandatory", Type.BOOLEAN));
if (ccToolchainProvider == null) {
return new RuleConfiguredTargetBuilder(ruleContext)
.addProvider(RunfilesProvider.simple(Runfiles.EMPTY))
.setFilesToBuild(NestedSetBuilder.emptySet(Order.STABLE_ORDER))
.build();
}

TemplateVariableInfo templateVariableInfo =
CcToolchain.createMakeVariableProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,19 @@ public static NestedSet<Artifact> getGcovFilesIfNeeded(
@Nullable
public static CcToolchainProvider getToolchainUsingDefaultCcToolchainAttribute(
RuleContext ruleContext) throws RuleErrorException {
return getToolchainUsingDefaultCcToolchainAttribute(ruleContext, true);
}

@Nullable
public static CcToolchainProvider getToolchainUsingDefaultCcToolchainAttribute(
RuleContext ruleContext, boolean mandatory) throws RuleErrorException {
if (ruleContext.attributes().has(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME)) {
return getToolchain(ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME);
return getToolchain(ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, mandatory);
} else if (ruleContext
.attributes()
.has(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK)) {
return getToolchain(
ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK);
ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK, mandatory);
}
return null;
}
Expand Down Expand Up @@ -322,8 +328,9 @@ public static NestedSet<Artifact> getDefaultCcToolchainStaticRuntimeInputs(
* Makes sure that the given info collection has a {@link CcToolchainProvider} (gives an error
* otherwise), and returns a reference to that {@link CcToolchainProvider}.
*/
public static CcToolchainProvider getToolchain(RuleContext ruleContext, String toolchainAttribute)
throws RuleErrorException {
@Nullable
public static CcToolchainProvider getToolchain(RuleContext ruleContext, String toolchainAttribute,
boolean mandatory) throws RuleErrorException {
if (!ruleContext.isAttrDefined(toolchainAttribute, LABEL)) {
throw ruleContext.throwWithRuleError(
String.format(
Expand All @@ -332,7 +339,7 @@ public static CcToolchainProvider getToolchain(RuleContext ruleContext, String t
toolchainAttribute));
}
TransitiveInfoCollection dep = ruleContext.getPrerequisite(toolchainAttribute);
return getToolchain(ruleContext, dep);
return getToolchain(ruleContext, dep, mandatory);
}

/**
Expand All @@ -342,15 +349,21 @@ public static CcToolchainProvider getToolchain(RuleContext ruleContext, String t
*/
public static CcToolchainProvider getToolchain(
RuleContext ruleContext, TransitiveInfoCollection dep) throws RuleErrorException {
return getToolchain(ruleContext, dep, true);
}

public static CcToolchainProvider getToolchain(
RuleContext ruleContext, TransitiveInfoCollection dep, boolean mandatory)
throws RuleErrorException {
Label toolchainType = getToolchainTypeFromRuleClass(ruleContext);
return getToolchain(ruleContext, dep, toolchainType);
return getToolchain(ruleContext, dep, toolchainType, mandatory);
}

public static CcToolchainProvider getToolchain(
RuleContext ruleContext, TransitiveInfoCollection dep, Label toolchainType)
RuleContext ruleContext, TransitiveInfoCollection dep, Label toolchainType, boolean mandatory)
throws RuleErrorException {
if (toolchainType != null && useToolchainResolution(ruleContext)) {
return getToolchainFromPlatformConstraints(ruleContext, toolchainType);
return getToolchainFromPlatformConstraints(ruleContext, toolchainType, mandatory);
}
return getToolchainFromLegacyToolchain(ruleContext, dep);
}
Expand All @@ -372,12 +385,15 @@ public static Label getToolchainTypeFromRuleClass(RuleContext ruleContext) {
}

private static CcToolchainProvider getToolchainFromPlatformConstraints(
RuleContext ruleContext, Label toolchainType) throws RuleErrorException {
RuleContext ruleContext, Label toolchainType, boolean mandatory) throws RuleErrorException {
ToolchainInfo toolchainInfo = ruleContext.getToolchainContext().forToolchainType(toolchainType);
if (toolchainInfo == null) {
throw ruleContext.throwWithRuleError(
"Unable to find a CC toolchain using toolchain resolution. Did you properly set"
+ " --platforms?");
if (mandatory) {
throw ruleContext.throwWithRuleError(
"Unable to find a CC toolchain using toolchain resolution. Did you properly set"
+ " --platforms?");
}
return null;
}
try {
return (CcToolchainProvider) toolchainInfo.getValue("cc");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ private CcToolchainProvider ccToolchain(RuleContext ruleContext) throws RuleErro
return CppHelper.getToolchain(
ruleContext,
ruleContext.getPrerequisite(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME),
ccToolchainType);
ccToolchainType,
/*mandatory=*/true);
}

private ImmutableSet<Artifact> getOutputFiles(Iterable<String> suffixes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ private ConfiguredAspect buildAspect(

try {
CcToolchainProvider ccToolchain =
CppHelper.getToolchain(ruleContext, ":j2objc_cc_toolchain");
CppHelper.getToolchain(ruleContext, ":j2objc_cc_toolchain", /*mandatory*/true);
ImmutableList<String> extraCompileArgs =
j2objcCompileWithARC(ruleContext)
? ImmutableList.of("-fno-strict-overflow", "-fobjc-arc-exceptions")
Expand Down
5 changes: 5 additions & 0 deletions tools/cpp/BUILD.tools
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ constraint_value(

cc_toolchain_alias(name = "current_cc_toolchain")

cc_toolchain_alias(
name = "optional_current_cc_toolchain",
mandatory = False,
)

cc_host_toolchain_alias(name = "current_cc_host_toolchain")

cc_libc_top_alias(name = "current_libc_top")
Expand Down
9 changes: 5 additions & 4 deletions tools/cpp/toolchain_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def find_cpp_toolchain(ctx):
ctx: The rule context for which to find a toolchain.
Returns:
A CcToolchainProvider.
A CcToolchainProvider, or None if the c++ toolchain was declared as
optional and not found.
"""

# Check the incompatible flag for toolchain resolution.
Expand All @@ -40,9 +41,9 @@ def find_cpp_toolchain(ctx):
fail("In order to use find_cpp_toolchain, you must include the '%s' in the toolchains argument to your rule." % CPP_TOOLCHAIN_TYPE)
toolchain_info = ctx.toolchains[CPP_TOOLCHAIN_TYPE]
if toolchain_info == None:
# No cpp toolchain was found, so report an error.
fail("Unable to find a CC toolchain using toolchain resolution. Target: %s, Platform: %s, Exec platform: %s" %
(ctx.label, ctx.fragments.platform.platform, ctx.fragments.platform.host_platform))
# No cpp toolchain was found, which is only possible when the rule declares it as
# optional explicitly.
return None
if hasattr(toolchain_info, "cc_provider_in_toolchain") and hasattr(toolchain_info, "cc"):
return toolchain_info.cc
return toolchain_info
Expand Down

0 comments on commit 030ce8e

Please sign in to comment.