# Copyright 2021 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Builds the main distribution package.

This script runs as the CIBW_BEFORE_BUILD command within cibuildwheel:
  - Main distribution .tar.bz2 file (the result of `ninja install`).
  - The python_packages/iree_base_compiler wheel.
  - Installable tests.

It uses cibuildwheel for all of this as a convenience since it already knows
how to arrange for the cross platform part of the build, including using
an appropriate manylinux image, etc.

This is expected to be run from the project directory, containing the
following sub-directories:
  - c/ : Main IREE repository checkout.
  - bindist/ : Directory where binary distribution artifacts are written.
  - c/version_info.json : Version config information (legacy).
  - c/version_local.json : Version config information.

Within the build environment (which may be the naked runner or a docker image):
  - iree-build/ : The build tree.
  - iree-install/ : The install tree.

Environment variables:
  - BINDIST_DIR : If set, then this overrides the default bindist/ directory.
    Should be set if running in a mapped context like a docker container.

Testing this script:
It is not recommended to run cibuildwheel locally. However, this script can
be executed as if running within such an environment. To do so, create
a directory and:
  ln -s /path/to/iree c
  python -m venv .venv
  source .venv/bin/activate

  python ./c/build_tools/github_actions/build_dist.py main-dist
  python ./c/build_tools/github_actions/build_dist.py py-tflite-compiler-tools-pkg
  python ./c/build_tools/github_actions/build_dist.py py-tf-compiler-tools-pkg


That is not a perfect approximation but is close.

To build without the compiler (primarily for the purposes of debugging this script),
use --without-compiler
"""

import json
import os
import platform
import shutil
import subprocess
import sys
import sysconfig
import tarfile

# Setup.
WORK_DIR = os.path.realpath(os.path.curdir)
BUILD_DIR = os.path.join(WORK_DIR, "iree-build")
INSTALL_DIR = os.path.join(WORK_DIR, "iree-install")
IREESRC_DIR = os.path.join(WORK_DIR, "c")
TF_INTEGRATIONS_DIR = os.path.join(IREESRC_DIR, "integrations/tensorflow")
BINDIST_DIR = os.environ.get("BINDIST_DIR")
if BINDIST_DIR is None:
    BINDIST_DIR = os.path.join(WORK_DIR, "bindist")
THIS_DIR = os.path.realpath(os.path.dirname(__file__))
CMAKE_CI_SCRIPT = os.path.join(THIS_DIR, "cmake_ci.py")
BUILD_REQUIREMENTS_TXT = os.path.join(
    IREESRC_DIR,
    "runtime",
    "bindings",
    "python",
    "iree",
    "runtime",
    "build_requirements.txt",
)
CI_REQUIREMENTS_TXT = os.path.join(THIS_DIR, "ci_requirements.txt")
CONFIGURE_BAZEL_PY = os.path.join(IREESRC_DIR, "configure_bazel.py")


# Load version info.
def load_version_info():
    with open(os.path.join(IREESRC_DIR, "version_local.json"), "rt") as f:
        return json.load(f)


try:
    version_info = load_version_info()
except FileNotFoundError:
    print("version_local.json not found. Using version.json defaults")
    version_info = {
        "package-version": "0.1dev1",
        "package-suffix": "-dev",
    }


def remove_cmake_cache():
    cache_file = os.path.join(BUILD_DIR, "CMakeCache.txt")
    if os.path.exists(cache_file):
        print(f"Removing {cache_file}")
        os.remove(cache_file)
    else:
        print(f"Not removing cache file (does not exist): {cache_file}")


def install_python_requirements():
    print("Installing python requirements...")
    subprocess.check_call(
        [sys.executable, "-m", "pip", "install", "-r", BUILD_REQUIREMENTS_TXT]
    )
    subprocess.check_call(
        [sys.executable, "-m", "pip", "install", "-r", CI_REQUIREMENTS_TXT]
    )


def configure_bazel():
    print("Generating configured.bazelrc...")
    subprocess.check_call([sys.executable, CONFIGURE_BAZEL_PY])


def build_main_dist(build_compiler=True):
    """Builds the main distribution binaries.

    Additional packages that are installable as part of a full build and do not
    benefit from a more restricted build can be added here.
    """
    install_python_requirements()

    # Clean up install and build trees.
    shutil.rmtree(INSTALL_DIR, ignore_errors=True)
    remove_cmake_cache()

    # CMake configure.
    print("*** Configuring ***")
    subprocess.run(
        [
            sys.executable,
            CMAKE_CI_SCRIPT,
            f"-B{BUILD_DIR}",
            "--log-level=VERBOSE",
            f"-DCMAKE_INSTALL_PREFIX={INSTALL_DIR}",
            # On some distributions, this will install to lib64. We would like
            # consistency in built packages, so hard-code it.
            "-DCMAKE_INSTALL_LIBDIR=lib",
            f"-DCMAKE_BUILD_TYPE=Release",
            f"-DIREE_BUILD_COMPILER=" + ("ON" if build_compiler else "OFF"),
            f"-DIREE_BUILD_PYTHON_BINDINGS=OFF",
            f"-DIREE_BUILD_SAMPLES=OFF",
        ],
        check=True,
    )

    print("*** Building ***")
    subprocess.run(
        [
            sys.executable,
            CMAKE_CI_SCRIPT,
            "--build",
            BUILD_DIR,
            "--target",
            "all",
        ],
        check=True,
    )

    # TODO: Get proper dependency management on install targets so we don't
    # have to build all first.
    subprocess.run(
        [
            sys.executable,
            CMAKE_CI_SCRIPT,
            "--build",
            BUILD_DIR,
            "--target",
            "iree-install-dist-stripped",
        ],
        check=True,
    )

    print("*** Packaging ***")
    dist_entries = [
        "bin",
        "lib",
        "include",
        "share",
    ]
    dist_archive = os.path.join(
        BINDIST_DIR,
        f"iree-dist{version_info['package-suffix']}"
        f"-{version_info['package-version']}"
        f"-{sysconfig.get_platform()}.tar.xz",
    )
    print(f"Creating archive {dist_archive}")
    os.makedirs(os.path.dirname(dist_archive), exist_ok=True)
    with tarfile.open(dist_archive, mode="w:xz") as tf:
        for entry in dist_entries:
            print(f"Adding entry: {entry}")
            tf.add(os.path.join(INSTALL_DIR, entry), arcname=entry, recursive=True)


def build_py_tf_compiler_tools_pkg():
    """Builds iree-install/python_packages/iree_tools_[tf, tflite] packages."""
    install_python_requirements()
    configure_bazel()

    # Clean up install and build trees.
    shutil.rmtree(INSTALL_DIR, ignore_errors=True)
    remove_cmake_cache()

    os.makedirs(BINDIST_DIR, exist_ok=True)

    for project in ["iree_tflite", "iree_tf"]:
        print(f"*** Building wheel for {project} ***")
        subprocess.run(
            [
                sys.executable,
                "-m",
                "pip",
                "wheel",
                os.path.join(TF_INTEGRATIONS_DIR, "python_projects", project),
            ],
            cwd=BINDIST_DIR,
            check=True,
        )


command = sys.argv[1]
if command == "main-dist":
    if len(sys.argv) > 2 and sys.argv[2] == "--without-compiler":
        print(f"*** NOT building compiler ***")
        build_main_dist(build_compiler=False)
    else:
        build_main_dist()
elif command == "py-tf-compiler-tools-pkg":
    build_py_tf_compiler_tools_pkg()
else:
    print(f"Unrecognized command: {command}")
