Skip to content

Commit

Permalink
Add ProtoInfo constructor to Starlark
Browse files Browse the repository at this point in the history
  • Loading branch information
cheister committed Jun 26, 2021
1 parent 6d603b7 commit e8c9773
Show file tree
Hide file tree
Showing 9 changed files with 529 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/google/devtools/build/lib/rules/proto/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//src/main/java/com/google/devtools/common/options",
"//src/main/java/net/starlark/java/eval",
"//src/main/java/net/starlark/java/syntax",
"//third_party:auto_value",
"//third_party:guava",
"//third_party:jsr305",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.STRING;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.StarlarkProviderIdentifier;
import com.google.devtools.build.lib.util.FileType;

/**
Expand Down Expand Up @@ -61,7 +63,12 @@ public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironmen
<code>proto_library</code> targets.
It may not depend on language-specific libraries.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.override(attr("deps", LABEL_LIST).allowedRuleClasses("proto_library").allowedFileTypes())
.override(attr("deps", LABEL_LIST)
.allowedFileTypes()
.mandatoryProvidersList(
ImmutableList.of(
ImmutableList.of(
StarlarkProviderIdentifier.forKey(ProtoInfo.PROVIDER.getKey())))))
/* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(srcs) -->
The list of <code>.proto</code> and <code>.protodevel</code> files that are
processed to create the target. This is usually a non empty list. One usecase
Expand All @@ -77,7 +84,12 @@ public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironmen
List of proto_library targets that can be referenced via "import public" in the proto
source.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("exports", LABEL_LIST).allowedRuleClasses("proto_library").allowedFileTypes())
.add(attr("exports", LABEL_LIST)
.allowedFileTypes()
.mandatoryProvidersList(
ImmutableList.of(
ImmutableList.of(
StarlarkProviderIdentifier.forKey(ProtoInfo.PROVIDER.getKey())))))
/* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(strip_import_prefix) -->
The prefix to strip from the paths of the .proto files in this rule.
Expand All @@ -101,7 +113,7 @@ public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironmen
prefix is added.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("import_prefix", STRING))
.advertiseStarlarkProvider(ProtoInfo.PROVIDER.id())
.advertiseStarlarkProvider(StarlarkProviderIdentifier.forKey(ProtoInfo.PROVIDER.getKey()))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;

/**
* Utility functions for proto_library and proto aspect implementations.
Expand Down Expand Up @@ -107,9 +108,9 @@ private static NestedSet<ProtoSource> computeExportedProtos(
}

private static NestedSet<ProtoSource> computeTransitiveProtoSources(
ImmutableList<ProtoInfo> protoDeps, Library library) {
ImmutableList<ProtoInfo> protoDeps, ImmutableList<ProtoSource> protoSources) {
NestedSetBuilder<ProtoSource> result = NestedSetBuilder.naiveLinkOrder();
result.addAll(library.getSources());
result.addAll(protoSources);
for (ProtoInfo dep : protoDeps) {
result.addTransitive(dep.getTransitiveSources());
}
Expand Down Expand Up @@ -387,7 +388,31 @@ public static ProtoInfo createProtoInfo(

ImmutableList<ProtoSource> directSources = library.getSources();
PathFragment directProtoSourceRoot = library.getSourceRoot();
NestedSet<ProtoSource> transitiveSources = computeTransitiveProtoSources(deps, library);
Artifact directDescriptorSet =
ruleContext.getGenfilesArtifact(
ruleContext.getLabel().getName() + "-descriptor-set.proto.bin");

return createProtoInfo(
originalDirectProtoSources,
directSources,
deps,
exports,
directProtoSourceRoot,
directDescriptorSet,
Location.BUILTIN);
}

public static ProtoInfo createProtoInfo(
ImmutableList<Artifact> originalDirectProtoSources,
ImmutableList<ProtoSource> directSources,
ImmutableList<ProtoInfo> deps,
ImmutableList<ProtoInfo> exports,
PathFragment directProtoSourceRoot,
Artifact directDescriptorSet,
Location location) {

NestedSet<ProtoSource> transitiveSources =
computeTransitiveProtoSources(deps, directSources);
NestedSet<Artifact> transitiveProtoSources =
computeTransitiveProtoSourceArtifacts(directSources, deps);
NestedSet<Artifact> transitiveOriginalProtoSources =
Expand All @@ -396,9 +421,6 @@ public static ProtoInfo createProtoInfo(
computeTransitiveProtoSourceRoots(deps, directProtoSourceRoot.getSafePathString());
NestedSet<Artifact> strictImportableProtosForDependents =
computeStrictImportableProtosForDependents(directSources, deps);
Artifact directDescriptorSet =
ruleContext.getGenfilesArtifact(
ruleContext.getLabel().getName() + "-descriptor-set.proto.bin");
NestedSet<Artifact> transitiveDescriptorSets =
computeTransitiveDescriptorSets(directDescriptorSet, deps);

Expand All @@ -420,7 +442,8 @@ public static ProtoInfo createProtoInfo(
transitiveDescriptorSets,
exportedSources,
strictImportableSources,
publicImportSources);
publicImportSources,
location);
}

public static Runfiles.Builder createDataRunfilesProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.starlarkbuildapi.FileApi;
import com.google.devtools.build.lib.starlarkbuildapi.ProtoInfoApi;
import com.google.devtools.build.lib.starlarkbuildapi.proto.ProtoBootstrap;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/**
* Configured target classes that implement this class can contribute .proto files to the
Expand All @@ -33,13 +40,6 @@
@Immutable
@AutoCodec
public final class ProtoInfo extends NativeInfo implements ProtoInfoApi<Artifact> {
/** Provider class for {@link ProtoInfo} objects. */
public static class ProtoInfoProvider extends BuiltinProvider<ProtoInfo>
implements ProtoInfoProviderApi {
public ProtoInfoProvider() {
super(ProtoBootstrap.PROTO_INFO_STARLARK_NAME, ProtoInfo.class);
}
}

