blob: cb065630c5a7c667c0f03482c887a85277ecbb70 [file] [log] [blame]
// Copyright 2014 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.
package com.google.devtools.build.lib.rules.cpp;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.LicensesProvider;
import com.google.devtools.build.lib.analysis.MiddlemanProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.events.Location;
import java.io.Serializable;
import java.util.HashMap;
/**
* Implementation for the cc_toolchain rule.
*/
public class CcToolchain implements RuleConfiguredTargetFactory {
/** Default attribute name where rules store the reference to cc_toolchain */
public static final String CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME = ":cc_toolchain";
public static final String CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK = "$cc_toolchain";
/** Default attribute name for the c++ toolchain type */
public static final String CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME = "$cc_toolchain_type";
@Override
public ConfiguredTarget create(RuleContext ruleContext)
throws InterruptedException, RuleErrorException, ActionConflictException {
if (!isAppleToolchain()) {
CcCommon.checkRuleLoadedThroughMacro(ruleContext);
}
validateToolchain(ruleContext);
CcToolchainAttributesProvider attributes =
new CcToolchainAttributesProvider(
ruleContext, isAppleToolchain(), getAdditionalBuildVariablesComputer(ruleContext));
RuleConfiguredTargetBuilder ruleConfiguredTargetBuilder =
new RuleConfiguredTargetBuilder(ruleContext)
.addNativeDeclaredProvider(attributes)
.addProvider(RunfilesProvider.simple(Runfiles.EMPTY));
if (attributes.getLicensesProvider() != null) {
ruleConfiguredTargetBuilder.add(LicensesProvider.class, attributes.getLicensesProvider());
}
if (!CppHelper.useToolchainResolution(ruleContext)) {
// This is not a platforms-backed build, let's provide CcToolchainAttributesProvider
// and have cc_toolchain_suite select one of its toolchains and create CcToolchainProvider
// from its attributes.
return ruleConfiguredTargetBuilder.build();
}
// This is a platforms-backed build, we will not analyze cc_toolchain_suite at all, and we are
// sure current cc_toolchain is the one selected. We can create CcToolchainProvider here.
CcToolchainProvider ccToolchainProvider =
CcToolchainProviderHelper.getCcToolchainProvider(ruleContext, attributes);
if (ccToolchainProvider == null) {
// Skyframe restart
return null;
}
TemplateVariableInfo templateVariableInfo =
createMakeVariableProvider(
ccToolchainProvider,
ruleContext.getRule().getLocation());
ruleConfiguredTargetBuilder
.addNativeDeclaredProvider(ccToolchainProvider)
.addNativeDeclaredProvider(templateVariableInfo)
.setFilesToBuild(ccToolchainProvider.getAllFiles())
.addProvider(new MiddlemanProvider(ccToolchainProvider.getAllFilesMiddleman()));
return ruleConfiguredTargetBuilder.build();
}
static TemplateVariableInfo createMakeVariableProvider(
CcToolchainProvider toolchainProvider,
Location location) {
HashMap<String, String> makeVariables =
new HashMap<>(toolchainProvider.getAdditionalMakeVariables());
// Add make variables from the toolchainProvider, also.
ImmutableMap.Builder<String, String> ccProviderMakeVariables = new ImmutableMap.Builder<>();
toolchainProvider.addGlobalMakeVariables(ccProviderMakeVariables);
makeVariables.putAll(ccProviderMakeVariables.build());
return new TemplateVariableInfo(ImmutableMap.copyOf(makeVariables), location);
}
/**
* This method marks that the toolchain at hand is actually apple_cc_toolchain. Good job me for
* object design and encapsulation.
*/
protected boolean isAppleToolchain() {
// To be overridden in subclass.
return false;
}
/** Functional interface for a function that accepts cpu and {@link BuildOptions}. */
protected interface AdditionalBuildVariablesComputer {
CcToolchainVariables apply(BuildOptions buildOptions);
}
/** Returns a function that will be called to retrieve root {@link CcToolchainVariables}. */
protected AdditionalBuildVariablesComputer getAdditionalBuildVariablesComputer(
RuleContext ruleContextPossiblyInHostConfiguration) {
return (AdditionalBuildVariablesComputer & Serializable)
(options) -> CcToolchainVariables.EMPTY;
}
/** Will be called during analysis to ensure target attributes are set correctly. */
protected void validateToolchain(RuleContext ruleContext) throws RuleErrorException {
// To be overridden in subclass.
}
}