#!/usr/bin/env python
# Copyright 2018 The Fuchsia 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 os
import subprocess
import sys


FUCHSIA_ROOT = os.path.dirname(  # $root
    os.path.dirname(             # scripts
    os.path.dirname(             # rust
    os.path.abspath(__file__))))

BUILD_CONFIG = '''
[llvm]
optimize = true
static-libstdcpp = true
ninja = true
targets = "X86;AArch64"

[build]
target = ["{target}-fuchsia"]
docs = false
extended = true
openssl-static = true

[install]
prefix = "{prefix}"
sysconfdir = "etc"

[rust]
optimize = true

[target.{target}-fuchsia]
cc = "{cc}"
cxx = "{cxx}"
ar = "{ar}"
linker = "{cc}"

[dist]
'''

CARGO_CONFIG = '''
[target.{target}-fuchsia]
linker = "{linker}"
ar = "{ar}"
rustflags = [
    "-C", "link-arg=--target={target}-fuchsia",
    "-C", "link-arg=--sysroot={sysroot}",
    "-C", "link-arg=-L{shared_libs_root}",
]
'''

def ensure_dir(dir):
    if not os.path.exists(dir):
        os.makedirs(dir)
    return dir

def main():
    parser = argparse.ArgumentParser(description='Build a Rust toolchain for Fuchsia')
    parser.add_argument(
            '--rust-root',
            help='root directory of Rust checkout',
            required=True)
    parser.add_argument(
            '--sysroot',
            help='zircon sysroot (possibly //out/release-x64/sdk/exported/zircon_sysroot/sysroot)',
            required=True)
    parser.add_argument(
            '--shared-libs-root',
            help='shared libs root (possibly //out/release-x64/x64-shared)',
            required=True)
    parser.add_argument(
            '--host-os',
            help='host operating system',
            choices=['linux', 'mac'],
            default='linux')
    parser.add_argument(
            '--target',
            help='target architecture',
            choices=['x86_64', 'aarch64'],
            default='x86_64')
    parser.add_argument(
            '--staging-dir',
            help='directory in which to stage Rust build configuration artifacts',
            default='/tmp/fuchsia_rustc_staging')
    parser.add_argument(
            '--debug',
            help='turn on debug mode, with extra logs',
            action='store_true')
    args = parser.parse_args()

    rust_root = os.path.abspath(args.rust_root)
    sysroot = os.path.abspath(args.sysroot)
    shared_libs_root = os.path.abspath(args.shared_libs_root)
    host_os = args.host_os
    target = args.target
    staging_dir = os.path.abspath(args.staging_dir)
    debug = args.debug

    build_dir = ensure_dir(os.path.join(staging_dir, 'build'))
    toolchain_dir = ensure_dir(os.path.join(staging_dir, 'toolchain'))
    clang_dir = os.path.join(FUCHSIA_ROOT, 'buildtools', host_os + '-x64',
                             'clang')

    config_file = os.path.join(build_dir, 'config.toml')
    with open(config_file, 'w') as file:
        file.write(BUILD_CONFIG.format(
            target=target,
            prefix=toolchain_dir,
            cc=os.path.join(clang_dir, 'bin', 'clang'),
            cxx=os.path.join(clang_dir, 'bin', 'clang++'),
            ar=os.path.join(clang_dir, 'bin', 'llvm-ar'),
        ))

    cargo_dir = ensure_dir(os.path.join(staging_dir, '.cargo'))
    with open(os.path.join(cargo_dir, 'config'), 'w') as file:
        file.write(CARGO_CONFIG.format(
            target=target,
            linker=os.path.join(clang_dir, 'bin', 'clang'),
            ar=os.path.join(clang_dir, 'bin', 'llvm-ar'),
            sysroot=sysroot,
            shared_libs_root=shared_libs_root,
        ))

    cflags_key = 'CFLAGS_%s-fuchsia' % target
    cflags_val = '--target=%s-fuchsia --sysroot=%s' % (target, sysroot)

    env = {
        'CARGO_HOME': cargo_dir,
        cflags_key: cflags_val,
        'PATH': os.environ['PATH'],
        'RUST_BACKTRACE': '1',
    }

    def run_build_command(command):
        command_args = [
            os.path.join(rust_root, 'x.py'),
        ]
        command_args += command
        command_args += [
            '--config',
            config_file,
            '--src',
            rust_root,
        ]
        if debug:
            command_args.append('--verbose')
        print('Running: %s' % ' '.join(command_args))
        # The builds need to run from a subdirectory of the staging dir
        # otherwise the cargo config set up above will get clobbered by x.py.
        out_dir = ensure_dir(os.path.join(staging_dir, 'out'))
        subprocess.check_call(command_args, env=env, cwd=out_dir)

    run_build_command(['install'])

    print('The toolchain is ready at: %s' % toolchain_dir)


if __name__ == '__main__':
    main()
