Skip to content

Commit

Permalink
[Reland] Accept proto paths relative to proto_source_root as direct d…
Browse files Browse the repository at this point in the history
…ependencies.

This is a reland of 5deca4c.

This will make protoc see as direct dependencies the .proto files that were included using the proto_source_root flag.

Until now, Bazel passed to protoc the direct dependencies of a target as the path relative to the WORKSPACE, which made it fail when a shorter path, relative to the package was used.

Progress on #4544.

RELNOTES: None.
PiperOrigin-RevId: 203808292
  • Loading branch information
Googler authored and Copybara-Service committed Jul 9, 2018
1 parent 68e92b4 commit e895664
Show file tree
Hide file tree
Showing 12 changed files with 572 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ private void createProtoCompileAction(SupportData supportData, Collection<Artifa
supportData.getTransitiveImports(),
supportData.getProtosInDirectDeps(),
supportData.getTransitiveProtoPathFlags(),
supportData.getDirectProtoSourceRoots(),
ruleContext.getLabel(),
outputs,
"C++",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ private void createProtoCompileAction(Artifact sourceJar) {
supportData.getTransitiveImports(),
supportData.getProtosInDirectDeps(),
supportData.getTransitiveProtoPathFlags(),
supportData.getDirectProtoSourceRoots(),
ruleContext.getLabel(),
ImmutableList.of(sourceJar),
"JavaLite",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ private void createProtoCompileAction(Artifact sourceJar) {
supportData.getTransitiveImports(),
supportData.getProtosInDirectDeps(),
supportData.getTransitiveProtoPathFlags(),
supportData.getDirectProtoSourceRoots(),
ruleContext.getLabel(),
ImmutableList.of(sourceJar),
"Java (Immutable)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public void createProtoCompileAction(
supportData.getTransitiveImports(),
supportData.getProtosInDirectDeps(),
supportData.getTransitiveProtoPathFlags(),
supportData.getDirectProtoSourceRoots(),
skylarkRuleContext.getLabel(),
ImmutableList.of(sourceJar),
"JavaLite",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ private J2ObjcMappingFileProvider createJ2ObjcProtoCompileActions(
supportData.getTransitiveImports(),
supportData.getProtosInDirectDeps(),
supportData.getTransitiveProtoPathFlags(),
supportData.getDirectProtoSourceRoots(),
ruleContext.getLabel(),
outputs,
"j2objc",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,22 @@ public ConfiguredTarget create(RuleContext ruleContext)

NestedSet<Artifact> transitiveImports =
ProtoCommon.collectTransitiveImports(ruleContext, protoSources);
NestedSet<String> protoPathFlags = ProtoCommon.collectTransitiveProtoPathFlags(ruleContext);

NestedSet<Artifact> protosInDirectDeps = ProtoCommon.computeProtosInDirectDeps(ruleContext);

String protoSourceRoot = ProtoCommon.getProtoSourceRoot(ruleContext);
NestedSet<String> directProtoSourceRoots =
ProtoCommon.getProtoSourceRootsOfDirectDependencies(ruleContext, protoSourceRoot);
NestedSet<String> protoPathFlags =
ProtoCommon.collectTransitiveProtoPathFlags(ruleContext, protoSourceRoot);

final SupportData supportData =
SupportData.create(
/* nonWeakDepsPredicate= */ Predicates.<TransitiveInfoCollection>alwaysTrue(),
protoSources,
protosInDirectDeps,
transitiveImports,
protoPathFlags,
directProtoSourceRoots,
!protoSources.isEmpty());

Artifact descriptorSetOutput =
Expand All @@ -75,7 +80,8 @@ public ConfiguredTarget create(RuleContext ruleContext)
descriptorSetOutput,
/* allowServices= */ true,
dependenciesDescriptorSets,
protoPathFlags);
protoPathFlags,
directProtoSourceRoots);

Runfiles dataRunfiles =
ProtoCommon.createDataRunfilesProvider(transitiveImports, ruleContext)
Expand All @@ -91,7 +97,8 @@ public ConfiguredTarget create(RuleContext ruleContext)
checkDepsProtoSources,
descriptorSetOutput,
transitiveDescriptorSetOutput,
protoPathFlags);
protoPathFlags,
protoSourceRoot);

