#!/usr/bin/env vpython3

# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""WebRTC iOS XCFramework build script.
Each architecture is compiled separately before being merged together.
By default, the library is created in out_ios_libs/. (Change with -o.)
"""

import argparse
import logging
import os
import shutil
import subprocess
import sys

os.environ['PATH'] = '/usr/libexec' + os.pathsep + os.environ['PATH']

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SRC_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..'))
sys.path.append(os.path.join(SRC_DIR, 'build'))
import find_depot_tools

SDK_OUTPUT_DIR = os.path.join(SRC_DIR, 'out_ios_libs')
SDK_FRAMEWORK_NAME = 'WebRTC.framework'
SDK_DSYM_NAME = 'WebRTC.dSYM'
SDK_XCFRAMEWORK_NAME = 'WebRTC.xcframework'

ENABLED_ARCHS = [
    'device:arm64', 'simulator:arm64', 'simulator:x64',
    'catalyst:arm64', 'catalyst:x64',
    'arm64', 'x64'
]
DEFAULT_ARCHS = [
    'device:arm64', 'simulator:arm64', 'simulator:x64'
]
IOS_MINIMUM_DEPLOYMENT_TARGET = {
    'device': '14.0',
    'simulator': '14.0',
    'catalyst': '14.0'
}
LIBVPX_BUILD_VP9 = False

sys.path.append(os.path.join(SCRIPT_DIR, '..', 'libs'))
from generate_licenses import LicenseBuilder


def _ParseArgs():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--build_config',
                        default='release',
                        choices=['debug', 'release'],
                        help='The build config. Can be "debug" or "release". '
                        'Defaults to "release".')
    parser.add_argument(
        '--arch',
        nargs='+',
        default=DEFAULT_ARCHS,
        choices=ENABLED_ARCHS,
        help='Architectures to build. Defaults to %(default)s.')
    parser.add_argument(
        '-c',
        '--clean',
        action='store_true',
        default=False,
        help='Removes the previously generated build output, if any.')
    parser.add_argument(
        '-p',
        '--purify',
        action='store_true',
        default=False,
        help='Purifies the previously generated build output by '
        'removing the temporary results used when (re)building.')
    parser.add_argument(
        '-o',
        '--output-dir',
        type=os.path.abspath,
        default=SDK_OUTPUT_DIR,
        help='Specifies a directory to output the build artifacts to. '
        'If specified together with -c, deletes the dir.')
    parser.add_argument(
        '-r',
        '--revision',
        type=int,
        default=0,
        help='Specifies a revision number to embed if building the framework.')
    parser.add_argument('--verbose',
                        action='store_true',
                        default=False,
                        help='Debug logging.')
    parser.add_argument('--use-remoteexec',
                        action='store_true',
                        default=False,
                        help='Use RBE to build.')
    parser.add_argument(
        '--deployment-target',
        default=IOS_MINIMUM_DEPLOYMENT_TARGET['device'],
        help='Raise the minimum deployment target to build for. '
        'Cannot be lowered below 12.0 for iOS/iPadOS '
        'and 14.0 for Catalyst.')
    parser.add_argument(
        '--extra-gn-args',
        default=[],
        nargs='*',
        help='Additional GN args to be used during Ninja generation.')

    return parser.parse_args()


def _RunCommand(cmd):
    logging.debug('Running: %r', cmd)
    subprocess.check_call(cmd, cwd=SRC_DIR)


def _CleanArtifacts(output_dir):
    if os.path.isdir(output_dir):
        logging.info('Deleting %s', output_dir)
        shutil.rmtree(output_dir)


def _CleanTemporary(output_dir, architectures):
    if os.path.isdir(output_dir):
        logging.info('Removing temporary build files.')
        for (env, archs) in architectures.items():
            for arch in archs:
                arch_lib_path = '%s_%s_libs' % (env, arch)
                if os.path.isdir(arch_lib_path):
                    shutil.rmtree(arch_lib_path)


def _ParseArchitecture(architectures):
    result = dict()
    for arch in architectures:
        if ":" in arch:
            target_environment, target_cpu = arch.split(":")
        else:
            logging.warning('The environment for build is not specified.')
            logging.warning('It is assumed based on cpu type.')
            logging.warning('See crbug.com/1138425 for more details.')
            if arch == "x64":
                target_environment = "simulator"
            else:
                target_environment = "device"
            target_cpu = arch
        archs = result.get(target_environment)
        if archs is None:
            result[target_environment] = {target_cpu}
        else:
            archs.add(target_cpu)

    return result


def _VersionMax(*versions):
    return max(*versions,
               key=lambda version:
               [int(component) for component in version.split('.')])


def BuildWebRTC(output_dir, target_environment, target_arch, flavor,
                gn_target_name, ios_deployment_target, libvpx_build_vp9,
                use_remoteexec, extra_gn_args):
    gn_args = [
        'target_os="ios"',
        'ios_enable_code_signing=false',
        'is_component_build=false',
        'rtc_include_tests=false',
    ]

    # Add flavor option.
    if flavor == 'debug':
        gn_args.append('is_debug=true')
    elif flavor == 'release':
        gn_args.append('is_debug=false')
    else:
        raise ValueError('Unexpected flavor type: %s' % flavor)

    gn_args.append('target_environment="%s"' % target_environment)

    gn_args.append('target_cpu="%s"' % target_arch)

    gn_args.append('ios_deployment_target="%s"' % ios_deployment_target)

    gn_args.append('rtc_libvpx_build_vp9=' +
                   ('true' if libvpx_build_vp9 else 'false'))

    gn_args.append('use_lld=true')
    gn_args.append('rtc_enable_objc_symbol_export=true')
    gn_args.append('use_siso=true')
    if use_remoteexec:
        gn_args.extend([
            'use_remoteexec=true',
            'use_reclient=false',
        ])

    args_string = ' '.join(gn_args + extra_gn_args)
    logging.info('Building WebRTC with args: %s', args_string)

    cmd = [
        sys.executable,
        os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py'),
        'gen',
        output_dir,
        '--args=' + args_string,
    ]
    _RunCommand(cmd)
    logging.info('Building target: %s', gn_target_name)

    cmd = [
        os.path.join(SRC_DIR, 'third_party', 'siso', 'cipd', 'siso'),
        'ninja',
        '-C',
        output_dir,
        gn_target_name,
    ]
    if use_remoteexec:
        cmd.extend(['-remote_jobs', '200'])
    _RunCommand(cmd)


def main():
    args = _ParseArgs()

    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)

    if args.clean:
        _CleanArtifacts(args.output_dir)
        return 0

    # architectures is typed as Dict[str, Set[str]],
    # where key is for the environment (device or simulator)
    # and value is for the cpu type.
    architectures = _ParseArchitecture(args.arch)
    gn_args = args.extra_gn_args

    if args.purify:
        _CleanTemporary(args.output_dir, architectures)
        return 0

    gn_target_name = 'framework_objc'
    gn_args.append('enable_dsyms=true')
    gn_args.append('enable_stripping=true')

    # Build all architectures.
    framework_paths = []
    all_lib_paths = []
    for (environment, archs) in list(architectures.items()):
        ios_deployment_target = _VersionMax(
            args.deployment_target, IOS_MINIMUM_DEPLOYMENT_TARGET[environment])
        framework_path = os.path.join(args.output_dir, environment)
        framework_paths.append(framework_path)
        lib_paths = []
        for arch in archs:
            lib_path = '%s_%s_libs' % (framework_path, arch)
            lib_paths.append(lib_path)
            BuildWebRTC(lib_path, environment, arch, args.build_config,
                        gn_target_name, ios_deployment_target,
                        LIBVPX_BUILD_VP9, args.use_remoteexec, gn_args)
        all_lib_paths.extend(lib_paths)

        # Combine the slices.
        dylib_path = os.path.join(SDK_FRAMEWORK_NAME, 'WebRTC')
        # Dylibs will be combined, all other files are the same across archs.
        shutil.rmtree(os.path.join(framework_path, SDK_FRAMEWORK_NAME),
                      ignore_errors=True)
        shutil.copytree(os.path.join(lib_paths[0], SDK_FRAMEWORK_NAME),
                        os.path.join(framework_path, SDK_FRAMEWORK_NAME),
                        symlinks=True)
        logging.info('Merging framework slices for %s.', environment)
        dylib_paths = [os.path.join(path, dylib_path) for path in lib_paths]
        out_dylib_path = os.path.join(framework_path, dylib_path)
        if os.path.islink(out_dylib_path):
            out_dylib_path = os.path.join(os.path.dirname(out_dylib_path),
                                          os.readlink(out_dylib_path))
        try:
            os.remove(out_dylib_path)
        except OSError:
            pass
        cmd = ['lipo'] + dylib_paths + ['-create', '-output', out_dylib_path]
        _RunCommand(cmd)

        # Merge the dSYM slices.
        lib_dsym_dir_path = os.path.join(lib_paths[0], SDK_DSYM_NAME)
        if os.path.isdir(lib_dsym_dir_path):
            shutil.rmtree(os.path.join(framework_path, SDK_DSYM_NAME),
                          ignore_errors=True)
            shutil.copytree(lib_dsym_dir_path,
                            os.path.join(framework_path, SDK_DSYM_NAME))
            logging.info('Merging dSYM slices.')
            dsym_path = os.path.join(SDK_DSYM_NAME, 'Contents', 'Resources',
                                     'DWARF', 'WebRTC')
            lib_dsym_paths = [
                os.path.join(path, dsym_path) for path in lib_paths
            ]
            out_dsym_path = os.path.join(framework_path, dsym_path)
            try:
                os.remove(out_dsym_path)
            except OSError:
                pass
            cmd = ['lipo'
                   ] + lib_dsym_paths + ['-create', '-output', out_dsym_path]
            _RunCommand(cmd)

            # Check for Mac-style WebRTC.framework/Resources/ (for Catalyst)...
            resources_dir = os.path.join(framework_path, SDK_FRAMEWORK_NAME,
                                         'Resources')
            if not os.path.exists(resources_dir):
                # ...then fall back to iOS-style WebRTC.framework/
                resources_dir = os.path.dirname(resources_dir)

            # Modify the version number.
            # Format should be <Branch cut MXX>.<Hotfix #>.<Rev #>.
            # e.g. 55.0.14986 means
            # branch cut 55, no hotfixes, and revision 14986.
            infoplist_path = os.path.join(resources_dir, 'Info.plist')
            cmd = [
                'PlistBuddy', '-c', 'Print :CFBundleShortVersionString',
                infoplist_path
            ]
            major_minor = subprocess.check_output(cmd).decode('utf-8').strip()
            version_number = '%s.%s' % (major_minor, args.revision)
            logging.info('Substituting revision number: %s', version_number)
            cmd = [
                'PlistBuddy', '-c', 'Set :CFBundleVersion ' + version_number,
                infoplist_path
            ]
            _RunCommand(cmd)
            _RunCommand(['plutil', '-convert', 'binary1', infoplist_path])

    xcframework_dir = os.path.join(args.output_dir, SDK_XCFRAMEWORK_NAME)
    if os.path.isdir(xcframework_dir):
        shutil.rmtree(xcframework_dir)

    logging.info('Creating xcframework.')
    cmd = ['xcodebuild', '-create-xcframework', '-output', xcframework_dir]

    # Apparently, xcodebuild needs absolute paths for input arguments
    for framework_path in framework_paths:
        cmd += [
            '-framework',
            os.path.abspath(os.path.join(framework_path, SDK_FRAMEWORK_NAME)),
        ]
        dsym_full_path = os.path.join(framework_path, SDK_DSYM_NAME)
        if os.path.exists(dsym_full_path):
            cmd += ['-debug-symbols', os.path.abspath(dsym_full_path)]

    _RunCommand(cmd)

    # Generate the license file.
    logging.info('Generate license file.')
    gn_target_full_name = '//sdk:' + gn_target_name
    builder = LicenseBuilder(all_lib_paths, [gn_target_full_name])
    builder.generate_license_text(
        os.path.join(args.output_dir, SDK_XCFRAMEWORK_NAME))

    logging.info('Done.')
    return 0


if __name__ == '__main__':
    sys.exit(main())
