blob: 1565e6fcad81c2d8f4de4cebefffb9bb2784e312 [file] [log] [blame]
/*
* Copyright 2013-present Facebook, Inc.
*
* 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.facebook.buck.cxx;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.FlavorDomain;
import com.facebook.buck.model.FlavorDomainException;
import com.facebook.buck.model.Flavored;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.ImmutableBuildRuleType;
import com.facebook.buck.rules.ImplicitDepsInferringDescription;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
public class CxxBinaryDescription implements
Description<CxxBinaryDescription.Arg>,
Flavored,
ImplicitDepsInferringDescription<CxxBinaryDescription.Arg> {
public static final BuildRuleType TYPE = ImmutableBuildRuleType.of("cxx_binary");
private final CxxBuckConfig cxxBuckConfig;
private final CxxPlatform defaultCxxPlatform;
private final FlavorDomain<CxxPlatform> cxxPlatforms;
public CxxBinaryDescription(
CxxBuckConfig cxxBuckConfig,
CxxPlatform defaultCxxPlatform,
FlavorDomain<CxxPlatform> cxxPlatforms) {
this.cxxBuckConfig = cxxBuckConfig;
this.defaultCxxPlatform = defaultCxxPlatform;
this.cxxPlatforms = cxxPlatforms;
}
@Override
public Arg createUnpopulatedConstructorArg() {
return new Arg();
}
@Override
public <A extends Arg> CxxBinary createBuildRule(
BuildRuleParams params,
BuildRuleResolver resolver,
A args) {
// Extract the platform from the flavor, falling back to the default platform if none are
// found.
CxxPlatform cxxPlatform;
try {
cxxPlatform = cxxPlatforms
.getValue(ImmutableSet.copyOf(params.getBuildTarget().getFlavors()))
.or(defaultCxxPlatform);
} catch (FlavorDomainException e) {
throw new HumanReadableException("%s: %s", params.getBuildTarget(), e.getMessage());
}
CxxLink cxxLink = CxxDescriptionEnhancer.createBuildRulesForCxxBinaryDescriptionArg(
params,
resolver,
cxxPlatform,
args);
// Return a CxxBinary rule as our representative in the action graph, rather than the CxxLink
// rule above for a couple reasons:
// 1) CxxBinary extends BinaryBuildRule whereas CxxLink does not, so the former can be used
// as executables for genrules.
// 2) In some cases, users add dependencies from some rules onto other binary rules, typically
// if the binary is executed by some test or library code at test time. These target graph
// deps should *not* become build time dependencies on the CxxLink step, otherwise we'd
// have to wait for the dependency binary to link before we could link the dependent binary.
// By using another BuildRule, we can keep the original target graph dependency tree while
// preventing it from affecting link parallelism.
return new CxxBinary(
params.copyWithDeps(
Suppliers.ofInstance(
ImmutableSortedSet.<BuildRule>naturalOrder()
.addAll(params.getDeclaredDeps())
.add(cxxLink)
.build()),
Suppliers.ofInstance(params.getExtraDeps())),
new SourcePathResolver(resolver),
cxxLink.getOutput(),
cxxLink);
}
@Override
public BuildRuleType getBuildRuleType() {
return TYPE;
}
@Override
public Iterable<BuildTarget> findDepsForTargetFromConstructorArgs(
BuildTarget buildTarget,
Arg constructorArg) {
ImmutableSet.Builder<BuildTarget> deps = ImmutableSet.builder();
if (!constructorArg.lexSrcs.get().isEmpty()) {
deps.add(cxxBuckConfig.getLexDep());
}
return deps.build();
}
@Override
public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
if (flavors.isEmpty()) {
return true;
}
for (Flavor flavor : cxxPlatforms.getFlavors()) {
if (flavors.equals(ImmutableSet.of(flavor))) {
return true;
}
}
return false;
}
@SuppressFieldNotInitialized
public static class Arg extends CxxConstructorArg {}
}