From 9d0f914b5196e37db59e253e47fadf132c5b723b Mon Sep 17 00:00:00 2001 From: Dmitry Lomov Date: Tue, 1 Sep 2015 17:56:32 +0000 Subject: Implementation of AndroidStudioIdeInfoAspect. -- MOS_MIGRATED_REVID=102057837 --- .../lib/bazel/rules/BazelRuleClassProvider.java | 3 + .../build/lib/ideinfo/AndroidStudioInfoAspect.java | 196 +++++++++++++++++++++ .../ideinfo/AndroidStudioInfoFilesProvider.java | 36 ++++ .../devtools/build/lib/rules/java/JavaLibrary.java | 4 + .../lib/rules/java/JavaRuleOutputJarsProvider.java | 57 ++++++ 5 files changed, 296 insertions(+) create mode 100644 src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java create mode 100644 src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoFilesProvider.java create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuleOutputJarsProvider.java (limited to 'src/main/java/com/google/devtools/build') diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index f337c257ba..f2e2c2b1b0 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -70,6 +70,7 @@ import com.google.devtools.build.lib.bazel.rules.workspace.NewGitRepositoryRule; import com.google.devtools.build.lib.bazel.rules.workspace.NewHttpArchiveRule; import com.google.devtools.build.lib.bazel.rules.workspace.NewLocalRepositoryRule; import com.google.devtools.build.lib.bazel.rules.workspace.WorkspaceBaseRule; +import com.google.devtools.build.lib.ideinfo.AndroidStudioInfoAspect; import com.google.devtools.build.lib.packages.Attribute; import com.google.devtools.build.lib.packages.PackageGroup; import com.google.devtools.build.lib.packages.Rule; @@ -353,6 +354,8 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new AndroidRepositoryRules.AndroidLocalRepositoryRule()); builder.addRuleDefinition(new AndroidHttpToolsRepositoryRule()); + builder.addAspectFactory(AndroidStudioInfoAspect.NAME, AndroidStudioInfoAspect.class); + builder.addConfigurationFragment(new BazelConfiguration.Loader()); builder.addConfigurationFragment(new CppConfigurationLoader( Functions.identity())); diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java new file mode 100644 index 0000000000..6316f1ad94 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java @@ -0,0 +1,196 @@ +// Copyright 2014 Google Inc. 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 com.google.common.collect.ImmutableList; +import com.google.common.io.ByteSource; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.Root; +import com.google.devtools.build.lib.analysis.Aspect; +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.actions.BinaryFileWriteAction; +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.ArtifactLocation; +import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.JavaRuleIdeInfo; +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.packages.AspectDefinition; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; +import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider; +import com.google.devtools.build.lib.vfs.PathFragment; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; + +/** + * Generates ide-build information for Android Studio. + */ +public class AndroidStudioInfoAspect implements ConfiguredAspectFactory { + public static final String NAME = "AndroidStudioInfoAspect"; + public static final String IDE_RESOLVE = "ide-resolve"; + public static final String IDE_BUILD = "ide-build"; + public static final String IDE_BUILD_SUFFIX = ".aswb-build"; + + @Override + public AspectDefinition getDefinition() { + return new AspectDefinition.Builder(NAME) + .requireProvider(JavaSourceInfoProvider.class) + .attributeAspect("deps", AndroidStudioInfoAspect.class) + .build(); + } + + @Override + public Aspect create(ConfiguredTarget base, RuleContext ruleContext) { + NestedSetBuilder ideBuildFilesBuilder = NestedSetBuilder.stableOrder(); + Iterable deps = + ruleContext.getPrerequisites("deps", Mode.TARGET, AndroidStudioInfoFilesProvider.class); + for (AndroidStudioInfoFilesProvider dep : deps) { + ideBuildFilesBuilder.addTransitive(dep.getIdeBuildFiles()); + } + + RuleIdeInfo.Kind ruleKind = getRuleKind(ruleContext.getRule()); + if (ruleKind != RuleIdeInfo.Kind.UNRECOGNIZED) { + Artifact ideBuildFile = createIdeBuildArtifact(base, ruleContext, ruleKind); + ideBuildFilesBuilder.add(ideBuildFile); + } + + NestedSet ideBuildFiles = ideBuildFilesBuilder.build(); + return new Aspect.Builder(NAME) + .addOutputGroup(IDE_BUILD, ideBuildFiles) + .addProvider( + AndroidStudioInfoFilesProvider.class, new AndroidStudioInfoFilesProvider(ideBuildFiles)) + .build(); + } + + private Artifact createIdeBuildArtifact( + ConfiguredTarget base, RuleContext ruleContext, RuleIdeInfo.Kind ruleKind) { + PathFragment ideBuildFilePath = getOutputFilePath(base, ruleContext); + Root genfilesDirectory = ruleContext.getConfiguration().getGenfilesDirectory(); + Artifact ideBuildFile = + ruleContext + .getAnalysisEnvironment() + .getDerivedArtifact(ideBuildFilePath, genfilesDirectory); + + RuleIdeInfo.Builder outputBuilder = RuleIdeInfo.newBuilder(); + + outputBuilder.setLabel(base.getLabel().toString()); + + outputBuilder.setBuildFile( + ruleContext + .getRule() + .getPackage() + .getBuildFile() + .getPath() + .toString()); + + outputBuilder.setKind(ruleKind); + + // Calculate source files. + JavaSourceInfoProvider sourceInfoProvider = base.getProvider(JavaSourceInfoProvider.class); + Collection sourceFiles = + sourceInfoProvider != null + ? sourceInfoProvider.getSourceFiles() + : ImmutableList.of(); + for (Artifact sourceFile : sourceFiles) { + outputBuilder.addSources(makeArtifactLocation(sourceFile)); + } + + outputBuilder.setJavaRuleIdeInfo(makeJavaRuleIdeInfo(base)); + + final RuleIdeInfo ruleIdeInfo = outputBuilder.build(); + ruleContext.registerAction( + new BinaryFileWriteAction( + ruleContext.getActionOwner(), + ideBuildFile, + new ByteSource() { + @Override + public InputStream openStream() throws IOException { + return ruleIdeInfo.toByteString().newInput(); + } + }, + /*makeExecutable =*/ false)); + return ideBuildFile; + } + + private static ArtifactLocation makeArtifactLocation(Artifact artifact) { + return ArtifactLocation.newBuilder() + .setRootPath(artifact.getRoot().getPath().toString()) + .setRelativePath(artifact.getRootRelativePathString()) + .build(); + } + + private static JavaRuleIdeInfo makeJavaRuleIdeInfo(ConfiguredTarget base) { + JavaRuleIdeInfo.Builder builder = JavaRuleIdeInfo.newBuilder(); + JavaRuleOutputJarsProvider outputJarsProvider = + base.getProvider(JavaRuleOutputJarsProvider.class); + if (outputJarsProvider != null) { + { + LibraryArtifact.Builder jarsBuilder = LibraryArtifact.newBuilder(); + Artifact classJar = outputJarsProvider.getClassJar(); + if (classJar != null) { + jarsBuilder.setJar(makeArtifactLocation(classJar)); + } + Artifact srcJar = outputJarsProvider.getSrcJar(); + if (srcJar != null) { + jarsBuilder.setSourceJar(makeArtifactLocation(srcJar)); + } + if (jarsBuilder.hasJar() || jarsBuilder.hasSourceJar()) { + builder.addJars(jarsBuilder.build()); + } + } + + { + LibraryArtifact.Builder genjarsBuilder = LibraryArtifact.newBuilder(); + + Artifact genClassJar = outputJarsProvider.getGenClassJar(); + if (genClassJar != null) { + genjarsBuilder.setJar(makeArtifactLocation(genClassJar)); + } + Artifact gensrcJar = outputJarsProvider.getGensrcJar(); + if (gensrcJar != null) { + genjarsBuilder.setSourceJar(makeArtifactLocation(gensrcJar)); + } + if (genjarsBuilder.hasJar() || genjarsBuilder.hasSourceJar()) { + builder.addJars(genjarsBuilder.build()); + } + } + } + + return builder.build(); + } + + private PathFragment getOutputFilePath(ConfiguredTarget base, RuleContext ruleContext) { + PathFragment packagePathFragment = + ruleContext.getLabel().getPackageIdentifier().getPathFragment(); + String name = base.getLabel().getName(); + return new PathFragment(packagePathFragment, new PathFragment(name + IDE_BUILD_SUFFIX)); + } + + private RuleIdeInfo.Kind getRuleKind(Rule rule) { + RuleIdeInfo.Kind kind; + if ("java_library".equals(rule.getRuleClassObject().getName())) { + kind = RuleIdeInfo.Kind.JAVA_LIBRARY; + } else { + kind = RuleIdeInfo.Kind.UNRECOGNIZED; + } + return kind; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoFilesProvider.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoFilesProvider.java new file mode 100644 index 0000000000..5795ae507b --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoFilesProvider.java @@ -0,0 +1,36 @@ +// Copyright 2014 Google Inc. 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 com.google.devtools.build.lib.actions.Artifact; +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; + +/** + * File provider for Android Studio ide build files. + */ +@Immutable +public final class AndroidStudioInfoFilesProvider implements TransitiveInfoProvider { + private final NestedSet ideBuildFiles; + + public AndroidStudioInfoFilesProvider(NestedSet ideBuildFiles) { + this.ideBuildFiles = ideBuildFiles; + } + + public NestedSet getIdeBuildFiles() { + return ideBuildFiles; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java index 60afde4567..5dcb16db29 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java @@ -215,6 +215,10 @@ public class JavaLibrary implements RuleConfiguredTargetFactory { ruleContext, common, ImmutableList.of(), classJar, srcJar, genClassJar, gensrcJar, ImmutableMap.of(), helper, filesBuilder, builder); + builder.add( + JavaRuleOutputJarsProvider.class, + new JavaRuleOutputJarsProvider(classJar, srcJar, genClassJar, gensrcJar)); + NestedSet filesToBuild = filesBuilder.build(); common.addTransitiveInfoProviders(builder, filesToBuild, classJar); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuleOutputJarsProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuleOutputJarsProvider.java new file mode 100644 index 0000000000..e553010f96 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuleOutputJarsProvider.java @@ -0,0 +1,57 @@ +// Copyright 2014 Google Inc. 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.java; + +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +import javax.annotation.Nullable; + +/** + * Provides information about jar files produced by a Java rule. + */ +@Immutable +public final class JavaRuleOutputJarsProvider implements TransitiveInfoProvider { + @Nullable private final Artifact classJar; + private final Artifact srcJar; + private final Artifact genClassJar; + private final Artifact gensrcJar; + + public JavaRuleOutputJarsProvider( + Artifact classJar, Artifact srcJar, Artifact genClassJar, Artifact gensrcJar) { + this.classJar = classJar; + this.srcJar = srcJar; + this.genClassJar = genClassJar; + this.gensrcJar = gensrcJar; + } + + @Nullable + public Artifact getClassJar() { + return classJar; + } + + public Artifact getSrcJar() { + return srcJar; + } + + public Artifact getGenClassJar() { + return genClassJar; + } + + public Artifact getGensrcJar() { + return gensrcJar; + } +} -- cgit v1.2.3