// 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.annotations.VisibleForTesting; 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.OutputGroupProvider; 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.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.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.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.devtools.intellij.ideinfo.IntellijIdeInfo.AndroidIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.ArtifactLocation; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.CIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.CToolchainIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.JavaIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.JavaToolchainIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.LibraryArtifact; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.PyIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.TargetIdeInfo; import com.google.devtools.intellij.ideinfo.IntellijIdeInfo.TestInfo; import com.google.protobuf.MessageLite; import java.io.ByteArrayInputStream; import java.io.File; 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. static final String IDE_INFO = "ide-info"; static final String IDE_INFO_TEXT = "ide-info-text"; static final String IDE_RESOLVE = "ide-resolve"; static final String IDE_COMPILE = "ide-compile"; 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(this) .attributeAspect("runtime_deps", this) .attributeAspect("resources", this) .add( attr("$packageParser", LABEL) .cfg(HOST) .exec() .value( Label.parseAbsoluteUnchecked( toolsRepository + "//tools/android:PackageParser"))) .add( attr("$jarFilter", LABEL) .cfg(HOST) .exec() .value( Label.parseAbsoluteUnchecked( toolsRepository + "//tools/android:JarFilter"))); 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(this, parameters, ruleContext); AndroidStudioInfoFilesProvider.Builder providerBuilder = new AndroidStudioInfoFilesProvider.Builder(); DependenciesResult dependenciesResult = processDependencies(base, ruleContext, providerBuilder); AndroidStudioInfoFilesProvider provider = createIdeBuildArtifact(base, ruleContext, dependenciesResult, providerBuilder); NestedSetBuilder ideCompileArtifacts = NestedSetBuilder.stableOrder(); // Add artifacts required for compilation OutputGroupProvider outputGroupProvider = base.getProvider(OutputGroupProvider.class); if (outputGroupProvider != null) { ideCompileArtifacts.addTransitive( outputGroupProvider.getOutputGroup(OutputGroupProvider.FILES_TO_COMPILE)); } builder .addOutputGroup(IDE_INFO, provider.getIdeInfoFiles()) .addOutputGroup(IDE_INFO_TEXT, provider.getIdeInfoTextFiles()) .addOutputGroup(IDE_RESOLVE, provider.getIdeResolveFiles()) .addOutputGroup(IDE_COMPILE, ideCompileArtifacts.build()) .addProvider(provider); return builder.build(); } private static class DependenciesResult { private DependenciesResult( Iterable