/*
* Copyright 2016-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.InternalFlavor;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.ExplicitBuildTargetSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.Tool;
import com.facebook.buck.rules.keys.SupportsInputBasedRuleKey;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Optional;
/**
* Controls how strip tool is invoked. To have better understanding please refer to `man strip`. If
* you don't want stripping, you should depend on CxxLink directly.
*/
public class CxxStrip extends AbstractBuildRule implements SupportsInputBasedRuleKey {
/**
* Used to identify this rule in the graph. This should be appended ONLY to build target that is
* passed to the CxxStrip constructor when you create instance of this class. Appending it in
* other places is does nothing except adds a unnecessary flavor that will skew output paths of
* other build rules.
*/
public static final Flavor RULE_FLAVOR = InternalFlavor.of("stripped");
@AddToRuleKey private final StripStyle stripStyle;
@AddToRuleKey private final SourcePath cxxLinkSourcePath;
@AddToRuleKey private final Tool strip;
@AddToRuleKey(stringify = true)
private final Path output;
public CxxStrip(
BuildRuleParams buildRuleParams,
StripStyle stripStyle,
SourcePath cxxLinkSourcePath,
Tool strip,
Path output) {
super(buildRuleParams);
this.stripStyle = stripStyle;
this.cxxLinkSourcePath = cxxLinkSourcePath;
this.strip = strip;
this.output = output;
performChecks(buildRuleParams.getBuildTarget());
}
private void performChecks(BuildTarget buildTarget) {
Preconditions.checkArgument(
buildTarget.getFlavors().contains(RULE_FLAVOR),
"CxxStrip rule %s should contain %s flavor",
this,
RULE_FLAVOR);
Preconditions.checkArgument(
StripStyle.FLAVOR_DOMAIN.containsAnyOf(buildTarget.getFlavors()),
"CxxStrip rule %s should contain one of the strip style flavors (%s)",
this,
StripStyle.FLAVOR_DOMAIN.getFlavors());
}
public static BuildRuleParams removeStripStyleFlavorInParams(
BuildRuleParams params, Optional<StripStyle> flavoredStripStyle) {
params = params.withoutFlavor(CxxStrip.RULE_FLAVOR);
if (flavoredStripStyle.isPresent()) {
params = params.withoutFlavor(flavoredStripStyle.get().getFlavor());
}
return params;
}
public static BuildRuleParams restoreStripStyleFlavorInParams(
BuildRuleParams params, Optional<StripStyle> flavoredStripStyle) {
if (flavoredStripStyle.isPresent()) {
// we should not append CxxStrip.RULE_FLAVOR here because it must be appended
// to CxxStrip rule only. Other users of CxxStrip flavors must not append it.
params = params.withAppendedFlavor(flavoredStripStyle.get().getFlavor());
}
return params;
}
@Override
public ImmutableList<Step> getBuildSteps(
BuildContext context, BuildableContext buildableContext) {
buildableContext.recordArtifact(output);
return ImmutableList.of(
CopyStep.forFile(
getProjectFilesystem(),
context.getSourcePathResolver().getAbsolutePath(cxxLinkSourcePath),
output),
new StripSymbolsStep(
output,
strip.getCommandPrefix(context.getSourcePathResolver()),
strip.getEnvironment(context.getSourcePathResolver()),
stripStyle.getStripToolArgs(),
getProjectFilesystem()));
}
public StripStyle getStripStyle() {
return stripStyle;
}
@Override
public SourcePath getSourcePathToOutput() {
return new ExplicitBuildTargetSourcePath(getBuildTarget(), output);
}
}