diff options
author | 2015-06-18 19:02:13 +0000 | |
---|---|---|
committer | 2015-06-19 11:04:32 +0000 | |
commit | 45dae50094d353c1a660d7d6cf6414a1ae8c1ef1 (patch) | |
tree | 45c2714cc33a6c5b82126b61d86769a21bf4c327 /src/main | |
parent | dd6ca09add101489624a70c9de697f3071f05108 (diff) |
Xcode project file support for structured resources defined in attribute "structured_resources" on ObjC rules.
--
MOS_MIGRATED_REVID=96332700
Diffstat (limited to 'src/main')
4 files changed, 74 insertions, 29 deletions
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 3b317ab8dd..f76964bc50 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 @@ -28,6 +28,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FI 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.GCNO; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; @@ -428,10 +429,14 @@ public final class ObjcCommon { .addAll(GENERAL_RESOURCE_FILE, attributes.resources()) .addAll(GENERAL_RESOURCE_FILE, attributes.strings()) .addAll(GENERAL_RESOURCE_FILE, attributes.xibs()) + .addAll( + GENERAL_RESOURCE_DIR, xcodeStructuredResourceDirs(attributes.structuredResources())) .addAll(BUNDLE_FILE, BundleableFile.flattenedRawResourceFiles(attributes.resources())) - .addAll(BUNDLE_FILE, + .addAll( + BUNDLE_FILE, BundleableFile.structuredRawResourceFiles(attributes.structuredResources())) - .addAll(XCASSETS_DIR, + .addAll( + XCASSETS_DIR, uniqueContainers(attributes.assetCatalogs(), ASSET_CATALOG_CONTAINER_TYPE)) .addAll(ASSET_CATALOG, attributes.assetCatalogs()) .addAll(XCDATAMODEL, attributes.datamodels()) @@ -594,6 +599,29 @@ public final class ObjcCommon { } /** + * Returns the Xcode structured resource directory paths. + * + * <p>For a checked-in source artifact "//a/b/res/sub_dir/d" included by objc rule "//a/b:c", + * "a/b/res" will be returned. For a generated source artifact "res/sub_dir/d" owned by genrule + * "//a/b:c", "bazel-out/.../genfiles/a/b/res" will be returned. + * + * <p>When XCode sees a included resource directory of "a/b/res", the entire directory structure + * up to "res" will be copied into the app bundle. + */ + private static Iterable<PathFragment> xcodeStructuredResourceDirs(Iterable<Artifact> artifacts) { + ImmutableSet.Builder<PathFragment> containers = new ImmutableSet.Builder<>(); + for (Artifact artifact : artifacts) { + PathFragment ownerRuleDirectory = artifact.getArtifactOwner().getLabel().getPackageFragment(); + String containerName = + artifact.getRootRelativePath().relativeTo(ownerRuleDirectory).getSegment(0); + PathFragment rootExecPath = artifact.getRoot().getExecPath(); + containers.add(rootExecPath.getRelative(ownerRuleDirectory.getRelative(containerName))); + } + + return containers.build(); + } + + /** * Similar to {@link #nearestContainerMatching(FileType, Artifact)}, but returns the container * closest to the root that matches the given type. */ 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 92fce30111..1737c0de00 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 @@ -115,6 +115,13 @@ public final class ObjcProvider implements TransitiveInfoProvider { public static final Key<Artifact> GENERAL_RESOURCE_FILE = new Key<>(STABLE_ORDER); /** + * Resource directories added to {@link TargetControl#getGeneralResourceFileList()} when running + * Xcodegen. When copying files inside resource directories to the app bundle, XCode will preserve + * the directory structures of the copied files. + */ + public static final Key<PathFragment> GENERAL_RESOURCE_DIR = new Key<>(STABLE_ORDER); + + /** * Exec paths of {@code .bundle} directories corresponding to imported bundles to link. * These are passed to Xcodegen. */ 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 3c4bca055a..5207f1ecf0 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 @@ -398,6 +398,10 @@ public class ObjcRuleClasses { the same structure passed to this argument, so <code>["res/foo.png"]</code> will end up in <code>Payload/foo.app/res/foo.png</code>. + <p>Note that in the generated XCode project file, all files in the top directory of + the specified files will be included in the Xcode-generated app bundle. So + specifying <code>["res/foo.png"]</code> will lead to the inclusion of all files in + directory <code>res</code>. <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/ .add(attr("structured_resources", LABEL_LIST) .legacyAllowAnyFileType() diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java index 30176c75d4..ec39f401c9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java @@ -18,6 +18,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_IMPOR import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_FOR_XCODEGEN; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB; @@ -527,33 +528,38 @@ public final class XcodeProvider implements TransitiveInfoProvider { .build(); // TODO(bazel-team): Add provisioning profile information when Xcodegen supports it. - TargetControl.Builder targetControl = TargetControl.newBuilder() - .setName(label.getName()) - .setLabel(xcodeTargetName(label)) - .setProductType(productType.getIdentifier()) - .addAllImportedLibrary(Artifact.toExecPaths(objcProvider.get(IMPORTED_LIBRARY))) - .addAllUserHeaderSearchPath(userHeaderSearchPaths) - .addAllHeaderSearchPath(headerSearchPaths) - .addAllSupportFile(Artifact.toExecPaths(headers)) - .addAllCopt(compilationModeCopts) - .addAllCopt(IosSdkCommands.DEFAULT_COMPILER_FLAGS) - .addAllCopt(Interspersing.prependEach("-D", objcProvider.get(DEFINE))) - .addAllCopt(copts) - .addAllLinkopt( - Interspersing.beforeEach("-force_load", objcProvider.get(FORCE_LOAD_FOR_XCODEGEN))) - .addAllLinkopt(IosSdkCommands.DEFAULT_LINKER_FLAGS) - .addAllLinkopt(Interspersing.beforeEach( - "-weak_framework", SdkFramework.names(objcProvider.get(WEAK_SDK_FRAMEWORK)))) - .addAllBuildSetting(xcodeprojBuildSettings) - .addAllBuildSetting(IosSdkCommands.defaultWarningsForXcode()) - .addAllSdkFramework(SdkFramework.names(objcProvider.get(SDK_FRAMEWORK))) - .addAllFramework(PathFragment.safePathStrings(objcProvider.get(FRAMEWORK_DIR))) - .addAllXcassetsDir(PathFragment.safePathStrings(objcProvider.get(XCASSETS_DIR))) - .addAllXcdatamodel(PathFragment.safePathStrings(datamodelDirs)) - .addAllBundleImport(PathFragment.safePathStrings(objcProvider.get(BUNDLE_IMPORT_DIR))) - .addAllSdkDylib(objcProvider.get(SDK_DYLIB)) - .addAllGeneralResourceFile(Artifact.toExecPaths(objcProvider.get(GENERAL_RESOURCE_FILE))) - .addSupportFile(buildFilePath); + TargetControl.Builder targetControl = + TargetControl.newBuilder() + .setName(label.getName()) + .setLabel(xcodeTargetName(label)) + .setProductType(productType.getIdentifier()) + .addAllImportedLibrary(Artifact.toExecPaths(objcProvider.get(IMPORTED_LIBRARY))) + .addAllUserHeaderSearchPath(userHeaderSearchPaths) + .addAllHeaderSearchPath(headerSearchPaths) + .addAllSupportFile(Artifact.toExecPaths(headers)) + .addAllCopt(compilationModeCopts) + .addAllCopt(IosSdkCommands.DEFAULT_COMPILER_FLAGS) + .addAllCopt(Interspersing.prependEach("-D", objcProvider.get(DEFINE))) + .addAllCopt(copts) + .addAllLinkopt( + Interspersing.beforeEach("-force_load", objcProvider.get(FORCE_LOAD_FOR_XCODEGEN))) + .addAllLinkopt(IosSdkCommands.DEFAULT_LINKER_FLAGS) + .addAllLinkopt( + Interspersing.beforeEach( + "-weak_framework", SdkFramework.names(objcProvider.get(WEAK_SDK_FRAMEWORK)))) + .addAllBuildSetting(xcodeprojBuildSettings) + .addAllBuildSetting(IosSdkCommands.defaultWarningsForXcode()) + .addAllSdkFramework(SdkFramework.names(objcProvider.get(SDK_FRAMEWORK))) + .addAllFramework(PathFragment.safePathStrings(objcProvider.get(FRAMEWORK_DIR))) + .addAllXcassetsDir(PathFragment.safePathStrings(objcProvider.get(XCASSETS_DIR))) + .addAllXcdatamodel(PathFragment.safePathStrings(datamodelDirs)) + .addAllBundleImport(PathFragment.safePathStrings(objcProvider.get(BUNDLE_IMPORT_DIR))) + .addAllSdkDylib(objcProvider.get(SDK_DYLIB)) + .addAllGeneralResourceFile( + Artifact.toExecPaths(objcProvider.get(GENERAL_RESOURCE_FILE))) + .addAllGeneralResourceFile( + PathFragment.safePathStrings(objcProvider.get(GENERAL_RESOURCE_DIR))) + .addSupportFile(buildFilePath); if (CAN_LINK_PRODUCT_TYPES.contains(productType)) { for (XcodeProvider dependency : propagatedDependencies) { |