Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 10 additions & 66 deletions sky/tools/create_macos_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# found in the LICENSE file.

import argparse
import subprocess
import shutil
import sys
import os
Expand Down Expand Up @@ -38,57 +37,32 @@ def main():
if os.path.isabs(args.x64_out_dir) else sky_utils.buildroot_relative_path(args.x64_out_dir)
)

fat_framework_bundle = os.path.join(dst, 'FlutterMacOS.framework')
arm64_framework = os.path.join(arm64_out_dir, 'FlutterMacOS.framework')
x64_framework = os.path.join(x64_out_dir, 'FlutterMacOS.framework')

arm64_dylib = os.path.join(arm64_framework, 'FlutterMacOS')
x64_dylib = os.path.join(x64_framework, 'FlutterMacOS')

if not os.path.isdir(arm64_framework):
print('Cannot find macOS arm64 Framework at %s' % arm64_framework)
return 1

x64_framework = os.path.join(x64_out_dir, 'FlutterMacOS.framework')
if not os.path.isdir(x64_framework):
print('Cannot find macOS x64 Framework at %s' % x64_framework)
return 1

arm64_dylib = os.path.join(arm64_framework, 'FlutterMacOS')
if not os.path.isfile(arm64_dylib):
print('Cannot find macOS arm64 dylib at %s' % arm64_dylib)
return 1

x64_dylib = os.path.join(x64_framework, 'FlutterMacOS')
if not os.path.isfile(x64_dylib):
print('Cannot find macOS x64 dylib at %s' % x64_dylib)
return 1

sky_utils.copy_tree(arm64_framework, fat_framework_bundle, symlinks=True)

regenerate_symlinks(fat_framework_bundle)

fat_framework_binary = os.path.join(fat_framework_bundle, 'Versions', 'A', 'FlutterMacOS')

# Create the arm64/x64 fat framework.
sky_utils.lipo([arm64_dylib, x64_dylib], fat_framework_binary)

# Make the framework readable and executable: u=rwx,go=rx.
subprocess.check_call(['chmod', '755', fat_framework_bundle])

# Add group and other readability to all files.
versions_path = os.path.join(fat_framework_bundle, 'Versions')
subprocess.check_call(['chmod', '-R', 'og+r', versions_path])
# Find all the files below the target dir with owner execute permission
find_subprocess = subprocess.Popen(['find', versions_path, '-perm', '-100', '-print0'],
stdout=subprocess.PIPE)
# Add execute permission for other and group for all files that had it for owner.
xargs_subprocess = subprocess.Popen(['xargs', '-0', 'chmod', 'og+x'],
stdin=find_subprocess.stdout)
find_subprocess.wait()
xargs_subprocess.wait()

process_framework(dst, args, fat_framework_bundle, fat_framework_binary)
fat_framework = os.path.join(dst, 'FlutterMacOS.framework')
sky_utils.create_fat_macos_framework(fat_framework, arm64_framework, x64_framework)
process_framework(dst, args, fat_framework)

# Create XCFramework from the arm64 and x64 fat framework.
xcframeworks = [fat_framework_bundle]
xcframeworks = [fat_framework]
create_xcframework(location=dst, name='FlutterMacOS', frameworks=xcframeworks)

if args.zip:
Expand All @@ -97,40 +71,10 @@ def main():
return 0


def regenerate_symlinks(fat_framework_bundle):
"""Regenerates the symlinks structure.

Recipes V2 upload artifacts in CAS before integration and CAS follows symlinks.
This logic regenerates the symlinks in the expected structure.
"""
if os.path.islink(os.path.join(fat_framework_bundle, 'FlutterMacOS')):
return
os.remove(os.path.join(fat_framework_bundle, 'FlutterMacOS'))
shutil.rmtree(os.path.join(fat_framework_bundle, 'Headers'), True)
shutil.rmtree(os.path.join(fat_framework_bundle, 'Modules'), True)
shutil.rmtree(os.path.join(fat_framework_bundle, 'Resources'), True)
current_version_path = os.path.join(fat_framework_bundle, 'Versions', 'Current')
shutil.rmtree(current_version_path, True)
os.symlink('A', current_version_path)
os.symlink(
os.path.join('Versions', 'Current', 'FlutterMacOS'),
os.path.join(fat_framework_bundle, 'FlutterMacOS')
)
os.symlink(
os.path.join('Versions', 'Current', 'Headers'), os.path.join(fat_framework_bundle, 'Headers')
)
os.symlink(
os.path.join('Versions', 'Current', 'Modules'), os.path.join(fat_framework_bundle, 'Modules')
)
os.symlink(
os.path.join('Versions', 'Current', 'Resources'),
os.path.join(fat_framework_bundle, 'Resources')
)


def process_framework(dst, args, fat_framework_bundle, fat_framework_binary):
def process_framework(dst, args, fat_framework):
fat_framework_binary = os.path.join(fat_framework, 'Versions', 'A', 'FlutterMacOS')
if args.dsym:
dsym_out = os.path.splitext(fat_framework_bundle)[0] + '.dSYM'
dsym_out = os.path.splitext(fat_framework)[0] + '.dSYM'
sky_utils.extract_dsym(fat_framework_binary, dsym_out)
if args.zip:
dsym_dst = os.path.join(dst, 'FlutterMacOS.dSYM')
Expand Down
56 changes: 56 additions & 0 deletions sky/tools/sky_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,62 @@ def copy_tree(source_path, destination_path, symlinks=False):
shutil.copytree(source_path, destination_path, symlinks=symlinks)


def create_fat_macos_framework(fat_framework, arm64_framework, x64_framework):
copy_tree(arm64_framework, fat_framework, symlinks=True)
_regenerate_symlinks(fat_framework)

fat_framework_binary = os.path.join(fat_framework, 'Versions', 'A', 'FlutterMacOS')

# 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)


def _regenerate_symlinks(framework_dir):
"""Regenerates the symlinks structure.

Recipes V2 upload artifacts in CAS before integration and CAS follows symlinks.
This logic regenerates the symlinks in the expected structure.
"""
if os.path.islink(os.path.join(framework_dir, 'FlutterMacOS')):
return
os.remove(os.path.join(framework_dir, 'FlutterMacOS'))
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, 'Resources'), True)
current_version_path = os.path.join(framework_dir, 'Versions', 'Current')
shutil.rmtree(current_version_path, True)
os.symlink('A', current_version_path)
os.symlink(
os.path.join('Versions', 'Current', 'FlutterMacOS'),
os.path.join(framework_dir, 'FlutterMacOS')
)
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', 'Resources'), os.path.join(framework_dir, 'Resources')
)


def _set_framework_permissions(framework_dir):
# Make the framework readable and executable: u=rwx,go=rx.
subprocess.check_call(['chmod', '755', framework_dir])

# Add group and other readability to all files.
versions_path = os.path.join(framework_dir, 'Versions')
subprocess.check_call(['chmod', '-R', 'og+r', versions_path])
# Find all the files below the target dir with owner execute permission
find_subprocess = subprocess.Popen(['find', versions_path, '-perm', '-100', '-print0'],
stdout=subprocess.PIPE)
# Add execute permission for other and group for all files that had it for owner.
xargs_subprocess = subprocess.Popen(['xargs', '-0', 'chmod', 'og+x'],
stdin=find_subprocess.stdout)
find_subprocess.wait()
xargs_subprocess.wait()


def create_zip(cwd, zip_filename, paths):
"""Creates a zip archive in cwd, containing a set of cwd-relative files.

Expand Down