aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/XcodeProvider.java60
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) {