Allow importing of late loaded dynamic frameworks
Adds a runtime_deps attribute to compilation rules (including objc_binary) that imports a dynamic framework (generated either via the objc_framework or ios_framework rules) into an app bundle without linking against it at build time.
RELNOTES: objc_binary now supports late-loaded dynamic frameworks.
--
MOS_MIGRATED_REVID=125261347
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
index 1f98901..af147d5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
@@ -224,6 +224,7 @@
.setResourceAttributes(new ResourceAttributes(ruleContext))
.addDefines(ruleContext.getTokenizedStringListAttr("defines"))
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
+ .addRuntimeDeps(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET))
.addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET))
.addNonPropagatedDepObjcProviders(
ruleContext.getPrerequisites(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
index 150bbe3..4e15603 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
@@ -275,6 +275,7 @@
.setResourceAttributes(new ResourceAttributes(ruleContext))
.addDefines(ruleContext.getTokenizedStringListAttr("defines"))
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
+ .addRuntimeDeps(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET))
.addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET))
.addNonPropagatedDepObjcProviders(
ruleContext.getPrerequisites(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
index 8bcc72a..952349a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java
@@ -134,8 +134,8 @@
}
static class Builder {
- private RuleContext context;
- private BuildConfiguration buildConfiguration;
+ private final RuleContext context;
+ private final BuildConfiguration buildConfiguration;
private Optional<CompilationAttributes> compilationAttributes = Optional.absent();
private Optional<ResourceAttributes> resourceAttributes = Optional.absent();
private Iterable<SdkFramework> extraSdkFrameworks = ImmutableList.of();
@@ -146,6 +146,7 @@
private Optional<CompilationArtifacts> compilationArtifacts = Optional.absent();
private Iterable<ObjcProvider> depObjcProviders = ImmutableList.of();
private Iterable<ObjcProvider> directDepObjcProviders = ImmutableList.of();
+ private Iterable<ObjcProvider> runtimeDepObjcProviders = ImmutableList.of();
private Iterable<String> defines = ImmutableList.of();
private Iterable<PathFragment> userHeaderSearchPaths = ImmutableList.of();
private Iterable<PathFragment> directDependencyHeaderSearchPaths = ImmutableList.of();
@@ -263,6 +264,22 @@
return this;
}
+ /**
+ * Adds providers for runtime frameworks included in the final app bundle but not linked with
+ * at build time.
+ */
+ Builder addRuntimeDeps(List<? extends TransitiveInfoCollection> runtimeDeps) {
+ ImmutableList.Builder<ObjcProvider> propagatedDeps =
+ ImmutableList.<ObjcProvider>builder();
+
+ for (TransitiveInfoCollection dep : runtimeDeps) {
+ addAnyProviders(propagatedDeps, dep, ObjcProvider.class);
+ }
+ this.runtimeDepObjcProviders = Iterables.concat(
+ this.runtimeDepObjcProviders, propagatedDeps.build());
+ return this;
+ }
+
private <T extends TransitiveInfoProvider> ImmutableList.Builder<T> addAnyProviders(
ImmutableList.Builder<T> listBuilder,
TransitiveInfoCollection collection,
@@ -394,6 +411,14 @@
.addTransitiveAndPropagate(depObjcProviders)
.addTransitiveWithoutPropagating(directDepObjcProviders);
+ for (ObjcProvider provider : runtimeDepObjcProviders) {
+ objcProvider.addTransitiveAndPropagate(ObjcProvider.DYNAMIC_FRAMEWORK_FILE, provider);
+ // TODO(b/28637288): Remove STATIC_FRAMEWORK_FILE and MERGE_ZIP when they are
+ // no longer provided by ios_framework.
+ objcProvider.addTransitiveAndPropagate(ObjcProvider.STATIC_FRAMEWORK_FILE, provider);
+ objcProvider.addTransitiveAndPropagate(ObjcProvider.MERGE_ZIP, provider);
+ }
+
for (CppCompilationContext headerProvider : depCcHeaderProviders) {
objcProvider.addTransitiveAndPropagate(HEADER, headerProvider.getDeclaredIncludeSrcs());
objcProvider.addAll(INCLUDE, headerProvider.getIncludeDirs());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
index 54134ca..e31f994 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
@@ -43,7 +43,7 @@
*/
private static class ObjcLibraryCcLinkParamsStore extends CcLinkParamsStore {
- private ObjcCommon common;
+ private final ObjcCommon common;
public ObjcLibraryCcLinkParamsStore(ObjcCommon common) {
this.common = common;
@@ -76,6 +76,7 @@
.addDefines(ruleContext.getTokenizedStringListAttr("defines"))
.setCompilationArtifacts(CompilationSupport.compilationArtifacts(ruleContext))
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
+ .addRuntimeDeps(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET))
.addDepObjcProviders(
ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class))
.addNonPropagatedDepObjcProviders(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
index a9edec7..fccb4c0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
@@ -724,6 +724,17 @@
.direct_compile_time_input()
.allowedRuleClasses(ALLOWED_DEPS_RULE_CLASSES)
.allowedFileTypes())
+ /* <!-- #BLAZE_RULE($objc_compiling_rule).ATTRIBUTE(runtime_deps) -->
+ The list of framework targets that are late loaded at runtime. They are included in the
+ app bundle but not linked against at build time.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(
+ attr("runtime_deps", LABEL_LIST)
+ .direct_compile_time_input()
+ .allowedRuleClasses("objc_framework")
+ // TODO(b/28637288): ios_framework is experimental and not fully implemented.
+ .allowedRuleClassesWithWarning("ios_framework")
+ .allowedFileTypes())
/* <!-- #BLAZE_RULE($objc_compiling_rule).ATTRIBUTE(non_propagated_deps) -->
The list of targets that are required in order to build this target,
but which are not included in the final bundle.
@@ -936,7 +947,7 @@
<p>The key in <code>${}</code> may be suffixed with <code>:rfc1034identifier</code> (for
example <code>${PRODUCT_NAME::rfc1034identifier}</code>) in which case Blaze will
- replicate Xcode's behavior and replace non-RFC1034-compliant characters with
+ replicate Xcode's behavior and replace non-RFC1034-compliant characters with
<code>-</code>.</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
.add(attr("infoplists", BuildType.LABEL_LIST).allowedFileTypes(PLIST_TYPE))