/* * Copyright 2014-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.jvm.java; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargets; import com.facebook.buck.parser.NoSuchBuildTargetException; 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.BuildRuleResolver; import com.facebook.buck.rules.BuildableContext; import com.facebook.buck.rules.CellPathResolver; import com.facebook.buck.rules.CommonDescriptionArg; import com.facebook.buck.rules.Description; import com.facebook.buck.rules.ExplicitBuildTargetSourcePath; import com.facebook.buck.rules.HasDeclaredDeps; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.step.Step; import com.facebook.buck.step.fs.CopyStep; import com.facebook.buck.step.fs.MakeCleanDirectoryStep; import com.facebook.buck.util.immutables.BuckStyleImmutable; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedSet; import java.nio.file.Path; import java.util.Optional; import org.immutables.value.Value; public class PrebuiltJarDescription implements Description<PrebuiltJarDescriptionArg> { @Override public Class<PrebuiltJarDescriptionArg> getConstructorArgType() { return PrebuiltJarDescriptionArg.class; } @Override public BuildRule createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, CellPathResolver cellRoots, PrebuiltJarDescriptionArg args) throws NoSuchBuildTargetException { SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); if (HasJavaAbi.isClassAbiTarget(params.getBuildTarget())) { return CalculateAbiFromClasses.of( params.getBuildTarget(), ruleFinder, params, args.getBinaryJar()); } SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); BuildRule prebuilt = new PrebuiltJar( params, pathResolver, args.getBinaryJar(), args.getSourceJar(), args.getGwtJar(), args.getJavadocUrl(), args.getMavenCoords(), args.getProvided()); params.getBuildTarget().checkUnflavored(); BuildRuleParams gwtParams = params .withAppendedFlavor(JavaLibrary.GWT_MODULE_FLAVOR) .copyReplacingDeclaredAndExtraDeps( Suppliers.ofInstance(ImmutableSortedSet.of(prebuilt)), Suppliers.ofInstance(ImmutableSortedSet.of())); BuildRule gwtModule = createGwtModule(gwtParams, args); resolver.addToIndex(gwtModule); return prebuilt; } @VisibleForTesting static BuildRule createGwtModule(BuildRuleParams params, PrebuiltJarDescriptionArg arg) { // Because a PrebuiltJar rarely requires any building whatsoever (it could if the source_jar // is a BuildTargetSourcePath), we make the PrebuiltJar a dependency of the GWT module. If this // becomes a performance issue in practice, then we will explore reducing the dependencies of // the GWT module. final SourcePath input; if (arg.getGwtJar().isPresent()) { input = arg.getGwtJar().get(); } else if (arg.getSourceJar().isPresent()) { input = arg.getSourceJar().get(); } else { input = arg.getBinaryJar(); } class ExistingOuputs extends AbstractBuildRule { @AddToRuleKey private final SourcePath source; private final Path output; protected ExistingOuputs(BuildRuleParams params, SourcePath source) { super(params); this.source = source; BuildTarget target = params.getBuildTarget(); this.output = BuildTargets.getGenPath( getProjectFilesystem(), target, String.format("%s/%%s-gwt.jar", target.getShortName())); } @Override public ImmutableList<Step> getBuildSteps( BuildContext context, BuildableContext buildableContext) { buildableContext.recordArtifact( context.getSourcePathResolver().getRelativePath(getSourcePathToOutput())); ImmutableList.Builder<Step> steps = ImmutableList.builder(); steps.addAll(MakeCleanDirectoryStep.of(getProjectFilesystem(), output.getParent())); steps.add( CopyStep.forFile( getProjectFilesystem(), context.getSourcePathResolver().getAbsolutePath(source), output)); return steps.build(); } @Override public SourcePath getSourcePathToOutput() { return new ExplicitBuildTargetSourcePath(getBuildTarget(), output); } } return new ExistingOuputs(params, input); } @BuckStyleImmutable @Value.Immutable interface AbstractPrebuiltJarDescriptionArg extends CommonDescriptionArg, HasDeclaredDeps { SourcePath getBinaryJar(); Optional<SourcePath> getSourceJar(); Optional<SourcePath> getGwtJar(); Optional<String> getJavadocUrl(); Optional<String> getMavenCoords(); @Value.Default default boolean getProvided() { return false; } } }