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 --- src/main/java/BUILD | 2 + .../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 ++++++ src/main/protobuf/BUILD | 1 + src/main/protobuf/android_studio_ide_info.proto | 58 ++++++ 8 files changed, 357 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 create mode 100644 src/main/protobuf/android_studio_ide_info.proto diff --git a/src/main/java/BUILD b/src/main/java/BUILD index 424a80d44e..8297abdcda 100644 --- a/src/main/java/BUILD +++ b/src/main/java/BUILD @@ -184,6 +184,7 @@ java_library( [ "com/google/devtools/build/lib/analysis/**/*.java", "com/google/devtools/build/lib/exec/*.java", + "com/google/devtools/build/lib/ideinfo/**/*.java", "com/google/devtools/build/lib/rules/**/*.java", "com/google/devtools/build/lib/skyframe/*.java", ], @@ -206,6 +207,7 @@ java_library( ":shell", ":skyframe-base", ":vfs", + "//src/main/protobuf:proto_android_studio_ide_info", "//src/main/protobuf:proto_bundlemerge", "//src/main/protobuf:proto_crosstool_config", "//src/main/protobuf:proto_extra_actions_base", 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; + } +} diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD index 719bd7b6a0..2fca35a0a8 100644 --- a/src/main/protobuf/BUILD +++ b/src/main/protobuf/BUILD @@ -9,6 +9,7 @@ FILES = [ "java_compilation", "crosstool_config", "extra_actions_base", + "android_studio_ide_info", "test_status", "bundlemerge", "xcodegen", diff --git a/src/main/protobuf/android_studio_ide_info.proto b/src/main/protobuf/android_studio_ide_info.proto new file mode 100644 index 0000000000..cdbe236759 --- /dev/null +++ b/src/main/protobuf/android_studio_ide_info.proto @@ -0,0 +1,58 @@ +// Copyright 2015 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. + +syntax = "proto3"; + +package blaze; + + +option java_package = "com.google.devtools.build.lib.ideinfo.androidstudio"; + +message ArtifactLocation { + string root_path = 1; + string relative_path = 2; +} + +message LibraryArtifact { + ArtifactLocation jar = 1; + ArtifactLocation interface_jar = 2; + ArtifactLocation source_jar = 3; +} + +message JavaRuleIdeInfo { + repeated LibraryArtifact jars = 1; + repeated LibraryArtifact generated_jars = 2; + ArtifactLocation package_manifest = 3; +} + +message RuleIdeInfo { + enum Kind { + ANDROID_BINARY = 0; + ANDROID_LIBRARY = 1; + ANDROID_TEST = 2; + ANDROID_ROBOELECTRIC_TEST = 3; + JAVA_LIBRARY = 4; + JAVA_TEST = 5; + JAVA_IMPORT = 6; + PROTO_LIBRARY = 7; + } + + string label = 1; + Kind kind = 2; + string build_file = 3; + repeated string dependencies = 4; + repeated string transitive_dependencies = 5; + repeated ArtifactLocation sources = 6; + JavaRuleIdeInfo java_rule_ide_info = 7; +} -- cgit v1.2.3