| // Copyright 2015 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.rules.android; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableCollection; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Iterables; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.actions.Root; |
| import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; |
| import com.google.devtools.build.lib.packages.AttributeMap; |
| import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| import java.util.Collection; |
| import java.util.LinkedHashSet; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.Set; |
| import javax.annotation.Nullable; |
| |
| /** |
| * An Android target provider to provide Android-specific info to IDEs. |
| */ |
| @Immutable |
| public final class AndroidIdeInfoProvider implements TransitiveInfoProvider { |
| /** Represents a directory that contains sources, generated or otherwise, for an IDE.*/ |
| @Immutable |
| public static class SourceDirectory { |
| final PathFragment relativePath; |
| final PathFragment rootExecutionPathFragment; |
| final PathFragment rootPath; |
| final boolean isSource; |
| |
| @VisibleForTesting |
| public static SourceDirectory fromSourceRoot( |
| PathFragment rootPath, |
| PathFragment relativePath) { |
| return new SourceDirectory(rootPath, PathFragment.EMPTY_FRAGMENT, relativePath, true); |
| } |
| |
| public static SourceDirectory fromRoot(Root root, PathFragment relativePath) { |
| return new SourceDirectory( |
| root.getPath().asFragment(), root.getExecPath(), relativePath, root.isSourceRoot()); |
| } |
| |
| private SourceDirectory( |
| PathFragment rootPath, |
| PathFragment rootExecutionPathFragment, |
| PathFragment relativePath, |
| boolean isSource) { |
| this.rootPath = rootPath; |
| this.rootExecutionPathFragment = rootExecutionPathFragment; |
| this.relativePath = relativePath; |
| this.isSource = isSource; |
| } |
| |
| /** |
| * The root relative path, {@link Artifact#getRootRelativePath()}. |
| */ |
| public PathFragment getRelativePath() { |
| return relativePath; |
| } |
| |
| /** |
| * The absolute path of the root that contains this directory, {@link Root#getPath()}. |
| */ |
| public PathFragment getRootPath() { |
| return rootPath; |
| } |
| |
| /** |
| * The path from the execution root to the actual root. For source roots, this returns |
| * the empty fragment, {@link Root#getExecPath()}. |
| */ |
| public PathFragment getRootExecutionPathFragment() { |
| return rootExecutionPathFragment; |
| } |
| |
| /** Indicates if the directory is in the gen files tree. */ |
| public boolean isSource() { |
| return isSource; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(relativePath, rootPath, rootExecutionPathFragment, isSource); |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof SourceDirectory) { |
| SourceDirectory otherDir = (SourceDirectory) other; |
| return Objects.equals(rootPath, otherDir.rootPath) |
| && Objects.equals(rootExecutionPathFragment, otherDir.rootExecutionPathFragment) |
| && Objects.equals(relativePath, otherDir.relativePath) |
| && Objects.equals(isSource, otherDir.isSource); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "SourceDirectory [relativePath=" + relativePath + ", rootPath=" + rootPath |
| + ", executionRootPrefix=" + rootExecutionPathFragment + ", isSource=" + isSource + "]"; |
| } |
| } |
| |
| /** |
| * Builder for {@link AndroidIdeInfoProvider} |
| */ |
| public static class Builder { |
| private Artifact manifest = null; |
| private Artifact generatedManifest = null; |
| private Artifact apk = null; |
| private Artifact resourceApk = null; |
| private Artifact idlClassJar = null; |
| private Artifact idlSourceJar = null; |
| private OutputJar resourceJar = null; |
| private String javaPackage = null; |
| private String idlImportRoot = null; |
| private final Set<SourceDirectory> resourceDirs = new LinkedHashSet<>(); |
| private final Set<SourceDirectory> assetDirs = new LinkedHashSet<>(); |
| private final Set<SourceDirectory> idlDirs = new LinkedHashSet<>(); |
| private final Set<Artifact> idlSrcs = new LinkedHashSet<>(); |
| private final Set<Artifact> idlGeneratedJavaFiles = new LinkedHashSet<>(); |
| private final Set<Artifact> apksUnderTest = new LinkedHashSet<>(); |
| private boolean definesAndroidResources; |
| private Artifact aar = null; |
| private Map<String, NestedSet<Artifact>> nativeLibs = null; |
| |
| public AndroidIdeInfoProvider build() { |
| return new AndroidIdeInfoProvider( |
| javaPackage, |
| idlImportRoot, |
| manifest, |
| generatedManifest, |
| apk, |
| idlClassJar, |
| idlSourceJar, |
| resourceJar, |
| definesAndroidResources, |
| aar, |
| ImmutableList.copyOf(assetDirs), |
| ImmutableList.copyOf(resourceDirs), |
| ImmutableList.copyOf(idlDirs), |
| ImmutableList.copyOf(idlSrcs), |
| ImmutableList.copyOf(idlGeneratedJavaFiles), |
| ImmutableList.copyOf(apksUnderTest), |
| nativeLibs != null |
| ? ImmutableMap.copyOf(nativeLibs) |
| : ImmutableMap.<String, NestedSet<Artifact>>of(), |
| resourceApk); |
| } |
| |
| public Builder setJavaPackage(String javaPackage) { |
| this.javaPackage = javaPackage; |
| return this; |
| } |
| |
| public Builder setDefinesAndroidResources(boolean definesAndroidResources) { |
| this.definesAndroidResources = definesAndroidResources; |
| return this; |
| } |
| |
| public Builder setApk(Artifact apk) { |
| Preconditions.checkState(this.apk == null); |
| this.apk = apk; |
| return this; |
| } |
| |
| public Builder setManifest(Artifact manifest) { |
| Preconditions.checkState(this.manifest == null); |
| this.manifest = manifest; |
| return this; |
| } |
| |
| public Builder setGeneratedManifest(Artifact manifest) { |
| Preconditions.checkState(this.generatedManifest == null); |
| this.generatedManifest = manifest; |
| return this; |
| } |
| |
| public Builder setIdlClassJar(@Nullable Artifact idlClassJar) { |
| Preconditions.checkState(this.idlClassJar == null); |
| this.idlClassJar = idlClassJar; |
| return this; |
| } |
| |
| public Builder setIdlSourceJar(@Nullable Artifact idlSourceJar) { |
| Preconditions.checkState(this.idlSourceJar == null); |
| this.idlSourceJar = idlSourceJar; |
| return this; |
| } |
| |
| public Builder setResourceJar(OutputJar resourceJar) { |
| this.resourceJar = resourceJar; |
| return this; |
| } |
| |
| public Builder setResourceApk(Artifact resourceApk) { |
| this.resourceApk = resourceApk; |
| return this; |
| } |
| |
| public Builder setAar(Artifact aar) { |
| this.aar = aar; |
| return this; |
| } |
| |
| public Builder setNativeLibs(Map<String, NestedSet<Artifact>> nativeLibs) { |
| this.nativeLibs = nativeLibs; |
| return this; |
| } |
| |
| |
| public Builder addIdlImportRoot(String idlImportRoot) { |
| this.idlImportRoot = idlImportRoot; |
| return this; |
| } |
| |
| /** |
| * Add "idl_srcs" contents. |
| */ |
| public Builder addIdlSrcs(Collection<Artifact> idlSrcs) { |
| this.idlSrcs.addAll(idlSrcs); |
| addIdlDirs(idlSrcs); |
| return this; |
| } |
| |
| /** |
| * Add the java files generated from "idl_srcs". |
| */ |
| public Builder addIdlGeneratedJavaFiles(Collection<Artifact> idlGeneratedJavaFiles) { |
| this.idlGeneratedJavaFiles.addAll(idlGeneratedJavaFiles); |
| return this; |
| } |
| |
| /** |
| * Add "idl_parcelables" contents. |
| */ |
| public Builder addIdlParcelables(Collection<Artifact> idlParcelables) { |
| addIdlDirs(idlParcelables); |
| return this; |
| } |
| |
| private void addIdlDirs(Collection<Artifact> idlArtifacts) { |
| for (Artifact idl : idlArtifacts) { |
| this.idlDirs.add( |
| SourceDirectory.fromRoot( |
| idl.getRoot(), |
| idl.getRootRelativePath().getParentDirectory())); |
| } |
| } |
| |
| public Builder addAllResources(Collection<SourceDirectory> resources) { |
| resourceDirs.addAll(resources); |
| return this; |
| } |
| |
| public Builder addAllAssets(Collection<SourceDirectory> assets) { |
| assetDirs.addAll(assets); |
| return this; |
| } |
| |
| public Builder addResourceSource(Artifact resource) { |
| resourceDirs.add( |
| SourceDirectory.fromRoot( |
| resource.getRoot(), |
| AndroidCommon.getSourceDirectoryRelativePathFromResource(resource))); |
| return this; |
| } |
| |
| public Builder addResourceSources(Collection<Artifact> resources) { |
| for (Artifact resource : resources) { |
| addResourceSource(resource); |
| } |
| return this; |
| } |
| |
| public Builder addAssetSources(Collection<Artifact> assets, PathFragment assetDir) { |
| for (Artifact asset : assets) { |
| addAssetSource(asset, assetDir); |
| } |
| return this; |
| } |
| |
| public Builder addAssetSource(Artifact asset, PathFragment assetDir) { |
| assetDirs.add( |
| SourceDirectory.fromRoot( |
| asset.getRoot(), AndroidCommon.trimTo(asset.getRootRelativePath(), assetDir))); |
| return this; |
| } |
| |
| public Builder addAllApksUnderTest(Iterable<Artifact> apks) { |
| Iterables.addAll(apksUnderTest, apks); |
| return this; |
| } |
| } |
| |
| private final String javaPackage; |
| private final String idlImportRoot; |
| private final Artifact manifest; |
| private final Artifact generatedManifest; |
| private final Artifact signedApk; |
| @Nullable private final Artifact idlClassJar; |
| @Nullable private final Artifact idlSourceJar; |
| @Nullable private final OutputJar resourceJar; |
| @Nullable private final Artifact resourceApk; |
| private final ImmutableCollection<SourceDirectory> resourceDirs; |
| private final boolean definesAndroidResources; |
| private final Artifact aar; |
| private final ImmutableCollection<SourceDirectory> assetDirs; |
| private final ImmutableCollection<SourceDirectory> idlImports; |
| private final ImmutableCollection<Artifact> idlSrcs; |
| private final ImmutableCollection<Artifact> idlGeneratedJavaFiles; |
| private final ImmutableCollection<Artifact> apksUnderTest; |
| private final ImmutableMap<String, NestedSet<Artifact>> nativeLibs; |
| |
| AndroidIdeInfoProvider( |
| String javaPackage, |
| String idlImportRoot, |
| @Nullable Artifact manifest, |
| @Nullable Artifact generatedManifest, |
| @Nullable Artifact signedApk, |
| @Nullable Artifact idlClassJar, |
| @Nullable Artifact idlSourceJar, |
| @Nullable OutputJar resourceJar, |
| boolean definesAndroidResources, |
| @Nullable Artifact aar, |
| ImmutableCollection<SourceDirectory> assetDirs, |
| ImmutableCollection<SourceDirectory> resourceDirs, |
| ImmutableCollection<SourceDirectory> idlImports, |
| ImmutableCollection<Artifact> idlSrcs, |
| ImmutableCollection<Artifact> idlGeneratedJavaFiles, |
| ImmutableCollection<Artifact> apksUnderTest, |
| ImmutableMap<String, NestedSet<Artifact>> nativeLibs, |
| Artifact resourceApk) { |
| this.javaPackage = javaPackage; |
| this.idlImportRoot = idlImportRoot; |
| this.manifest = manifest; |
| this.generatedManifest = generatedManifest; |
| this.signedApk = signedApk; |
| this.idlClassJar = idlClassJar; |
| this.idlSourceJar = idlSourceJar; |
| this.resourceJar = resourceJar; |
| this.definesAndroidResources = definesAndroidResources; |
| this.aar = aar; |
| this.assetDirs = assetDirs; |
| this.resourceDirs = resourceDirs; |
| this.idlImports = idlImports; |
| this.idlSrcs = idlSrcs; |
| this.idlGeneratedJavaFiles = idlGeneratedJavaFiles; |
| this.apksUnderTest = apksUnderTest; |
| this.nativeLibs = nativeLibs; |
| this.resourceApk = resourceApk; |
| } |
| |
| /** Returns java package for this target. */ |
| public String getJavaPackage() { |
| return javaPackage; |
| } |
| |
| /** Returns the direct AndroidManifest. */ |
| @Nullable |
| public Artifact getManifest() { |
| return manifest; |
| } |
| |
| /** Returns the direct generated AndroidManifest. */ |
| @Nullable |
| public Artifact getGeneratedManifest() { |
| return generatedManifest; |
| } |
| |
| /** |
| * Returns true if the target defined Android resources. |
| * Exposes {@link LocalResourceContainer#definesAndroidResources(AttributeMap)} |
| */ |
| public boolean definesAndroidResources() { |
| return this.definesAndroidResources; |
| } |
| |
| @Nullable |
| public String getIdlImportRoot() { |
| return idlImportRoot; |
| } |
| |
| /** Returns the direct debug key signed apk, if there is one. */ |
| @Nullable |
| public Artifact getSignedApk() { |
| return signedApk; |
| } |
| |
| @Nullable |
| public Artifact getIdlClassJar() { |
| return idlClassJar; |
| } |
| |
| @Nullable |
| public Artifact getIdlSourceJar() { |
| return idlSourceJar; |
| } |
| |
| @Nullable |
| public OutputJar getResourceJar() { |
| return resourceJar; |
| } |
| |
| @Nullable |
| public Artifact getAar() { |
| return aar; |
| } |
| |
| @Nullable |
| public Artifact getResourceApk() { |
| return resourceApk; |
| } |
| |
| /** A list of the direct Resource directories. */ |
| public ImmutableCollection<SourceDirectory> getResourceDirs() { |
| return resourceDirs; |
| } |
| |
| /** A list of the direct Asset directories. */ |
| public ImmutableCollection<SourceDirectory> getAssetDirs() { |
| return assetDirs; |
| } |
| |
| /** A list of direct idl directories. */ |
| public ImmutableCollection<SourceDirectory> getIdlImports() { |
| return idlImports; |
| } |
| |
| /** A list of sources from the "idl_srcs" attribute. */ |
| public ImmutableCollection<Artifact> getIdlSrcs() { |
| return idlSrcs; |
| } |
| |
| /** A list of java files generated from the "idl_srcs" attribute. */ |
| public ImmutableCollection<Artifact> getIdlGeneratedJavaFiles() { |
| return idlGeneratedJavaFiles; |
| } |
| |
| /** A list of the APKs related to the app under test, if any. */ |
| public ImmutableCollection<Artifact> getApksUnderTest() { |
| return apksUnderTest; |
| } |
| |
| /** A map, keyed on architecture, of the native libs for the app, if any. */ |
| public ImmutableMap<String, NestedSet<Artifact>> getNativeLibs() { |
| return nativeLibs; |
| } |
| } |