return new RuleConfiguredTargetBuilder(ruleContext)
.setFilesToBuild(NestedSetBuilder.create(STABLE_ORDER, descriptorSetOutput))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,28 +100,66 @@ public static NestedSet<Artifact> collectDependenciesDescriptorSets(RuleContext
}

/**
* Returns all proto source roots in this lib and in its transitive dependencies.
* Returns all proto source roots in this lib ({@code currentProtoSourceRoot}) and in its
* transitive dependencies.
*
* Build will fail if the {@code proto_source_root} of the current lib is different than the
* package name.
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
public static NestedSet<String> collectTransitiveProtoPathFlags(RuleContext ruleContext) {
public static NestedSet<String> collectTransitiveProtoPathFlags(
RuleContext ruleContext, String currentProtoSourceRoot) {
NestedSetBuilder<String> protoPath = NestedSetBuilder.stableOrder();

// first add the protoSourceRoot of the current target, if any
if (currentProtoSourceRoot != null && !currentProtoSourceRoot.isEmpty()) {
protoPath.add(currentProtoSourceRoot);
}

for (ProtoSourcesProvider provider :
ruleContext.getPrerequisites("deps", Mode.TARGET, ProtoSourcesProvider.class)) {
protoPath.addTransitive(provider.getTransitiveProtoPathFlags());
}

return protoPath.build();
}

/**
* Returns the {@code proto_source_root} of the current library or null if none is specified.
*
* <p>Build will fail if the {@code proto_source_root} of the current library is different than
* the package name.
*/
@Nullable
public static String getProtoSourceRoot(RuleContext ruleContext) {
String protoSourceRoot =
ruleContext.attributes().get("proto_source_root", Type.STRING);
if (protoSourceRoot != null && !protoSourceRoot.isEmpty()) {
checkProtoSourceRootIsTheSameAsPackage(protoSourceRoot, ruleContext);
protoPath.add(protoSourceRoot);
}
return protoSourceRoot;
}

