diff options
Diffstat (limited to 'src')
8 files changed, 212 insertions, 114 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java index 35c228bb0b..a5a9a71240 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.ASSET_CATALOG; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; @@ -54,6 +55,14 @@ import java.util.Set; */ @Immutable final class Bundling { + + /** + * Names of top-level directories in dynamic frameworks (i.e. directly under the + * {@code *.framework} directory) that should not be copied into the final bundle. + */ + private static final ImmutableSet<String> STRIP_FRAMEWORK_DIRS = + ImmutableSet.of("Headers", "PrivateHeaders", "Modules"); + static final class Builder { private String name; private String bundleDirFormat; @@ -259,6 +268,34 @@ final class Bundling { return binaryStringsBuilder.build(); } + private NestedSet<BundleableFile> dynamicFrameworkFiles() { + NestedSetBuilder<BundleableFile> frameworkFilesBuilder = NestedSetBuilder.stableOrder(); + for (Artifact frameworkFile : objcProvider.get(DYNAMIC_FRAMEWORK_FILE)) { + PathFragment frameworkDir = + ObjcCommon.nearestContainerMatching(ObjcCommon.FRAMEWORK_CONTAINER_TYPE, frameworkFile) + .get(); + String frameworkName = frameworkDir.getBaseName(); + PathFragment inFrameworkPath = frameworkFile.getExecPath().relativeTo(frameworkDir); + if (inFrameworkPath.getFirstSegment(STRIP_FRAMEWORK_DIRS) == 0) { + continue; + } + // If this is a top-level file in the framework set the executable bit (to make sure we set + // the bit on the actual dylib binary - other files may also get it but we have no way to + // distinguish them). + int permissions = + inFrameworkPath.segmentCount() == 1 + ? BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE + : BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE; + BundleableFile bundleFile = + new BundleableFile( + frameworkFile, + "Frameworks/" + frameworkName + "/" + inFrameworkPath.getPathString(), + permissions); + frameworkFilesBuilder.add(bundleFile); + } + return frameworkFilesBuilder.build(); + } + /** * Filters files that would map to the same location in the bundle, adding only one copy to the * set of files returned. @@ -289,12 +326,16 @@ final class Bundling { Optional<Artifact> actoolzipOutput = actoolzipOutput(); Optional<Artifact> combinedArchitectureBinary = combinedArchitectureBinary(); NestedSet<BundleableFile> binaryStringsFiles = binaryStringsFiles(); + NestedSet<BundleableFile> dynamicFrameworks = dynamicFrameworkFiles(); NestedSet<Artifact> mergeZips = mergeZips(actoolzipOutput); NestedSet<Artifact> rootMergeZips = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(objcProvider.get(ROOT_MERGE_ZIP)).build(); - bundleFilesBuilder.addAll(binaryStringsFiles).addAll(objcProvider.get(BUNDLE_FILE)); + bundleFilesBuilder + .addAll(binaryStringsFiles) + .addAll(dynamicFrameworks) + .addAll(objcProvider.get(BUNDLE_FILE)); ImmutableList<BundleableFile> bundleFiles = deduplicateByBundlePaths(bundleFilesBuilder.build()); @@ -305,7 +346,6 @@ final class Bundling { .addAll(bundleInfoplist.asSet()) .addTransitive(mergeZips) .addTransitive(rootMergeZips) - .addAll(BundleableFile.toArtifacts(binaryStringsFiles)) .addAll(BundleableFile.toArtifacts(bundleFiles)); return new Bundling( diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 6abcce77b3..45593190e1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -17,11 +17,10 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; import static com.google.devtools.build.lib.rules.cpp.Link.LINK_LIBRARY_FILETYPES; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_CPP; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_FRAMEWORKS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; @@ -31,6 +30,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.CLANG; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.CLANG_PLUSPLUS; @@ -438,8 +438,7 @@ public final class CompilationSupport { .add(compileFlagsForClang(appleConfiguration)) .add(commonLinkAndCompileFlagsForClang(objcProvider, objcConfiguration, appleConfiguration)) .add(objcConfiguration.getCoptsForCompilationMode()) - .addBeforeEachPath( - "-iquote", ObjcCommon.userHeaderSearchPaths(buildConfiguration)) + .addBeforeEachPath("-iquote", ObjcCommon.userHeaderSearchPaths(buildConfiguration)) .addBeforeEachExecPath("-include", compilationArtifacts.getPchFile().asSet()) .addBeforeEachPath("-I", objcProvider.get(INCLUDE)) .addBeforeEachPath("-isystem", objcProvider.get(INCLUDE_SYSTEM)) @@ -480,22 +479,24 @@ public final class CompilationSupport { } // TODO(bazel-team): Remote private headers from inputs once they're added to the provider. - ruleContext.registerAction(ObjcRuleClasses.spawnAppleEnvActionBuilder( - ruleContext, appleConfiguration.getIosCpuPlatform()) - .setMnemonic("ObjcCompile") - .setExecutable(xcrunwrapper(ruleContext)) - .setCommandLine(commandLine.build()) - .addInput(sourceFile) - .addInputs(additionalInputs.build()) - .addOutput(objFile) - .addOutputs(gcnoFiles.build()) - .addOutput(dotdFile) - .addTransitiveInputs(objcProvider.get(HEADER)) - .addTransitiveInputs(objcProvider.get(MODULE_MAP)) - .addInputs(compilationArtifacts.getPrivateHdrs()) - .addTransitiveInputs(objcProvider.get(FRAMEWORK_FILE)) - .addInputs(compilationArtifacts.getPchFile().asSet()) - .build(ruleContext)); + ruleContext.registerAction( + ObjcRuleClasses.spawnAppleEnvActionBuilder( + ruleContext, appleConfiguration.getIosCpuPlatform()) + .setMnemonic("ObjcCompile") + .setExecutable(xcrunwrapper(ruleContext)) + .setCommandLine(commandLine.build()) + .addInput(sourceFile) + .addInputs(additionalInputs.build()) + .addOutput(objFile) + .addOutputs(gcnoFiles.build()) + .addOutput(dotdFile) + .addTransitiveInputs(objcProvider.get(HEADER)) + .addTransitiveInputs(objcProvider.get(MODULE_MAP)) + .addInputs(compilationArtifacts.getPrivateHdrs()) + .addTransitiveInputs(objcProvider.get(STATIC_FRAMEWORK_FILE)) + .addTransitiveInputs(objcProvider.get(DYNAMIC_FRAMEWORK_FILE)) + .addInputs(compilationArtifacts.getPchFile().asSet()) + .build(ruleContext)); } /** @@ -957,7 +958,8 @@ public final class CompilationSupport { .addOutputs(linkmap.asSet()) .addTransitiveInputs(bazelBuiltLibraries) .addTransitiveInputs(objcProvider.get(IMPORTED_LIBRARY)) - .addTransitiveInputs(objcProvider.get(FRAMEWORK_FILE)) + .addTransitiveInputs(objcProvider.get(STATIC_FRAMEWORK_FILE)) + .addTransitiveInputs(objcProvider.get(DYNAMIC_FRAMEWORK_FILE)) .addInputs(ccLibraries) .addInputs(extraLinkInputs) .addInputs(prunedJ2ObjcArchives) @@ -1077,6 +1079,12 @@ public final class CompilationSupport { .add("-objc_abi_version") .add("-Xlinker") .add("2") + // Set the rpath so that at runtime dylibs can be loaded from the bundle root's "Frameworks" + // directory. + .add("-Xlinker") + .add("-rpath") + .add("-Xlinker") + .add("@executable_path/Frameworks") .add("-fobjc-link-runtime") .add(DEFAULT_LINKER_FLAGS) .addBeforeEach("-framework", frameworkNames(objcProvider)) @@ -1108,13 +1116,6 @@ public final class CompilationSupport { commandLine.add("-L").add(AppleToolchain.swiftLibDir(appleConfiguration)); } - if (objcProvider.is(USES_SWIFT) || objcProvider.is(USES_FRAMEWORKS)) { - // Enable loading bundled frameworks. - commandLine - .add("-Xlinker").add("-rpath") - .add("-Xlinker").add("@executable_path/Frameworks"); - } - for (String linkopt : attributes.linkopts()) { commandLine.add("-Wl," + linkopt); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosFramework.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosFramework.java index 610382ecb7..4de6706c1f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosFramework.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosFramework.java @@ -16,11 +16,9 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.devtools.build.lib.rules.objc.ObjcCommon.uniqueContainers; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FLAG; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FILE; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_FRAMEWORKS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MERGE_ZIP; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -123,8 +121,13 @@ public class IosFramework extends ReleaseBundlingTargetFactory { ObjcProvider frameworkProvider = new ObjcProvider.Builder() .add(MERGE_ZIP, ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA)) - .add(FLAG, USES_FRAMEWORKS) - .addAll(FRAMEWORK_FILE, frameworkImports) + // TODO(dmishe): The framework returned by this rule is dynamic, not static. But because + // this rule (incorrectly?) propagates its contents as a bundle (see "IPA" above) we + // cannot declare its files as dynamic framework files because they would then be copied + // into the final IPA, conflicting with the exported bundle. Instead we propagate using + // the static frameworks key which will see the files correctly added to compile and + // linker actions but not added to the final bundle. + .addAll(STATIC_FRAMEWORK_FILE, frameworkImports) .addAll( FRAMEWORK_DIR, uniqueContainers(frameworkImports, ObjcCommon.FRAMEWORK_CONTAINER_TYPE)) 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 f7d478928d..d15148b1e2 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 @@ -24,11 +24,11 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEBUG_SYMBOLS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEBUG_SYMBOLS_PLIST; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FLAG; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_FOR_XCODEGEN; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_CPP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR; @@ -46,6 +46,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SOURCE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STRINGS; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.TOP_LEVEL_MODULE_MAP; @@ -181,9 +182,8 @@ public final class ObjcCommon { ImmutableList.Builder<PathFragment> paths = new ImmutableList.Builder<>(); PathFragment packageFragment = ruleContext.getLabel().getPackageIdentifier().getPathFragment(); - List<PathFragment> rootFragments = ImmutableList.of( - packageFragment, - genfilesFragment.getRelative(packageFragment)); + List<PathFragment> rootFragments = + ImmutableList.of(packageFragment, genfilesFragment.getRelative(packageFragment)); Iterable<PathFragment> relativeIncludes = Iterables.filter(includes(), Predicates.not(PathFragment.IS_ABSOLUTE)); @@ -301,7 +301,8 @@ public final class ObjcCommon { private Iterable<SdkFramework> extraSdkFrameworks = ImmutableList.of(); private Iterable<SdkFramework> extraWeakSdkFrameworks = ImmutableList.of(); private Iterable<String> extraSdkDylibs = ImmutableList.of(); - private Iterable<Artifact> frameworkImports = ImmutableList.of(); + private Iterable<Artifact> staticFrameworkImports = ImmutableList.of(); + private Iterable<Artifact> dynamicFrameworkImports = ImmutableList.of(); private Optional<CompilationArtifacts> compilationArtifacts = Optional.absent(); private Iterable<ObjcProvider> depObjcProviders = ImmutableList.of(); private Iterable<ObjcProvider> directDepObjcProviders = ImmutableList.of(); @@ -337,15 +338,19 @@ public final class ObjcCommon { } public Builder setCompilationAttributes(CompilationAttributes baseCompilationAttributes) { - Preconditions.checkState(!this.compilationAttributes.isPresent(), - "compilationAttributes is already set to: %s", this.compilationAttributes); + Preconditions.checkState( + !this.compilationAttributes.isPresent(), + "compilationAttributes is already set to: %s", + this.compilationAttributes); this.compilationAttributes = Optional.of(baseCompilationAttributes); return this; } public Builder setResourceAttributes(ResourceAttributes baseResourceAttributes) { - Preconditions.checkState(!this.resourceAttributes.isPresent(), - "resourceAttributes is already set to: %s", this.resourceAttributes); + Preconditions.checkState( + !this.resourceAttributes.isPresent(), + "resourceAttributes is already set to: %s", + this.resourceAttributes); this.resourceAttributes = Optional.of(baseResourceAttributes); return this; } @@ -366,14 +371,31 @@ public final class ObjcCommon { return this; } - Builder addFrameworkImports(Iterable<Artifact> frameworkImports) { - this.frameworkImports = Iterables.concat(this.frameworkImports, frameworkImports); + /** + * Adds all given artifacts as members of static frameworks. They must be contained in + * {@code .frameworks} directories and the binary in that framework should be statically linked. + */ + Builder addStaticFrameworkImports(Iterable<Artifact> frameworkImports) { + this.staticFrameworkImports = Iterables.concat(this.staticFrameworkImports, frameworkImports); + return this; + } + + /** + * Adds all given artifacts as members of dynamic frameworks. They must be contained in + * {@code .frameworks} directories and the binary in that framework should be dynamically + * linked. + */ + Builder addDynamicFrameworkImports(Iterable<Artifact> frameworkImports) { + this.dynamicFrameworkImports = + Iterables.concat(this.dynamicFrameworkImports, frameworkImports); return this; } Builder setCompilationArtifacts(CompilationArtifacts compilationArtifacts) { - Preconditions.checkState(!this.compilationArtifacts.isPresent(), - "compilationArtifacts is already set to: %s", this.compilationArtifacts); + Preconditions.checkState( + !this.compilationArtifacts.isPresent(), + "compilationArtifacts is already set to: %s", + this.compilationArtifacts); this.compilationArtifacts = Optional.of(compilationArtifacts); return this; } @@ -397,13 +419,13 @@ public final class ObjcCommon { } addDepObjcProviders(propagatedObjcDeps.build()); this.depCcHeaderProviders = Iterables.concat(this.depCcHeaderProviders, cppDeps.build()); - this.depCcLinkProviders = - Iterables.concat(this.depCcLinkProviders, cppDepLinkParams.build()); + this.depCcLinkProviders = Iterables.concat(this.depCcLinkProviders, cppDepLinkParams.build()); return this; } private <T extends TransitiveInfoProvider> ImmutableList.Builder<T> addAnyProviders( - ImmutableList.Builder<T> listBuilder, TransitiveInfoCollection collection, + ImmutableList.Builder<T> listBuilder, + TransitiveInfoCollection collection, Class<T> providerClass) { if (collection.getProvider(providerClass) != null) { listBuilder.add(collection.getProvider(providerClass)); @@ -425,8 +447,8 @@ public final class ObjcCommon { * dependers on the declaring rule. */ Builder addNonPropagatedDepObjcProviders(Iterable<ObjcProvider> directDepObjcProviders) { - this.directDepObjcProviders = Iterables.concat( - this.directDepObjcProviders, directDepObjcProviders); + this.directDepObjcProviders = + Iterables.concat(this.directDepObjcProviders, directDepObjcProviders); return this; } @@ -519,8 +541,13 @@ public final class ObjcCommon { .addAll(SDK_FRAMEWORK, extraSdkFrameworks) .addAll(WEAK_SDK_FRAMEWORK, extraWeakSdkFrameworks) .addAll(SDK_DYLIB, extraSdkDylibs) - .addAll(FRAMEWORK_FILE, frameworkImports) - .addAll(FRAMEWORK_DIR, uniqueContainers(frameworkImports, FRAMEWORK_CONTAINER_TYPE)) + .addAll(STATIC_FRAMEWORK_FILE, staticFrameworkImports) + .addAll(DYNAMIC_FRAMEWORK_FILE, dynamicFrameworkImports) + .addAll( + FRAMEWORK_DIR, uniqueContainers(staticFrameworkImports, FRAMEWORK_CONTAINER_TYPE)) + .addAll( + FRAMEWORK_DIR, + uniqueContainers(dynamicFrameworkImports, FRAMEWORK_CONTAINER_TYPE)) .addAll(INCLUDE, userHeaderSearchPaths) .addAllForDirectDependents(INCLUDE, directDependencyHeaderSearchPaths) .addAll(DEFINE, defines) @@ -559,7 +586,8 @@ public final class ObjcCommon { for (LinkerInputs.LibraryToLink library : params.getLibraries()) { Artifact artifact = library.getArtifact(); if (LINK_LIBRARY_FILETYPES.matches(artifact.getFilename())) { - objcProvider.add(FORCE_LOAD_FOR_XCODEGEN, + objcProvider.add( + FORCE_LOAD_FOR_XCODEGEN, "$(WORKSPACE_ROOT)/" + artifact.getExecPath().getSafePathString()); } } @@ -567,11 +595,12 @@ public final class ObjcCommon { if (compilationAttributes.isPresent()) { CompilationAttributes attributes = compilationAttributes.get(); - Iterable<PathFragment> sdkIncludes = Iterables.transform( - Interspersing.prependEach( - AppleToolchain.sdkDir() + "/usr/include/", - PathFragment.safePathStrings(attributes.sdkIncludes())), - TO_PATH_FRAGMENT); + Iterable<PathFragment> sdkIncludes = + Iterables.transform( + Interspersing.prependEach( + AppleToolchain.sdkDir() + "/usr/include/", + PathFragment.safePathStrings(attributes.sdkIncludes())), + TO_PATH_FRAGMENT); objcProvider .addAll(HEADER, attributes.hdrs()) .addAll(HEADER, attributes.textualHdrs()) @@ -652,14 +681,17 @@ public final class ObjcCommon { for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) { for (Artifact archive : artifacts.getArchive().asSet()) { objcProvider.add(FORCE_LOAD_LIBRARY, archive); - objcProvider.add(FORCE_LOAD_FOR_XCODEGEN, String.format( - "$(BUILT_PRODUCTS_DIR)/lib%s.a", - XcodeProvider.xcodeTargetName(context.getLabel()))); + objcProvider.add( + FORCE_LOAD_FOR_XCODEGEN, + String.format( + "$(BUILT_PRODUCTS_DIR)/lib%s.a", + XcodeProvider.xcodeTargetName(context.getLabel()))); } } for (Artifact archive : extraImportLibraries) { objcProvider.add(FORCE_LOAD_LIBRARY, archive); - objcProvider.add(FORCE_LOAD_FOR_XCODEGEN, + objcProvider.add( + FORCE_LOAD_FOR_XCODEGEN, "$(WORKSPACE_ROOT)/" + archive.getExecPath().getSafePathString()); } } @@ -671,7 +703,8 @@ public final class ObjcCommon { objcProvider.add(TOP_LEVEL_MODULE_MAP, moduleMap); } - objcProvider.addAll(LINKED_BINARY, linkedBinary.asSet()) + objcProvider + .addAll(LINKED_BINARY, linkedBinary.asSet()) .addAll(LINKMAP_FILE, linkmapFile.asSet()); if (dsymOutputType != null) { @@ -698,7 +731,6 @@ public final class ObjcCommon { ruleContext.getPrerequisiteArtifact("launch_storyboard", Mode.TARGET); return launchStoryboard != null; } - } static final FileType BUNDLE_CONTAINER_TYPE = FileType.of(".bundle"); @@ -711,8 +743,7 @@ public final class ObjcCommon { private final Optional<CompilationArtifacts> compilationArtifacts; private ObjcCommon( - ObjcProvider objcProvider, - Optional<CompilationArtifacts> compilationArtifacts) { + ObjcProvider objcProvider, Optional<CompilationArtifacts> compilationArtifacts) { this.objcProvider = Preconditions.checkNotNull(objcProvider); this.compilationArtifacts = Preconditions.checkNotNull(compilationArtifacts); } @@ -738,9 +769,7 @@ public final class ObjcCommon { } static ImmutableList<PathFragment> userHeaderSearchPaths(BuildConfiguration configuration) { - return ImmutableList.of( - new PathFragment("."), - configuration.getGenfilesFragment()); + return ImmutableList.of(new PathFragment("."), configuration.getGenfilesFragment()); } /** @@ -842,8 +871,11 @@ public final class ObjcCommon { for (Artifact artifact : artifacts) { boolean inContainer = nearestContainerMatching(containerTypes, artifact).isPresent(); if (!inContainer) { - errors.add(String.format(NOT_IN_CONTAINER_ERROR_FORMAT, - artifact.getExecPath(), Iterables.toString(containerTypes))); + errors.add( + String.format( + NOT_IN_CONTAINER_ERROR_FORMAT, + artifact.getExecPath(), + Iterables.toString(containerTypes))); } } return errors; diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java index 86788d96ac..1b86ca0935 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java @@ -24,7 +24,9 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; +import com.google.devtools.build.lib.rules.objc.ObjcCommon.Builder; import com.google.devtools.build.lib.rules.objc.ObjcSdkFrameworks.Attributes; +import com.google.devtools.build.lib.syntax.Type; /** * Implementation for the {@code objc_framework} rule. @@ -34,15 +36,19 @@ public class ObjcFramework implements RuleConfiguredTargetFactory { public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { Attributes sdkFrameworkAttributes = new Attributes(ruleContext); + ObjcCommon.Builder commonBuilder = + new Builder(ruleContext) + .addExtraSdkFrameworks(sdkFrameworkAttributes.sdkFrameworks()) + .addExtraWeakSdkFrameworks(sdkFrameworkAttributes.weakSdkFrameworks()) + .addExtraSdkDylibs(sdkFrameworkAttributes.sdkDylibs()); + ImmutableList<Artifact> frameworkImports = ruleContext.getPrerequisiteArtifacts("framework_imports", Mode.TARGET).list(); - ObjcCommon common = new ObjcCommon.Builder(ruleContext) - .addFrameworkImports( - frameworkImports) - .addExtraSdkFrameworks(sdkFrameworkAttributes.sdkFrameworks()) - .addExtraWeakSdkFrameworks(sdkFrameworkAttributes.weakSdkFrameworks()) - .addExtraSdkDylibs(sdkFrameworkAttributes.sdkDylibs()) - .build(); + if (ruleContext.attributes().get("is_dynamic", Type.BOOLEAN)) { + commonBuilder.addDynamicFrameworkImports(frameworkImports); + } else { + commonBuilder.addStaticFrameworkImports(frameworkImports); + } Iterable<String> containerErrors = ObjcCommon.notInContainerErrors(frameworkImports, ObjcCommon.FRAMEWORK_CONTAINER_TYPE); @@ -52,7 +58,7 @@ public class ObjcFramework implements RuleConfiguredTargetFactory { NestedSet<Artifact> filesToBuild = NestedSetBuilder.emptySet(STABLE_ORDER); return ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild) - .addProvider(ObjcProvider.class, common.getObjcProvider()) + .addProvider(ObjcProvider.class, commonBuilder.build().getObjcProvider()) .build(); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java index a4c68ac4c6..9f264f9d4a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkRule.java @@ -22,6 +22,7 @@ import com.google.devtools.build.lib.analysis.RuleDefinition; import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder; +import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileTypeSet; /** @@ -36,10 +37,16 @@ public class ObjcFrameworkRule implements RuleDefinition { The list of files under a <code>.framework</code> directory which are provided to Objective-C targets that depend on this target. <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ - .add(attr("framework_imports", LABEL_LIST) - .allowedFileTypes(FileTypeSet.ANY_FILE) - .mandatory() - .nonEmpty()) + .add( + attr("framework_imports", LABEL_LIST) + .allowedFileTypes(FileTypeSet.ANY_FILE) + .mandatory() + .nonEmpty()) + /* <!-- #BLAZE_RULE(objc_framework).ATTRIBUTE(is_dynamic) --> + Indicates whether this framework is linked dynamically. If this attribute is set, the + framework will be copied into the final application bundle. + <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ + .add(attr("is_dynamic", Type.BOOLEAN).value(false)) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java index 8705e5728f..b44550036c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java @@ -228,11 +228,19 @@ public final class ObjcProvider extends SkylarkClassObject implements Transitive new Key<>(LINK_ORDER, "framework_dir", PathFragment.class); /** - * Files in {@code .framework} directories that should be included as inputs when compiling and - * linking. + * Files in {@code .framework} directories belonging to a statically linked framework. They should + * be included as inputs when compiling and linking. */ - public static final Key<Artifact> FRAMEWORK_FILE = - new Key<>(STABLE_ORDER, "framework_file", Artifact.class); + public static final Key<Artifact> STATIC_FRAMEWORK_FILE = + new Key<>(STABLE_ORDER, "static_framework_file", Artifact.class); + + /** + * Files in {@code .framework} directories belonging to a dynamically linked framework. They + * should be included as inputs when compiling and linking as well as copied into the final + * application bundle. + */ + public static final Key<Artifact> DYNAMIC_FRAMEWORK_FILE = + new Key<>(STABLE_ORDER, "dynamic_framework_file", Artifact.class); /** * Bundles which should be linked in as a nested bundle to the final application. @@ -322,11 +330,6 @@ public final class ObjcProvider extends SkylarkClassObject implements Transitive USES_SWIFT, /** - * Indicates that the resulting bundle will have embedded frameworks. This affects linking step. - */ - USES_FRAMEWORKS, - - /** * Indicates that watch os 1 extension is present in the bundle. */ HAS_WATCH1_EXTENSION, @@ -357,7 +360,8 @@ public final class ObjcProvider extends SkylarkClassObject implements Transitive XCDATAMODEL, MODULE_MAP, MERGE_ZIP, - FRAMEWORK_FILE, + STATIC_FRAMEWORK_FILE, + DYNAMIC_FRAMEWORK_FILE, DEBUG_SYMBOLS, DEBUG_SYMBOLS_PLIST, BREAKPAD_FILE, diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java index 5115d33229..e3572eb85e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java @@ -488,13 +488,14 @@ public final class ReleaseBundlingSupport { } private String signingCommandLine() { - ImmutableList.Builder<String> dirsToSign = new ImmutableList.Builder<>(); - - // Explicitly sign Swift dylibs. Unfortunately --deep option on codesign doesn't do this - // automatically. // The order here is important. The innermost code must singed first. + ImmutableList.Builder<String> dirsToSign = new ImmutableList.Builder<>(); String bundleDir = ShellUtils.shellEscape(bundling.getBundleDir()); - if (objcProvider.is(USES_SWIFT)) { + + // Explicitly sign the frameworks (raw .dylib files and .framework directories in Frameworks/). + // Unfortunately the --deep option on codesign doesn't do this automatically. + if (objcProvider.is(USES_SWIFT) + || !objcProvider.get(ObjcProvider.DYNAMIC_FRAMEWORK_FILE).isEmpty()) { dirsToSign.add(bundleDir + "/Frameworks/*"); } dirsToSign.add(bundleDir); @@ -686,21 +687,25 @@ public final class ReleaseBundlingSupport { // We want access to #import-able things from our test rig's dependency graph, but we don't // want to link anything since that stuff is shared automatically by way of the // -bundle_loader linker flag. - ObjcProvider partialObjcProvider = new ObjcProvider.Builder() - .addTransitiveAndPropagate(ObjcProvider.HEADER, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.INCLUDE, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.DEFINE, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.SDK_DYLIB, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.SDK_FRAMEWORK, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.SOURCE, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.WEAK_SDK_FRAMEWORK, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.FRAMEWORK_DIR, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.FRAMEWORK_FILE, objcProvider) - .build(); + ObjcProvider partialObjcProvider = + new ObjcProvider.Builder() + .addTransitiveAndPropagate(ObjcProvider.HEADER, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.INCLUDE, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.DEFINE, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.SDK_DYLIB, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.SDK_FRAMEWORK, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.SOURCE, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.WEAK_SDK_FRAMEWORK, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.FRAMEWORK_DIR, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.STATIC_FRAMEWORK_FILE, objcProvider) + .addTransitiveAndPropagate(ObjcProvider.DYNAMIC_FRAMEWORK_FILE, objcProvider) + .build(); // TODO(bazel-team): Handle the FRAMEWORK_DIR key properly. We probably want to add it to // framework search paths, but not actually link it with the -framework flag. - return new XcTestAppProvider(intermediateArtifacts - .combinedArchitectureBinary(), releaseBundling.getIpaArtifact(), partialObjcProvider); + return new XcTestAppProvider( + intermediateArtifacts.combinedArchitectureBinary(), + releaseBundling.getIpaArtifact(), + partialObjcProvider); } /** |