Clean up macOS framework creation scripts (flutter/engine#54658)
This refactors `create_fat_macos_framework`, `_regenerate_symlinks` and `_set_framework_permissions` to be more generic and not hardcode "FlutterMacOS" as a framework name. Further, it reuses several utility functions from the iOS code in `sky_utils` to improve readability and eliminate duplication. This is refactoring prior to embedding dSYMs in FlutterMacOS.xcframework in a followup patch. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
parent
950352ab04
commit
d18ba04282
@ -47,12 +47,12 @@ def main():
|
|||||||
print('Cannot find macOS x64 Framework at %s' % x64_framework)
|
print('Cannot find macOS x64 Framework at %s' % x64_framework)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
arm64_dylib = os.path.join(arm64_framework, 'FlutterMacOS')
|
arm64_dylib = sky_utils.get_mac_framework_dylib_path(arm64_framework)
|
||||||
if not os.path.isfile(arm64_dylib):
|
if not os.path.isfile(arm64_dylib):
|
||||||
print('Cannot find macOS arm64 dylib at %s' % arm64_dylib)
|
print('Cannot find macOS arm64 dylib at %s' % arm64_dylib)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
x64_dylib = os.path.join(x64_framework, 'FlutterMacOS')
|
x64_dylib = sky_utils.get_mac_framework_dylib_path(x64_framework)
|
||||||
if not os.path.isfile(x64_dylib):
|
if not os.path.isfile(x64_dylib):
|
||||||
print('Cannot find macOS x64 dylib at %s' % x64_dylib)
|
print('Cannot find macOS x64 dylib at %s' % x64_dylib)
|
||||||
return 1
|
return 1
|
||||||
@ -71,15 +71,16 @@ def main():
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def process_framework(dst, args, fat_framework):
|
def process_framework(dst, args, framework_path):
|
||||||
fat_framework_binary = os.path.join(fat_framework, 'Versions', 'A', 'FlutterMacOS')
|
framework_binary = sky_utils.get_mac_framework_dylib_path(framework_path)
|
||||||
|
|
||||||
if args.dsym:
|
if args.dsym:
|
||||||
dsym_out = os.path.splitext(fat_framework)[0] + '.dSYM'
|
dsym_out = os.path.join(dst, 'FlutterMacOS.dSYM')
|
||||||
sky_utils.extract_dsym(fat_framework_binary, dsym_out)
|
sky_utils.extract_dsym(framework_binary, dsym_out)
|
||||||
if args.zip:
|
if args.zip:
|
||||||
dsym_dst = os.path.join(dst, 'FlutterMacOS.dSYM')
|
dsym_dst = os.path.join(dst, 'FlutterMacOS.dSYM')
|
||||||
sky_utils.create_zip(dsym_dst, 'FlutterMacOS.dSYM.zip', ['.'])
|
sky_utils.create_zip(dsym_dst, 'FlutterMacOS.dSYM.zip', ['.'])
|
||||||
# Double zip to make it consistent with legacy artifacts.
|
# Create a zip of just the contents of the dSYM, then create a zip of that zip.
|
||||||
# TODO(fujino): remove this once https://github.com/flutter/flutter/issues/125067 is resolved
|
# TODO(fujino): remove this once https://github.com/flutter/flutter/issues/125067 is resolved
|
||||||
sky_utils.create_zip(dsym_dst, 'FlutterMacOS.dSYM_.zip', ['FlutterMacOS.dSYM.zip'])
|
sky_utils.create_zip(dsym_dst, 'FlutterMacOS.dSYM_.zip', ['FlutterMacOS.dSYM.zip'])
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ def process_framework(dst, args, fat_framework):
|
|||||||
|
|
||||||
if args.strip:
|
if args.strip:
|
||||||
unstripped_out = os.path.join(dst, 'FlutterMacOS.unstripped')
|
unstripped_out = os.path.join(dst, 'FlutterMacOS.unstripped')
|
||||||
sky_utils.strip_binary(fat_framework_binary, unstripped_out)
|
sky_utils.strip_binary(framework_binary, unstripped_out)
|
||||||
|
|
||||||
|
|
||||||
def zip_framework(dst):
|
def zip_framework(dst):
|
||||||
|
@ -119,36 +119,43 @@ def copy_tree(source_path, destination_path, symlinks=False):
|
|||||||
|
|
||||||
|
|
||||||
def create_fat_macos_framework(fat_framework, arm64_framework, x64_framework):
|
def create_fat_macos_framework(fat_framework, arm64_framework, x64_framework):
|
||||||
|
"""Creates a fat framework from two arm64 and x64 frameworks."""
|
||||||
|
# Clone the arm64 framework bundle as a starting point.
|
||||||
copy_tree(arm64_framework, fat_framework, symlinks=True)
|
copy_tree(arm64_framework, fat_framework, symlinks=True)
|
||||||
_regenerate_symlinks(fat_framework)
|
_regenerate_symlinks(fat_framework)
|
||||||
|
lipo([get_mac_framework_dylib_path(arm64_framework),
|
||||||
fat_framework_binary = os.path.join(fat_framework, 'Versions', 'A', 'FlutterMacOS')
|
get_mac_framework_dylib_path(x64_framework)], get_mac_framework_dylib_path(fat_framework))
|
||||||
|
|
||||||
# Create the arm64/x64 fat framework.
|
|
||||||
arm64_dylib = os.path.join(arm64_framework, 'FlutterMacOS')
|
|
||||||
x64_dylib = os.path.join(x64_framework, 'FlutterMacOS')
|
|
||||||
lipo([arm64_dylib, x64_dylib], fat_framework_binary)
|
|
||||||
_set_framework_permissions(fat_framework)
|
_set_framework_permissions(fat_framework)
|
||||||
|
|
||||||
|
|
||||||
def _regenerate_symlinks(framework_dir):
|
def _regenerate_symlinks(framework_dir):
|
||||||
"""Regenerates the symlinks structure.
|
"""Regenerates the framework symlink structure.
|
||||||
|
|
||||||
Recipes V2 upload artifacts in CAS before integration and CAS follows symlinks.
|
When building on the bots, the framework is produced in one shard, uploaded
|
||||||
This logic regenerates the symlinks in the expected structure.
|
to LUCI's content-addressable storage cache (CAS), then pulled down in
|
||||||
|
another shard. When that happens, symlinks are dereferenced, resulting a
|
||||||
|
corrupted framework. This regenerates the expected symlink farm.
|
||||||
"""
|
"""
|
||||||
if os.path.islink(os.path.join(framework_dir, 'FlutterMacOS')):
|
# If the dylib is symlinked, assume symlinks are all fine and bail out.
|
||||||
|
# The shutil.rmtree calls below only work on directories, and fail on symlinks.
|
||||||
|
framework_name = get_framework_name(framework_dir)
|
||||||
|
if os.path.islink(os.path.join(framework_dir, framework_name)):
|
||||||
return
|
return
|
||||||
os.remove(os.path.join(framework_dir, 'FlutterMacOS'))
|
|
||||||
|
# Delete any existing files/directories.
|
||||||
|
os.remove(os.path.join(framework_dir, framework_name))
|
||||||
shutil.rmtree(os.path.join(framework_dir, 'Headers'), True)
|
shutil.rmtree(os.path.join(framework_dir, 'Headers'), True)
|
||||||
shutil.rmtree(os.path.join(framework_dir, 'Modules'), True)
|
shutil.rmtree(os.path.join(framework_dir, 'Modules'), True)
|
||||||
shutil.rmtree(os.path.join(framework_dir, 'Resources'), True)
|
shutil.rmtree(os.path.join(framework_dir, 'Resources'), True)
|
||||||
current_version_path = os.path.join(framework_dir, 'Versions', 'Current')
|
current_version_path = os.path.join(framework_dir, 'Versions', 'Current')
|
||||||
shutil.rmtree(current_version_path, True)
|
shutil.rmtree(current_version_path, True)
|
||||||
|
|
||||||
|
# Recreate the expected framework symlinks.
|
||||||
os.symlink('A', current_version_path)
|
os.symlink('A', current_version_path)
|
||||||
|
|
||||||
os.symlink(
|
os.symlink(
|
||||||
os.path.join('Versions', 'Current', 'FlutterMacOS'),
|
os.path.join('Versions', 'Current', framework_name),
|
||||||
os.path.join(framework_dir, 'FlutterMacOS')
|
os.path.join(framework_dir, framework_name)
|
||||||
)
|
)
|
||||||
os.symlink(os.path.join('Versions', 'Current', 'Headers'), os.path.join(framework_dir, 'Headers'))
|
os.symlink(os.path.join('Versions', 'Current', 'Headers'), os.path.join(framework_dir, 'Headers'))
|
||||||
os.symlink(os.path.join('Versions', 'Current', 'Modules'), os.path.join(framework_dir, 'Modules'))
|
os.symlink(os.path.join('Versions', 'Current', 'Modules'), os.path.join(framework_dir, 'Modules'))
|
||||||
@ -158,6 +165,7 @@ def _regenerate_symlinks(framework_dir):
|
|||||||
|
|
||||||
|
|
||||||
def _set_framework_permissions(framework_dir):
|
def _set_framework_permissions(framework_dir):
|
||||||
|
"""Sets framework contents to be world readable, and world executable if user-executable."""
|
||||||
# Make the framework readable and executable: u=rwx,go=rx.
|
# Make the framework readable and executable: u=rwx,go=rx.
|
||||||
subprocess.check_call(['chmod', '755', framework_dir])
|
subprocess.check_call(['chmod', '755', framework_dir])
|
||||||
|
|
||||||
@ -190,6 +198,16 @@ def _dsymutil_path():
|
|||||||
return buildroot_relative_path(dsymutil_path)
|
return buildroot_relative_path(dsymutil_path)
|
||||||
|
|
||||||
|
|
||||||
|
def get_framework_name(framework_dir):
|
||||||
|
"""Returns Foo given /path/to/Foo.framework."""
|
||||||
|
return os.path.splitext(os.path.basename(framework_dir))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_mac_framework_dylib_path(framework_dir):
|
||||||
|
"""Returns /path/to/Foo.framework/Versions/A/Foo given /path/to/Foo.framework."""
|
||||||
|
return os.path.join(framework_dir, 'Versions', 'A', get_framework_name(framework_dir))
|
||||||
|
|
||||||
|
|
||||||
def extract_dsym(binary_path, dsym_out_path):
|
def extract_dsym(binary_path, dsym_out_path):
|
||||||
"""Extracts a dSYM bundle from the specified Mach-O binary."""
|
"""Extracts a dSYM bundle from the specified Mach-O binary."""
|
||||||
arch_dir = 'mac-arm64' if platform.processor() == 'arm' else 'mac-x64'
|
arch_dir = 'mac-arm64' if platform.processor() == 'arm' else 'mac-x64'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user