for (ProtoSourcesProvider provider : ruleContext.getPrerequisites(
"deps", Mode.TARGET, ProtoSourcesProvider.class)) {
protoPath.addTransitive(provider.getTransitiveProtoPathFlags());
/**
* Returns a set of the {@code proto_source_root} collected from the current library and the
* direct dependencies.
*
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
public static NestedSet<String> getProtoSourceRootsOfDirectDependencies(
RuleContext ruleContext, String currentProtoSourceRoot) {
NestedSetBuilder<String> protoSourceRoots = NestedSetBuilder.stableOrder();
if (currentProtoSourceRoot != null && !currentProtoSourceRoot.isEmpty()) {
protoSourceRoots.add(currentProtoSourceRoot);
}

return protoPath.build();
for (ProtoSourcesProvider provider :
ruleContext.getPrerequisites("deps", Mode.TARGET, ProtoSourcesProvider.class)) {
String protoSourceRoot = provider.getProtoSourceRoot();
if (protoSourceRoot != null && !protoSourceRoot.isEmpty()) {
protoSourceRoots.add(provider.getProtoSourceRoot());
}
}

return protoSourceRoots.build();
}

private static void checkProtoSourceRootIsTheSameAsPackage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLineItem;
import com.google.devtools.build.lib.actions.CommandLineItem.CapturingMapFn;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.actions.ResourceSet;
Expand All @@ -50,6 +51,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import javax.annotation.Nullable;

/** Constructs actions to run the protocol compiler to generate sources from .proto files. */
Expand Down Expand Up @@ -296,6 +298,7 @@ CustomCommandLine.Builder createProtoCompilerCommandLine() throws MissingPrerequ
addIncludeMapArguments(
result,
areDepsStrict ? supportData.getProtosInDirectDeps() : null,
supportData.getDirectProtoSourceRoots(),
supportData.getTransitiveImports());

if (areDepsStrict) {
Expand Down Expand Up @@ -331,7 +334,8 @@ public static void writeDescriptorSet(
Artifact output,
boolean allowServices,
NestedSet<Artifact> transitiveDescriptorSets,
NestedSet<String> protoSourceRoots) {
NestedSet<String> protoSourceRoots,
NestedSet<String> directProtoSourceRoots) {
if (protosToCompile.isEmpty()) {
ruleContext.registerAction(
FileWriteAction.createEmptyWithInputs(
Expand All @@ -347,6 +351,7 @@ public static void writeDescriptorSet(
transitiveSources,
protosInDirectDeps,
protoSourceRoots,
directProtoSourceRoots,
ruleContext.getLabel(),
ImmutableList.of(output),
"Descriptor Set",
Expand Down Expand Up @@ -394,6 +399,7 @@ public static void registerActions(
NestedSet<Artifact> transitiveSources,
NestedSet<Artifact> protosInDirectDeps,
NestedSet<String> protoSourceRoots,
NestedSet<String> directProtoSourceRoots,
Label ruleLabel,
Iterable<Artifact> outputs,
String flavorName,
Expand All @@ -406,6 +412,7 @@ public static void registerActions(
transitiveSources,
protosInDirectDeps,
protoSourceRoots,
directProtoSourceRoots,
ruleLabel,
outputs,
flavorName,
Expand All @@ -423,6 +430,7 @@ private static SpawnAction.Builder createActions(
NestedSet<Artifact> transitiveSources,
@Nullable NestedSet<Artifact> protosInDirectDeps,
NestedSet<String> protoSourceRoots,
NestedSet<String> directProtoSourceRoots,
Label ruleLabel,
Iterable<Artifact> outputs,
String flavorName,
Expand Down Expand Up @@ -458,6 +466,7 @@ private static SpawnAction.Builder createActions(
protosToCompile,
transitiveSources,
protoSourceRoots,
directProtoSourceRoots,
areDepsStrict(ruleContext) ? protosInDirectDeps : null,
ruleLabel,
allowServices,
Expand Down Expand Up @@ -495,6 +504,7 @@ static CustomCommandLine createCommandLineFromToolchains(
Iterable<Artifact> protosToCompile,
NestedSet<Artifact> transitiveSources,
NestedSet<String> transitiveProtoPathFlags,
NestedSet<String> directProtoSourceRoots,
@Nullable NestedSet<Artifact> protosInDirectDeps,
Label ruleLabel,
boolean allowServices,
Expand Down Expand Up @@ -537,7 +547,7 @@ static CustomCommandLine createCommandLineFromToolchains(
cmdLine.addAll(protocOpts);

// Add include maps
addIncludeMapArguments(cmdLine, protosInDirectDeps, transitiveSources);
addIncludeMapArguments(cmdLine, protosInDirectDeps, directProtoSourceRoots, transitiveSources);

if (protosInDirectDeps != null) {
cmdLine.addFormatted(STRICT_DEPS_FLAG_TEMPLATE, ruleLabel);
Expand All @@ -558,6 +568,7 @@ static CustomCommandLine createCommandLineFromToolchains(
static void addIncludeMapArguments(
CustomCommandLine.Builder commandLine,
@Nullable NestedSet<Artifact> protosInDirectDependencies,
NestedSet<String> directProtoSourceRoots,
NestedSet<Artifact> transitiveImports) {
commandLine.addAll(VectorArg.of(transitiveImports).mapped(EXPAND_TRANSITIVE_IMPORT_ARG));
if (protosInDirectDependencies != null) {
Expand All @@ -566,7 +577,8 @@ static void addIncludeMapArguments(
"--direct_dependencies",
VectorArg.join(":")
.each(protosInDirectDependencies)
.mapped(EXPAND_TO_PATH_IGNORING_REPOSITORY));
.mapped(new ExpandToPathFn(directProtoSourceRoots)));

} else {
// The proto compiler requires an empty list to turn on strict deps checking
commandLine.add("--direct_dependencies=");
Expand All @@ -584,6 +596,24 @@ static void addIncludeMapArguments(
args.accept(
"-I" + getPathIgnoringRepository(artifact) + "=" + artifact.getExecPathString());

@AutoCodec
@AutoCodec.VisibleForSerialization
static final class ExpandToPathFn implements CapturingMapFn<Artifact> {
private final NestedSet<String> directProtoSourceRoots;

public ExpandToPathFn(NestedSet<String> directProtoSourceRoots) {
this.directProtoSourceRoots = directProtoSourceRoots;
}

@Override
public void expandToCommandLine(Artifact proto, Consumer<String> args) {
for (String directProtoSourceRoot : directProtoSourceRoots) {
expandToPathIgnoringSourceRoot(proto, directProtoSourceRoot, args);
}
EXPAND_TO_PATH_IGNORING_REPOSITORY.expandToCommandLine(proto, args);
}
}

@AutoCodec @AutoCodec.VisibleForSerialization
static final CommandLineItem.MapFn<Artifact> EXPAND_TO_PATH_IGNORING_REPOSITORY =
(artifact, args) -> args.accept(getPathIgnoringRepository(artifact));
Expand All @@ -603,6 +633,29 @@ private static String getPathIgnoringRepository(Artifact artifact) {
.toString();
}

private static void expandToPathIgnoringSourceRoot(
Artifact artifact, String directProtoSourceRoot, Consumer<String> args) {
// TODO(bazel-team): IAE is caught here because every artifact is relativized against every
// directProtoSourceRoot. Instead of catching the exception, a check should be performed
// to see if the artifact has the root as a substring before relativizing.
try {
String relativePath =
artifact
.getRootRelativePath()
.relativeTo(
artifact
.getOwnerLabel()
.getPackageIdentifier()
.getRepository()
.getPathUnderExecRoot())
.relativeTo(directProtoSourceRoot)
.toString();
args.accept(relativePath);
} catch (IllegalArgumentException exception) {
// do nothing
}
}

/**
* Describes a toolchain and the value to replace for a $(OUT) that might appear in its
* commandLine() (e.g., "bazel-out/foo.srcjar").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ public static ProtoSourcesProvider create(
NestedSet<Artifact> checkDepsProtoSources,
Artifact directDescriptorSet,
NestedSet<Artifact> transitiveDescriptorSets,
NestedSet<String> transitiveProtoPathFlags) {
NestedSet<String> transitiveProtoPathFlags,
String protoSourceRoot) {
return new AutoValue_ProtoSourcesProvider(
transitiveImports,
transitiveProtoSources,
directProtoSources,
checkDepsProtoSources,
directDescriptorSet,
transitiveDescriptorSets,
transitiveProtoPathFlags);
transitiveProtoPathFlags,
protoSourceRoot);
}

/**
Expand Down Expand Up @@ -108,5 +110,8 @@ public static ProtoSourcesProvider create(
@Override
public abstract NestedSet<String> getTransitiveProtoPathFlags();

/** The {@code proto_source_root} of the current library. */
public abstract String getProtoSourceRoot();

ProtoSourcesProvider() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ public static SupportData create(
NestedSet<Artifact> protosInDirectDeps,
NestedSet<Artifact> transitiveImports,
NestedSet<String> transitiveProtoPathFlags,
NestedSet<String> directProtoSourceRoots,
boolean hasProtoSources) {
return new AutoValue_SupportData(
nonWeakDepsPredicate,
directProtoSources,
transitiveImports,
protosInDirectDeps,
transitiveProtoPathFlags,
directProtoSourceRoots,
hasProtoSources);
}

Expand All @@ -62,6 +64,11 @@ public static SupportData create(
*/
public abstract NestedSet<String> getTransitiveProtoPathFlags();

/**
* The {@code proto_source_root}'s collected from the current library and the direct dependencies.
*/
public abstract NestedSet<String> getDirectProtoSourceRoots();

public abstract boolean hasProtoSources();

SupportData() {}
Expand Down
Loading

0 comments on commit e895664

Please sign in to comment.