/* * Copyright 2015-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.CxxStrip; import com.facebook.buck.cxx.LinkerMapMode; import com.facebook.buck.cxx.StripStyle; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargets; 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.HasPostBuildSteps; 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.MoveStep; import com.facebook.buck.step.fs.RmStep; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import java.nio.file.Path; /** Creates dSYM bundle for the given _unstripped_ binary. */ public class AppleDsym extends AbstractBuildRule implements HasPostBuildSteps, SupportsInputBasedRuleKey { public static final Flavor RULE_FLAVOR = InternalFlavor.of("apple-dsym"); public static final String DSYM_DWARF_FILE_FOLDER = "Contents/Resources/DWARF/"; @AddToRuleKey private final Tool lldb; @AddToRuleKey private final Tool dsymutil; @AddToRuleKey private final SourcePath unstrippedBinarySourcePath; @AddToRuleKey(stringify = true) private final Path dsymOutputPath; public AppleDsym( BuildRuleParams params, Tool dsymutil, Tool lldb, SourcePath unstrippedBinarySourcePath, Path dsymOutputPath) { super(params); this.dsymutil = dsymutil; this.lldb = lldb; this.unstrippedBinarySourcePath = unstrippedBinarySourcePath; this.dsymOutputPath = dsymOutputPath; checkFlavorCorrectness(params.getBuildTarget()); } public static Path getDsymOutputPath(BuildTarget target, ProjectFilesystem filesystem) { AppleDsym.checkFlavorCorrectness(target); return BuildTargets.getGenPath( filesystem, target, "%s." + AppleBundleExtension.DSYM.toFileExtension()); } public static String getDwarfFilenameForDsymTarget(BuildTarget dsymTarget) { AppleDsym.checkFlavorCorrectness(dsymTarget); return dsymTarget.getShortName(); } private static void checkFlavorCorrectness(BuildTarget buildTarget) { Preconditions.checkArgument( buildTarget.getFlavors().contains(RULE_FLAVOR), "Rule %s must be identified by %s flavor", buildTarget, RULE_FLAVOR); Preconditions.checkArgument( !AppleDebugFormat.FLAVOR_DOMAIN.containsAnyOf(buildTarget.getFlavors()), "Rule %s must not contain any debug format flavors (%s), only rule flavor %s", buildTarget, AppleDebugFormat.FLAVOR_DOMAIN.getFlavors(), RULE_FLAVOR); Preconditions.checkArgument( !buildTarget.getFlavors().contains(CxxStrip.RULE_FLAVOR), "Rule %s must not contain strip flavor %s: %s works only with unstripped binaries!", buildTarget, CxxStrip.RULE_FLAVOR, AppleDsym.class.toString()); Preconditions.checkArgument( !StripStyle.FLAVOR_DOMAIN.containsAnyOf(buildTarget.getFlavors()), "Rule %s must not contain strip style flavors: %s works only with unstripped binaries!", buildTarget, AppleDsym.class.toString()); Preconditions.checkArgument( !LinkerMapMode.FLAVOR_DOMAIN.containsAnyOf(buildTarget.getFlavors()), "Rule %s must not contain linker map mode flavors.", buildTarget); } @Override public ImmutableList<Step> getBuildSteps( BuildContext context, BuildableContext buildableContext) { buildableContext.recordArtifact(dsymOutputPath); Path unstrippedBinaryPath = context.getSourcePathResolver().getAbsolutePath(unstrippedBinarySourcePath); Path dwarfFileFolder = dsymOutputPath.resolve(DSYM_DWARF_FILE_FOLDER); return ImmutableList.of( RmStep.of(getProjectFilesystem(), dsymOutputPath).withRecursive(true), new DsymStep( getProjectFilesystem(), dsymutil.getEnvironment(context.getSourcePathResolver()), dsymutil.getCommandPrefix(context.getSourcePathResolver()), unstrippedBinaryPath, dsymOutputPath), new MoveStep( getProjectFilesystem(), dwarfFileFolder.resolve(unstrippedBinaryPath.getFileName()), dwarfFileFolder.resolve(getDwarfFilenameForDsymTarget(getBuildTarget())))); } @Override public SourcePath getSourcePathToOutput() { return new ExplicitBuildTargetSourcePath(getBuildTarget(), dsymOutputPath); } @Override public ImmutableList<Step> getPostBuildSteps(BuildContext context) { return ImmutableList.of( new RegisterDebugSymbolsStep( unstrippedBinarySourcePath, lldb, context.getSourcePathResolver(), dsymOutputPath)); } }