#!/usr/bin/env fuchsia-vendored-python
# Copyright 2020 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 glob
import json
import os
import shutil
import subprocess
import sys
"""
The sdk is organized as such:

//arch/
//arch/x64/...
//arch/{other_architectures}/...
//pkg/
//pkg/{libs}/
//pkg/sysroot/
//pkg/sysroot/meta.json

This script will create a new arch/ directory (--arch-name) by copying the
layout described in //pkg/sysroot/meta.json for an existing architecture.
This involves first copying headers which will be no different, and also
all shared objects in //pkg/arch/{existing_arch}/sysroot/lib. Most of these
shared objects are actually just linker scripts so they can be safely copied.
The other shared objects will be later replaced by //pkg/sysroot/*.ifs files,
currently this is libc.ifs and zircon.ifs. Scrt1.o is also replaced.
//pkg/arch/{new_arch}/lib is populated from shared objects created from
//pkg/*/*.ifs files (excluding //pkg/sysroot).
"""

TARGET_TO_TRIPLE = {
    "x64": "x86_64-unknown-fuchsia",
    "arm64": "aarch64-unknown-fuchsia",
    "riscv64": "riscv64-unknown-fuchsia",
}


def get_filename_from_ifs(ifs_file):
    ifs_file = os.path.basename(ifs_file)
    # This is necessary because libc.ifs is not called c.ifs, which would be the
    # conventional naming scheme for other libraries.
    name = os.path.splitext(ifs_file)[0]
    if not name.startswith("lib"):
        name = "lib" + name
    return name + ".so"


class SysrootGenerator:

    def _copy_files(self, other_arch, other_paths, meta_json_key):
        for src_path in other_paths:
            path = src_path.replace(other_arch, self.arch_name, 1)
            os.makedirs(
                os.path.join(self.sdk_dir, os.path.dirname(path)),
                exist_ok=True)
            shutil.copyfile(
                os.path.join(self.sdk_dir, src_path),
                os.path.join(self.sdk_dir, path))
            self.sysroot_meta["versions"][self.arch_name][meta_json_key].append(
                path)

    def _copy_headers(self, other_arch, other_headers):
        self._copy_files(other_arch, other_headers, "headers")

    def _copy_link_libs(self, other_arch, other_link_libs):
        self._copy_files(other_arch, other_link_libs, "link_libs")
        self._make_Scrt1()

    def _make_Scrt1(self):
        # For bringing up new architectures executables won't be run anyway, this just creates
        # an empty Scrt1.o.
        Scrt1 = os.path.join(
            self.sdk_dir, "arch", self.arch_name, "sysroot", "lib", "Scrt1.o")
        open(Scrt1, "w")

    def __init__(self, sdk_dir, arch_name):
        self.sdk_dir = sdk_dir
        self.arch_name = arch_name

    def _create_from_dir_structure(self):
        other_arch = os.listdir(os.path.join(self.sdk_dir, "arch"))[0]

        def make_src_dst(dir):
            return os.path.join(
                self.sdk_dir, "arch", other_arch, "sysroot", dir), os.path.join(
                    self.sdk_dir, "arch", self.arch_name, "sysroot", dir)

        src, dst = make_src_dst("include")
        shutil.copytree(src, dst)

        src, dst = make_src_dst("lib")
        shutil.copytree(src, dst)
        self._make_Scrt1()

    def _create_from_meta_json(self, meta_json):
        with open(meta_json) as f:
            self.sysroot_meta = json.load(f)
            other_arch, other_version = next(
                iter(self.sysroot_meta["versions"].items()))
            other_headers, other_link_libs = other_version[
                "headers"], other_version["link_libs"]
            self.sysroot_meta["versions"][self.arch_name] = {
                "debug_libs": [],
                "dist_dir": f"arch/{self.arch_name}/sysroot",
                "dist_libs": [],
                "headers": [],
                "include_dir": f"arch/{self.arch_name}/sysroot/include",
                "link_libs": [],
                "root": f"arch/{self.arch_name}/sysroot"
            }
        self._copy_headers(other_arch, other_headers)
        self._copy_link_libs(other_arch, other_link_libs)

    def create(self):
        meta_json = os.path.join(self.sdk_dir, "pkg", "sysroot", "meta.json")
        if os.path.exists(meta_json):
            self.emit_meta_json = True
            self._create_from_meta_json(meta_json)
        else:
            pkg_sysroot = os.path.join(self.sdk_dir, "pkg", "sysroot")
            self.emit_meta_json = False
            self.sysroot_meta = {
                "ifs_files": glob.glob("*.ifs", root_dir=pkg_sysroot)
            }
            self._create_from_dir_structure()

    def add_stubs(self, create_stub):
        for ifs_file in self.sysroot_meta["ifs_files"]:
            source = os.path.join(self.sdk_dir, "pkg", "sysroot", ifs_file)
            dest = os.path.join(
                self.sdk_dir, "arch", self.arch_name, "sysroot", "lib",
                get_filename_from_ifs(ifs_file))
            create_stub(source, dest)

    def finish(self):
        if not self.emit_meta_json:
            return
        with open(os.path.join(self.sdk_dir, "pkg", "sysroot", "meta.json"),
                  "w") as f:
            json.dump(self.sysroot_meta, f)


def create_libs(sdk_dir, arch_name, create_stub):
    dirs = [
        f for f in os.listdir(os.path.join(sdk_dir, "pkg"))
        if os.path.basename(f) != "sysroot"
    ]
    for dir in dirs:
        ifs_file = os.path.join(sdk_dir, "pkg", dir, f"{dir}.ifs")
        if os.path.exists(ifs_file):
            os.makedirs(
                os.path.join(sdk_dir, "arch", arch_name, "lib"), exist_ok=True)
            create_stub(
                ifs_file,
                os.path.join(
                    sdk_dir, "arch", arch_name, "lib",
                    get_filename_from_ifs(ifs_file)))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--sdk-dir",
        required=True,
        help="Path to sdk, should have arch/ and pkg/ at top level")
    parser.add_argument(
        "--arch", required=True, help="ifs target to use for generating stubs")
    parser.add_argument("--ifs-path", default="llvm-ifs")
    args = parser.parse_args()

    if os.path.exists(os.path.join(args.sdk_dir, "arch", args.arch)):
        print(f"arch/{args.arch} already exists!")
        return 1

    def write_stub(src, dest):
        subprocess.check_call(
            [
                args.ifs_path, "--target", TARGET_TO_TRIPLE[args.arch],
                f"--output-elf={dest}", src
            ])

    sysroot_creator = SysrootGenerator(args.sdk_dir, args.arch)
    sysroot_creator.create()
    sysroot_creator.add_stubs(write_stub)
    sysroot_creator.finish()

    # These are libs outside of the sysroot like fdio, etc.
    create_libs(args.sdk_dir, args.arch, write_stub)

    return 0


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