// Copyright 2014 The Bazel Authors. All rights reserved. // // 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.google.devtools.build.lib.ideinfo; import static com.google.common.collect.Iterables.transform; import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.io.ByteSource; import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; import com.google.devtools.build.lib.actions.Root; import com.google.devtools.build.lib.analysis.AnalysisUtils; import com.google.devtools.build.lib.analysis.ConfiguredAspect; import com.google.devtools.build.lib.analysis.ConfiguredAspect.Builder; import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.actions.BinaryFileWriteAction; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.AndroidRuleIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.ArtifactLocation; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CRuleIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.CToolchainIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.JavaRuleIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.JavaToolchainIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.LibraryArtifact; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo.Kind; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.TestInfo; import com.google.devtools.build.lib.packages.AspectDefinition; import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.NativeAspectClass; import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.TargetUtils; import com.google.devtools.build.lib.rules.android.AndroidIdeInfoProvider; import com.google.devtools.build.lib.rules.android.AndroidIdeInfoProvider.SourceDirectory; import com.google.devtools.build.lib.rules.android.AndroidSdkProvider; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.java.JavaExportsProvider; import com.google.devtools.build.lib.rules.java.JavaGenJarsProvider; import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar; import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider; import com.google.devtools.build.lib.rules.java.JavaToolchainProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.protobuf.MessageLite; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import javax.annotation.Nullable; /** * Generates ide-build information for Android Studio. */ public class AndroidStudioInfoAspect extends NativeAspectClass implements ConfiguredAspectFactory { public static final String NAME = "AndroidStudioInfoAspect"; // Output groups. public static final String IDE_INFO = "ide-info"; public static final String IDE_INFO_TEXT = "ide-info-text"; public static final String IDE_RESOLVE = "ide-resolve"; private final String toolsRepository; private final AndroidStudioInfoSemantics androidStudioInfoSemantics; private final ImmutableList prerequisiteAttrs; public AndroidStudioInfoAspect( String toolsRepository, AndroidStudioInfoSemantics androidStudioInfoSemantics) { this.toolsRepository = toolsRepository; this.androidStudioInfoSemantics = androidStudioInfoSemantics; this.prerequisiteAttrs = buildPrerequisiteAttrs(); } @Override public String getName() { return NAME; } /** * Attribute to propagate dependencies along. */ public static class PrerequisiteAttr { public final String name; public final Type type; public PrerequisiteAttr(String name, Type type) { this.name = name; this.type = type; } } private ImmutableList buildPrerequisiteAttrs() { ImmutableList.Builder builder = ImmutableList.builder(); builder.add(new PrerequisiteAttr("deps", BuildType.LABEL_LIST)); builder.add(new PrerequisiteAttr("exports", BuildType.LABEL_LIST)); // From android_test builder.add(new PrerequisiteAttr("binary_under_test", BuildType.LABEL)); // from java_* rules builder.add(new PrerequisiteAttr(":java_toolchain", BuildType.LABEL)); // from cc_* rules builder.add(new PrerequisiteAttr(":cc_toolchain", BuildType.LABEL)); androidStudioInfoSemantics.augmentPrerequisiteAttrs(builder); return builder.build(); } // File suffixes. public static final String ASWB_BUILD_SUFFIX = ".aswb-build"; public static final String ASWB_BUILD_TEXT_SUFFIX = ".aswb-build.txt"; public static final Function LABEL_TO_STRING = new Function() { @Nullable @Override public String apply(Label label) { return label.toString(); } }; @Override public AspectDefinition getDefinition(AspectParameters aspectParameters) { AspectDefinition.Builder builder = new AspectDefinition.Builder(NAME) .attributeAspect("runtime_deps", this) .attributeAspect("resources", this) .add(attr("$packageParser", LABEL).cfg(HOST).exec() .value(Label.parseAbsoluteUnchecked( toolsRepository + "//tools/android:PackageParser"))); for (PrerequisiteAttr prerequisiteAttr : prerequisiteAttrs) { builder.attributeAspect(prerequisiteAttr.name, this); } return builder.build(); } @Override public ConfiguredAspect create( ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) { ConfiguredAspect.Builder builder = new Builder(NAME, ruleContext); AndroidStudioInfoFilesProvider.Builder providerBuilder = new AndroidStudioInfoFilesProvider.Builder(); RuleIdeInfo.Kind ruleKind = getRuleKind(ruleContext.getRule(), base); DependenciesResult dependenciesResult = processDependencies( base, ruleContext, providerBuilder); AndroidStudioInfoFilesProvider provider = createIdeBuildArtifact( base, ruleContext, ruleKind, dependenciesResult, providerBuilder); builder .addOutputGroup(IDE_INFO, provider.getIdeInfoFiles()) .addOutputGroup(IDE_INFO_TEXT, provider.getIdeInfoTextFiles()) .addOutputGroup(IDE_RESOLVE, provider.getIdeResolveFiles()) .addProvider( AndroidStudioInfoFilesProvider.class, provider); return builder.build(); } private static class DependenciesResult { private DependenciesResult(Iterable