aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java87
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java100
4 files changed, 211 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
index 36bb1ea586..25e9fe0749 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
@@ -179,7 +179,7 @@ public class ObjcCommandLineOptions extends FragmentOptions {
+ " and system libraries."
)
public boolean prioritizeStaticLibs;
-
+
@Option(
name = "objc_debug_with_GLIBCXX",
defaultValue = "true",
@@ -200,7 +200,17 @@ public class ObjcCommandLineOptions extends FragmentOptions {
+ "build."
)
public Label extraEntitlements;
-
+
+ @Option(
+ name = "experimental_auto_top_level_union_objc_protos",
+ defaultValue = "false",
+ category = "flags",
+ help =
+ "Specifies whether to use the experimental proto generation scheme, in which they are all "
+ + "generated and linked into the final linking target."
+ )
+ public boolean experimentalAutoTopLevelUnionObjCProtos;
+
@VisibleForTesting static final String DEFAULT_MINIMUM_IOS = "7.0";
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
index ec85472ae8..f8ed4411e2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
@@ -74,6 +74,7 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
private final boolean useAbsolutePathsForActions;
private final boolean prioritizeStaticLibs;
private final boolean debugWithGlibcxx;
+ private final boolean experimentalAutoTopLevelUnionObjCProtos;
@Nullable private final Label extraEntitlements;
ObjcConfiguration(ObjcCommandLineOptions objcOptions, BuildConfiguration.Options options,
@@ -100,6 +101,8 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
this.prioritizeStaticLibs = objcOptions.prioritizeStaticLibs;
this.debugWithGlibcxx = objcOptions.debugWithGlibcxx;
this.extraEntitlements = objcOptions.extraEntitlements;
+ this.experimentalAutoTopLevelUnionObjCProtos =
+ objcOptions.experimentalAutoTopLevelUnionObjCProtos;
}
/**
@@ -255,7 +258,7 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
public String getSigningCertName() {
return this.signingCertName;
}
-
+
/**
* Returns true if the linker invocation should contain static library includes before framework
* and system library includes.
@@ -271,4 +274,12 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
public Label getExtraEntitlements() {
return extraEntitlements;
}
+
+ /**
+ * Whether the experimental feature of only generating proto sources at the linking target is
+ * enabled or not.
+ */
+ public boolean experimentalAutoTopLevelUnionObjCProtos() {
+ return experimentalAutoTopLevelUnionObjCProtos;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java
new file mode 100644
index 0000000000..cf102da124
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspect.java
@@ -0,0 +1,87 @@
+// Copyright 2016 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.objc;
+
+import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
+
+import com.google.devtools.build.lib.analysis.ConfiguredAspect;
+import com.google.devtools.build.lib.analysis.ConfiguredNativeAspectFactory;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider;
+
+/**
+ * Aspect that gathers the proto dependencies of the attached rule target, and propagates the proto
+ * values of its dependencies through the ObjcProtoProvider.
+ */
+public class ObjcProtoAspect implements ConfiguredNativeAspectFactory {
+ public static final String NAME = "ObjcProtoAspect";
+
+ @Override
+ public AspectDefinition getDefinition(AspectParameters aspectParameters) {
+ return new AspectDefinition.Builder(NAME)
+ .attributeAspect("deps", ObjcProtoAspect.class)
+ .requiresConfigurationFragments(ObjcConfiguration.class)
+ .build();
+ }
+
+ @Override
+ public ConfiguredAspect create(
+ ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters)
+ throws InterruptedException {
+ ConfiguredAspect.Builder aspectBuilder = new ConfiguredAspect.Builder(NAME, ruleContext);
+ ObjcConfiguration objcConfiguration = ruleContext.getFragment(ObjcConfiguration.class);
+
+ if (!objcConfiguration.experimentalAutoTopLevelUnionObjCProtos()) {
+ // Only process the aspect if the experimental flag is set.
+ return aspectBuilder.build();
+ }
+
+ ObjcProtoProvider.Builder aspectObjcProtoProvider = new ObjcProtoProvider.Builder();
+
+ Iterable<ObjcProtoProvider> depObjcProtoProviders =
+ ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProtoProvider.class);
+ aspectObjcProtoProvider.addTransitive(depObjcProtoProviders);
+
+ // If the rule has the portable_proto_filters, it must be an objc_proto_library configured
+ // to use the third party protobuf library, in contrast with the PB2 internal library. Only
+ // the third party library is enabled to propagate the protos with this aspect.
+ if (ruleContext
+ .attributes()
+ .has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, LABEL_LIST)) {
+ aspectObjcProtoProvider.addPortableProtoFilters(
+ PrerequisiteArtifacts.nestedSet(
+ ruleContext, ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST));
+
+ // Gather up all the dependency protos depended by this target.
+ Iterable<ProtoSourcesProvider> protoProviders =
+ ruleContext.getPrerequisites("deps", Mode.TARGET, ProtoSourcesProvider.class);
+
+ for (ProtoSourcesProvider protoProvider : protoProviders) {
+ aspectObjcProtoProvider.addProtoSources(protoProvider.getTransitiveProtoSources());
+ }
+ }
+
+ // Only add the provider if it has any values, otherwise skip it.
+ if (!aspectObjcProtoProvider.isEmpty()) {
+ aspectBuilder.addProvider(ObjcProtoProvider.class, aspectObjcProtoProvider.build());
+ }
+ return aspectBuilder.build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java
new file mode 100644
index 0000000000..d1ed2b9aea
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProvider.java
@@ -0,0 +1,100 @@
+// Copyright 2016 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.objc;
+
+import com.google.common.base.Preconditions;
+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.collect.nestedset.NestedSetBuilder;
+
+/**
+ * A provider that provides all protos and portable proto filters information in the transitive
+ * closure of its dependencies that are needed for generating and compiling only one version of
+ * proto files.
+ */
+public class ObjcProtoProvider implements TransitiveInfoProvider {
+
+ private final NestedSet<Artifact> protoSources;
+ private final NestedSet<Artifact> portableProtoFilters;
+
+ private ObjcProtoProvider(
+ NestedSet<Artifact> protoSources, NestedSet<Artifact> portableProtoFilters) {
+ this.protoSources = Preconditions.checkNotNull(protoSources);
+ this.portableProtoFilters = Preconditions.checkNotNull(portableProtoFilters);
+ }
+
+ /**
+ * Returns the set of all the protos that the dependencies of this provider has seen.
+ */
+ public NestedSet<Artifact> getProtoSources() {
+ return protoSources;
+ }
+
+ /**
+ * Returns the set of all the associated filters to the collected protos.
+ */
+ public NestedSet<Artifact> getPortableProtoFilters() {
+ return portableProtoFilters;
+ }
+
+ /**
+ * A builder for this context with an API that is optimized for collecting information from
+ * several transitive dependencies.
+ */
+ public static final class Builder {
+ private final NestedSetBuilder<Artifact> protoSources = NestedSetBuilder.linkOrder();
+ private final NestedSetBuilder<Artifact> portableProtoFilters = NestedSetBuilder.linkOrder();
+
+ /**
+ * Adds all the protos to the set of dependencies.
+ */
+ public Builder addProtoSources(NestedSet<Artifact> protoSources) {
+ this.protoSources.addTransitive(protoSources);
+ return this;
+ }
+
+ /**
+ * Adds all the proto filters to the set of dependencies.
+ */
+ public Builder addPortableProtoFilters(Iterable<Artifact> protoFilters) {
+ this.portableProtoFilters.addAll(protoFilters);
+ return this;
+ }
+
+ /**
+ * Add all protos and filters from providers, and propagate them to any (transitive) dependers
+ * on this ObjcProtoProvider.
+ */
+ public Builder addTransitive(Iterable<ObjcProtoProvider> providers) {
+ for (ObjcProtoProvider provider : providers) {
+ this.protoSources.addTransitive(provider.getProtoSources());
+ this.portableProtoFilters.addTransitive(provider.getPortableProtoFilters());
+ }
+ return this;
+ }
+
+ /**
+ * Whether this provider has any protos or filters.
+ */
+ public boolean isEmpty() {
+ return protoSources.isEmpty() && portableProtoFilters.isEmpty();
+ }
+
+ public ObjcProtoProvider build() {
+ return new ObjcProtoProvider(protoSources.build(), portableProtoFilters.build());
+ }
+ }
+}