Address embedded bundles without cache access.
PiperOrigin-RevId: 194953059
diff --git a/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl b/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl
index dc83fc9..e8c3192 100644
--- a/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl
+++ b/src/TulsiGenerator/Bazel/tulsi/tulsi_aspects.bzl
@@ -723,11 +723,11 @@
"""Returns Apple bundle info for the given target, None if not a bundle."""
if AppleBundleInfo in target:
apple_bundle = target[AppleBundleInfo]
- bundle_full_name = apple_bundle.bundle_name + apple_bundle.bundle_extension
has_dsym = (apple_common.AppleDebugOutputs in target)
return [struct(
archive_root=apple_bundle.archive_root,
- bundle_full_name=bundle_full_name,
+ bundle_name=apple_bundle.bundle_name,
+ bundle_extension=apple_bundle.bundle_extension,
has_dsym=has_dsym)]
return None
diff --git a/src/TulsiGenerator/Scripts/bazel_build.py b/src/TulsiGenerator/Scripts/bazel_build.py
index 25fcc36..5323278 100755
--- a/src/TulsiGenerator/Scripts/bazel_build.py
+++ b/src/TulsiGenerator/Scripts/bazel_build.py
@@ -1062,15 +1062,90 @@
'installing_embedded_bundles').Start()
for bundle_info in output_data['embedded_bundles']:
- name = bundle_info['bundle_full_name']
+ bundle_name = bundle_info['bundle_name']
+ bundle_extension = bundle_info['bundle_extension']
+ full_name = bundle_name + bundle_extension
+ output_path = os.path.join(self.built_products_dir, full_name)
# TODO(b/68936732): See if copying just the binary (not the whole bundle)
# is enough to make Instruments work.
- source_path = os.path.join(bundle_info['archive_root'], name)
- output_path = os.path.join(self.built_products_dir, name)
- self._RsyncBundle(name, source_path, output_path)
+ if self._IsValidArtifactArchiveRoot(bundle_info['archive_root'],
+ bundle_name):
+ source_path = os.path.join(bundle_info['archive_root'], full_name)
+ self._RsyncBundle(full_name, source_path, output_path)
+ else:
+ # Try to find the embedded bundle within the installed main bundle.
+ bundle_path = self._FindEmbeddedBundleInMain(bundle_name,
+ bundle_extension)
+ if bundle_path:
+ self._RsyncBundle(full_name, bundle_path, output_path)
+ else:
+ _PrintXcodeWarning('Could not find bundle %s in main bundle. ' %
+ (bundle_name + bundle_extension) +
+ 'Device-level Instruments debugging will be '
+ 'disabled for this bundle. Please report a '
+ 'Tulsi bug and attach a full Xcode build log.')
timer.End()
+ # Maps extensions to anticipated subfolders.
+ _EMBEDDED_BUNDLE_PATHS = {
+ '.appex': 'PlugIns',
+ '.framework': 'Frameworks'
+ }
+
+ def _FindEmbeddedBundleInMain(self, bundle_name, bundle_extension):
+ """Retrieves the first embedded bundle found within our main bundle."""
+ main_bundle = os.environ.get('EXECUTABLE_FOLDER_PATH')
+
+ if not main_bundle:
+ return None
+
+ main_bundle_path = os.path.join(self.built_products_dir,
+ main_bundle)
+
+ return self._FindEmbeddedBundle(bundle_name,
+ bundle_extension,
+ main_bundle_path)
+
+ def _FindEmbeddedBundle(self, bundle_name, bundle_extension, bundle_path):
+ """Retrieves the first embedded bundle found within this bundle path."""
+ embedded_subfolder = self._EMBEDDED_BUNDLE_PATHS[bundle_extension]
+
+ if not embedded_subfolder:
+ return None
+
+ projected_bundle_path = os.path.join(bundle_path,
+ embedded_subfolder,
+ bundle_name + bundle_extension)
+
+ if os.path.isdir(projected_bundle_path):
+ return projected_bundle_path
+
+ # For frameworks not in the main app bundle, and possibly other executable
+ # bundle content in the future, we recurse through every .appex in PlugIns
+ # to find those frameworks.
+ #
+ # This won't support frameworks that could potentially have the same name
+ # but are different between the app and extensions, but we intentionally
+ # choose not to handle that case. Xcode build system only supports
+ # uniquely named frameworks, and we shouldn't confuse the dynamic loader
+ # with frameworks that have the same image names but different content.
+ appex_root_path = os.path.join(bundle_path, 'PlugIns')
+ if not os.path.isdir(appex_root_path):
+ return None
+
+ # Find each directory within appex_root_path and attempt to find a bundle.
+ # If one can't be found, return None.
+ appex_dirs = os.listdir(appex_root_path)
+ for appex_dir in appex_dirs:
+ appex_path = os.path.join(appex_root_path, appex_dir)
+ path = self._FindEmbeddedBundle(bundle_name,
+ bundle_extension,
+ appex_path)
+ if path:
+ return path
+ return None
+
def _StartInstallingGeneratedHeaders(self, outputs):
"""Invokes install_genfiles.py to install generated Bazel files."""
@@ -1262,7 +1337,9 @@
# app/extension/df bundles. Currently hinges on implementation of the
# build rules.
dsym_path = os.path.dirname(bundle_info['archive_root'])
- dsym_filename = '%s.dSYM' % bundle_info['bundle_full_name']
+ bundle_full_name = (bundle_info['bundle_name'] +
+ bundle_info['bundle_extension'])
+ dsym_filename = '%s.dSYM' % bundle_full_name
child_dsyms.add((dsym_path, dsym_filename))
dsym_to_process.update(child_dsyms)