public static final ProtoInfoProvider PROVIDER = new ProtoInfoProvider();

Expand Down Expand Up @@ -93,7 +93,9 @@ public ProtoInfo(
// Layering checks.
NestedSet<ProtoSource> exportedSources,
NestedSet<ProtoSource> strictImportableSources,
NestedSet<ProtoSource> publicImportSources) {
NestedSet<ProtoSource> publicImportSources,
Location creationLocation) {
super(creationLocation);
this.directSources = directSources;
this.directProtoSources = extractProtoSources(directSources);
this.originalDirectProtoSources = extractOriginalProtoSources(directSources);
Expand Down Expand Up @@ -263,4 +265,63 @@ public NestedSet<ProtoSource> getStrictImportableSources() {
NestedSet<ProtoSource> getPublicImportSources() {
return publicImportSources;
}

/** Provider class for {@link ProtoInfo} objects. */
public static class ProtoInfoProvider extends BuiltinProvider<ProtoInfo>
implements ProtoInfoProviderApi {
private ProtoInfoProvider() {
super(ProtoBootstrap.PROTO_INFO_STARLARK_NAME, ProtoInfo.class);
}

private void checkSequenceOfProtoInfo(Sequence<?> seq, String field) throws EvalException {
for (Object v : seq) {
if (!(v instanceof ProtoInfo)) {
throw Starlark.errorf("Expected 'sequence of ProtoInfo' for '%s', found element of type '%s'", field, Starlark.type(v));
}
}
}

@Override
@SuppressWarnings({"unchecked"})
public ProtoInfo protoInfo(
String protoSourceRootApi,
FileApi descriptorSetApi,
Sequence<?> sourcesApi,
Sequence<?> depsApi,
Sequence<?> exportsApi,
StarlarkThread thread)
throws EvalException {

checkSequenceOfProtoInfo(depsApi, "deps");
checkSequenceOfProtoInfo(exportsApi, "exports");

Artifact directDescriptorSet = (Artifact) descriptorSetApi;

List<Artifact> directSourcesList = Sequence.cast(sourcesApi, Artifact.class, "sources");
ImmutableList<Artifact> originalDirectProtoSources = ImmutableList.copyOf(directSourcesList);

ImmutableList.Builder<ProtoSource> sourcesBuilder = ImmutableList.builder();
for(Artifact src: directSourcesList) {
sourcesBuilder.add(new ProtoSource(src, PathFragment.create(protoSourceRootApi)));
}
ImmutableList<ProtoSource> sources = sourcesBuilder.build();

List<ProtoInfo> depsList = Sequence.cast(depsApi, ProtoInfo.class, "deps");
ImmutableList<ProtoInfo> deps = ImmutableList.copyOf(depsList);

List<ProtoInfo> exportsList = Sequence.cast(exportsApi, ProtoInfo.class, "exports");
ImmutableList<ProtoInfo> exports = ImmutableList.copyOf(exportsList);

PathFragment protoSourceRoot = PathFragment.create(protoSourceRootApi);

return ProtoCommon.createProtoInfo(
originalDirectProtoSources,
sources,
deps,
exports,
protoSourceRoot,
directDescriptorSet,
thread.getCallerLocation());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.docgen.annot.StarlarkConstructor;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi;
import com.google.devtools.build.lib.starlarkbuildapi.core.StructApi;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.ParamType;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.StarlarkThread;

/** Info object propagating information about protocol buffer sources. */
@StarlarkBuiltin(
Expand All @@ -35,11 +41,6 @@
+ "rules_proto</a>."
+ "</p>")
public interface ProtoInfoApi<FileT extends FileApi> extends StructApi {
/** Provider class for {@link ProtoInfoApi} objects. */
@StarlarkBuiltin(name = "Provider", documented = false, doc = "")
interface ProtoInfoProviderApi extends ProviderApi {
// Currently empty. ProtoInfo cannot be created from Starlark at the moment.
}

@StarlarkMethod(
name = "transitive_imports",
Expand Down Expand Up @@ -105,4 +106,54 @@ interface ProtoInfoProviderApi extends ProviderApi {
+ " as a source, that source file would be imported as 'import c/d.proto'",
structField = true)
String getDirectProtoSourceRoot();

/** Provider class for {@link ProtoInfoApi} objects. */
@StarlarkBuiltin(name = "Provider", documented = false, doc = "")
interface ProtoInfoProviderApi extends ProviderApi {

@StarlarkMethod(
name = "ProtoInfo",
doc = "The <code>ProtoInfo</code> constructor.",
parameters = {
@Param(
name = "proto_source_root",
allowedTypes = {@ParamType(type = String.class)},
named = true,
doc = "The directory relative to which the .proto files are defined."),
@Param(
name = "descriptor_set",
allowedTypes = { @ParamType(type = FileApi.class)},
named = true,
doc = "The FileDescriptorSet of the direct sources."),
@Param(
name = "sources",
allowedTypes = {@ParamType(type = Sequence.class, generic1 = FileApi.class)},
named = true,
defaultValue = "[]",
doc = "Proto sources."),
@Param(
name = "deps",
allowedTypes = {@ParamType(type = Sequence.class, generic1 = ProtoInfoApi.class)},
named = true,
defaultValue = "[]",
doc = "Proto dependencies."),
@Param(
name = "exports",
allowedTypes = {@ParamType(type = Sequence.class, generic1 = ProtoInfoApi.class)},
named = true,
defaultValue = "[]",
doc = "Proto exports."),
},
selfCall = true,
useStarlarkThread = true)
@StarlarkConstructor
ProtoInfoApi<?> protoInfo(
String protoSourceRoot,
FileApi descriptorSet,
Sequence<?> sources,
Sequence<?> deps,
Sequence<?> exports,
StarlarkThread thread)
throws EvalException;
}
}
3 changes: 3 additions & 0 deletions src/test/java/com/google/devtools/build/lib/rules/proto/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,14 @@ java_test(
name = "ProtoInfoStarlarkApiTest",
srcs = ["ProtoInfoStarlarkApiTest.java"],
deps = [
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
"//src/main/java/com/google/devtools/build/lib/analysis:configured_target",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/rules/proto",
"//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/proto",
"//src/main/java/com/google/devtools/build/lib/util",
"//src/test/java/com/google/devtools/build/lib/actions/util",
"//src/test/java/com/google/devtools/build/lib/analysis/util",
"//src/test/java/com/google/devtools/build/lib/packages:testutil",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
Expand Down Expand Up @@ -90,7 +91,8 @@ private ProtoInfo protoInfo(
/* strictImportableSources */ NestedSetBuilder.wrap(
Order.STABLE_ORDER, strictImportableSources),
/* publicImportSources */ NestedSetBuilder.wrap(
Order.STABLE_ORDER, publicImportProtoSources));
Order.STABLE_ORDER, publicImportProtoSources),
/* location */ Location.fromFileLineColumn("foo", 1, 2));
}

@Test
Expand Down
Loading

0 comments on commit e8c9773

Please sign in to comment.