|  | #!/usr/bin/env python3 | 
|  | # | 
|  | # Copyright 2013 The Flutter Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | import argparse | 
|  | import platform | 
|  | import subprocess | 
|  | import shutil | 
|  | import sys | 
|  | import os | 
|  |  | 
|  | buildroot_dir = os.path.abspath( | 
|  | os.path.join(os.path.realpath(__file__), '..', '..', '..', '..') | 
|  | ) | 
|  |  | 
|  | ARCH_SUBPATH = 'mac-arm64' if platform.processor() == 'arm' else 'mac-x64' | 
|  | DSYMUTIL = os.path.join( | 
|  | os.path.dirname(__file__), '..', '..', '..', 'buildtools', ARCH_SUBPATH, | 
|  | 'clang', 'bin', 'dsymutil' | 
|  | ) | 
|  |  | 
|  | out_dir = os.path.join(buildroot_dir, 'out') | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | parser = argparse.ArgumentParser( | 
|  | description='Creates FlutterEmbedder.framework for macOS' | 
|  | ) | 
|  |  | 
|  | parser.add_argument('--dst', type=str, required=True) | 
|  | parser.add_argument('--arm64-out-dir', type=str, required=True) | 
|  | parser.add_argument('--x64-out-dir', type=str, required=True) | 
|  | parser.add_argument('--strip', action='store_true', default=False) | 
|  | parser.add_argument('--dsym', action='store_true', default=False) | 
|  | # TODO(godofredoc): Remove after recipes v2 have landed. | 
|  | parser.add_argument('--zip', action='store_true', default=False) | 
|  |  | 
|  | args = parser.parse_args() | 
|  |  | 
|  | dst = ( | 
|  | args.dst | 
|  | if os.path.isabs(args.dst) else os.path.join(buildroot_dir, args.dst) | 
|  | ) | 
|  | arm64_out_dir = ( | 
|  | args.arm64_out_dir if os.path.isabs(args.arm64_out_dir) else | 
|  | os.path.join(buildroot_dir, args.arm64_out_dir) | 
|  | ) | 
|  | x64_out_dir = ( | 
|  | args.x64_out_dir if os.path.isabs(args.x64_out_dir) else | 
|  | os.path.join(buildroot_dir, args.x64_out_dir) | 
|  | ) | 
|  |  | 
|  | fat_framework = os.path.join(dst, 'FlutterEmbedder.framework') | 
|  | arm64_framework = os.path.join(arm64_out_dir, 'FlutterEmbedder.framework') | 
|  | x64_framework = os.path.join(x64_out_dir, 'FlutterEmbedder.framework') | 
|  |  | 
|  | arm64_dylib = os.path.join(arm64_framework, 'FlutterEmbedder') | 
|  | x64_dylib = os.path.join(x64_framework, 'FlutterEmbedder') | 
|  |  | 
|  | if not os.path.isdir(arm64_framework): | 
|  | print('Cannot find macOS arm64 Framework at %s' % arm64_framework) | 
|  | return 1 | 
|  |  | 
|  | if not os.path.isdir(x64_framework): | 
|  | print('Cannot find macOS x64 Framework at %s' % x64_framework) | 
|  | return 1 | 
|  |  | 
|  | if not os.path.isfile(arm64_dylib): | 
|  | print('Cannot find macOS arm64 dylib at %s' % arm64_dylib) | 
|  | return 1 | 
|  |  | 
|  | if not os.path.isfile(x64_dylib): | 
|  | print('Cannot find macOS x64 dylib at %s' % x64_dylib) | 
|  | return 1 | 
|  |  | 
|  | if not os.path.isfile(DSYMUTIL): | 
|  | print('Cannot find dsymutil at %s' % DSYMUTIL) | 
|  | return 1 | 
|  |  | 
|  | shutil.rmtree(fat_framework, True) | 
|  | shutil.copytree(arm64_framework, fat_framework, symlinks=True) | 
|  | regenerate_symlinks(fat_framework) | 
|  |  | 
|  | fat_framework_binary = os.path.join( | 
|  | fat_framework, 'Versions', 'A', 'FlutterEmbedder' | 
|  | ) | 
|  |  | 
|  | # Create the arm64/x64 fat framework. | 
|  | subprocess.check_call([ | 
|  | 'lipo', arm64_dylib, x64_dylib, '-create', '-output', fat_framework_binary | 
|  | ]) | 
|  | process_framework(dst, args, fat_framework, fat_framework_binary) | 
|  |  | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | def regenerate_symlinks(fat_framework): | 
|  | """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, 'FlutterEmbedder')): | 
|  | return | 
|  | os.remove(os.path.join(fat_framework, 'FlutterEmbedder')) | 
|  | shutil.rmtree(os.path.join(fat_framework, 'Headers'), True) | 
|  | shutil.rmtree(os.path.join(fat_framework, 'Modules'), True) | 
|  | shutil.rmtree(os.path.join(fat_framework, 'Resources'), True) | 
|  | current_version_path = os.path.join(fat_framework, 'Versions', 'Current') | 
|  | shutil.rmtree(current_version_path, True) | 
|  | os.symlink('A', current_version_path) | 
|  | os.symlink( | 
|  | os.path.join('Versions', 'Current', 'FlutterEmbedder'), | 
|  | os.path.join(fat_framework, 'FlutterEmbedder') | 
|  | ) | 
|  | os.symlink( | 
|  | os.path.join('Versions', 'Current', 'Headers'), | 
|  | os.path.join(fat_framework, 'Headers') | 
|  | ) | 
|  | os.symlink( | 
|  | os.path.join('Versions', 'Current', 'Modules'), | 
|  | os.path.join(fat_framework, 'Modules') | 
|  | ) | 
|  | os.symlink( | 
|  | os.path.join('Versions', 'Current', 'Resources'), | 
|  | os.path.join(fat_framework, 'Resources') | 
|  | ) | 
|  |  | 
|  |  | 
|  | def process_framework(dst, args, fat_framework, fat_framework_binary): | 
|  | if args.dsym: | 
|  | dsym_out = os.path.splitext(fat_framework)[0] + '.dSYM' | 
|  | subprocess.check_call([DSYMUTIL, '-o', dsym_out, fat_framework_binary]) | 
|  | if args.zip: | 
|  | dsym_dst = os.path.join(dst, 'FlutterEmbedder.dSYM') | 
|  | subprocess.check_call([ | 
|  | 'zip', '-r', '-y', 'FlutterEmbedder.dSYM.zip', '.' | 
|  | ], | 
|  | cwd=dsym_dst) | 
|  | dsym_final_src_path = os.path.join(dsym_dst, 'FlutterEmbedder.dSYM.zip') | 
|  | dsym_final_dst_path = os.path.join(dst, 'FlutterEmbedder.dSYM.zip') | 
|  | shutil.move(dsym_final_src_path, dsym_final_dst_path) | 
|  |  | 
|  | if args.strip: | 
|  | # copy unstripped | 
|  | unstripped_out = os.path.join(dst, 'FlutterEmbedder.unstripped') | 
|  | shutil.copyfile(fat_framework_binary, unstripped_out) | 
|  | subprocess.check_call(['strip', '-x', '-S', fat_framework_binary]) | 
|  |  | 
|  | # Zip FlutterEmbedder.framework. | 
|  | if args.zip: | 
|  | framework_dst = os.path.join(dst, 'FlutterEmbedder.framework') | 
|  | subprocess.check_call([ | 
|  | 'zip', | 
|  | '-r', | 
|  | '-y', | 
|  | 'FlutterEmbedder.framework.zip', | 
|  | '.', | 
|  | ], | 
|  | cwd=framework_dst) | 
|  | final_src_path = os.path.join( | 
|  | framework_dst, 'FlutterEmbedder.framework.zip' | 
|  | ) | 
|  | final_dst_path = os.path.join(dst, 'FlutterEmbedder.framework.zip') | 
|  | shutil.move(final_src_path, final_dst_path) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) |