/* * 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.apple; import com.facebook.buck.cxx.BuildRuleWithBinary; import com.facebook.buck.cxx.ProvidesLinkedBinaryDeps; import com.facebook.buck.file.WriteFile; 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.BuildRule; import com.facebook.buck.rules.BuildRuleParams; import com.facebook.buck.rules.BuildableContext; import com.facebook.buck.rules.ForwardingBuildTargetSourcePath; import com.facebook.buck.rules.HasRuntimeDeps; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.keys.SupportsInputBasedRuleKey; import com.facebook.buck.step.Step; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedSet; import java.util.Optional; import java.util.stream.Stream; /** * This build rule wraps the usual build rule and should be treated as top-level binary rule for * apple platform. Depending on the debug format, it should depend on dsym and stripped cxx binary, * or just on stripped binary. */ public class AppleDebuggableBinary extends AbstractBuildRule implements BuildRuleWithBinary, SupportsInputBasedRuleKey, HasRuntimeDeps { public static final Flavor RULE_FLAVOR = InternalFlavor.of("apple-debuggable-binary"); /** * Binary rule could be stripped and unstripped, depending on requirements. See AppleDebugFormat. */ private final BuildRule binaryRule; @AddToRuleKey private final SourcePath binarySourcePath; public AppleDebuggableBinary(BuildRuleParams buildRuleParams, BuildRule binaryRule) { super(buildRuleParams); this.binaryRule = binaryRule; this.binarySourcePath = Preconditions.checkNotNull(binaryRule.getSourcePathToOutput()); performChecks(buildRuleParams, binaryRule); } private void performChecks(BuildRuleParams buildRuleParams, BuildRule cxxStrip) { Preconditions.checkArgument( buildRuleParams.getBuildTarget().getFlavors().contains(RULE_FLAVOR), "Rule %s should contain flavor %s", this, RULE_FLAVOR); Preconditions.checkArgument( AppleDebugFormat.FLAVOR_DOMAIN.containsAnyOf(buildRuleParams.getBuildTarget().getFlavors()), "Rule %s should contain some of AppleDebugFormat flavors", this); Preconditions.checkArgument( getBuildDeps().contains(cxxStrip), "Rule %s should depend on its stripped rule %s", this, cxxStrip); } /** Indicates whether its possible to wrap given _binary_ rule. */ public static boolean canWrapBinaryBuildRule(BuildRule binaryBuildRule) { return binaryBuildRule instanceof ProvidesLinkedBinaryDeps; } public static boolean isBuildRuleDebuggable(BuildRule buildRule) { // stub binary files cannot have dSYMs if (buildRule instanceof WriteFile) { return false; } // fat/thin binaries and dynamic libraries may have dSYMs if (buildRule instanceof ProvidesLinkedBinaryDeps || buildRule instanceof AppleDebuggableBinary) { return true; } return false; } // Defines all rules that AppleDebuggableBinary should depend on, depending on debug format. // For no-debug: only stripped binary. // For dwarf: on unstripped binary and all static libs, because these files must be accessible // during debug session. // For dsym: on stripped binary and dsym rule, because dSYM must be accessible during debug // session. public static ImmutableSortedSet<BuildRule> getRequiredRuntimeDeps( AppleDebugFormat debugFormat, BuildRule strippedBinaryRule, ProvidesLinkedBinaryDeps unstrippedBinaryRule, Optional<AppleDsym> appleDsym) { if (debugFormat == AppleDebugFormat.NONE) { return ImmutableSortedSet.of(strippedBinaryRule); } ImmutableSortedSet.Builder<BuildRule> builder = ImmutableSortedSet.naturalOrder(); if (debugFormat == AppleDebugFormat.DWARF) { builder.add(unstrippedBinaryRule); builder.addAll(unstrippedBinaryRule.getCompileDeps()); builder.addAll(unstrippedBinaryRule.getStaticLibraryDeps()); } else if (debugFormat == AppleDebugFormat.DWARF_AND_DSYM) { Preconditions.checkArgument( appleDsym.isPresent(), "debugFormat %s expects AppleDsym rule to be present", AppleDebugFormat.DWARF_AND_DSYM); builder.add(strippedBinaryRule); builder.add(appleDsym.get()); } return builder.build(); } @Override public ImmutableList<Step> getBuildSteps( BuildContext context, BuildableContext buildableContext) { return ImmutableList.of(); } @Override public SourcePath getSourcePathToOutput() { return new ForwardingBuildTargetSourcePath(getBuildTarget(), binarySourcePath); } @Override public BuildRule getBinaryBuildRule() { return binaryRule; } @Override public Stream<BuildTarget> getRuntimeDeps() { return getDeclaredDeps().stream().map(BuildRule::getBuildTarget); } }