#!/usr/bin/python3
##===- utils/llvmbuild - Build the LLVM project ----------------*-python-*-===##
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
#
# This script builds many different flavors of the LLVM ecosystem.  It
# will build LLVM, Clang and dragonegg as well as run tests on them.
# This script is convenient to use to check builds and tests before
# committing changes to the upstream repository
#
# A typical source setup uses three trees and looks like this:
#
# official
#   dragonegg
#   llvm
#     tools
#       clang
# staging
#   dragonegg
#   llvm
#     tools
#       clang
# commit
#   dragonegg
#   llvm
#     tools
#       clang
#
# In a typical workflow, the "official" tree always contains unchanged
# sources from the main LLVM project repositories.  The "staging" tree
# is where local work is done.  A set of changes resides there waiting
# to be moved upstream.  The "commit" tree is where changes from
# "staging" make their way upstream.  Individual incremental changes
# from "staging" are applied to "commit" and committed upstream after
# a successful build and test run.  A successful build is one in which
# testing results in no more failures than seen in the testing of the
# "official" tree.
# 
# A build may be invoked as such:
#
# llvmbuild --src=~/llvm/commit --src=~/llvm/staging --src=~/llvm/official
#   --build=debug --build=release --build=paranoid
#   --prefix=/home/greened/install --builddir=/home/greened/build
#
# This will build the LLVM ecosystem, including LLVM, Clangand
# dragonegg, putting build results in ~/build and installing tools in
# ~/install.  llvm-compilers-check creates separate build and install
# directories for each source/build flavor.  In the above example,
# llvmbuild will build debug, release and paranoid (debug+checks)
# flavors from each source tree (official, staging and commit) for a
# total of nine builds.  All builds will be run in parallel.
#
# The user may control parallelism via the --jobs and --threads
# switches.  --jobs tells llvm-compilers-checl the maximum total
# number of builds to activate in parallel.  The user may think of it
# as equivalent to the GNU make -j switch.  --threads tells
# llvm-compilers-check how many worker threads to use to accomplish
# those builds.  If --threads is less than --jobs, --threads workers
# will be launched and each one will pick a source/flavor combination
# to build.  Then llvm-compilers-check will invoke GNU make with -j
# (--jobs / --threads) to use up the remaining job capacity.  Once a
# worker is finished with a build, it will pick another combination
# off the list and start building it.
#
##===----------------------------------------------------------------------===##

import optparse
import os
import sys
import threading
import queue
import logging
import traceback
import subprocess
import re

# TODO: Use shutil.which when it is available (3.2 or later)
def find_executable(executable, path=None):
    """Try to find 'executable' in the directories listed in 'path' (a
    string listing directories separated by 'os.pathsep'; defaults to
    os.environ['PATH']).  Returns the complete filename or None if not
    found
    """
    if path is None:
        path = os.environ['PATH']
    paths = path.split(os.pathsep)
    extlist = ['']
    if os.name == 'os2':
        (base, ext) = os.path.splitext(executable)
        # executable files on OS/2 can have an arbitrary extension, but
        # .exe is automatically appended if no dot is present in the name
        if not ext:
            executable = executable + ".exe"
    elif sys.platform == 'win32':
        pathext = os.environ['PATHEXT'].lower().split(os.pathsep)
        (base, ext) = os.path.splitext(executable)
        if ext.lower() not in pathext:
            extlist = pathext
    for ext in extlist:
        execname = executable + ext
        if os.path.isfile(execname):
            return execname
        else:
            for p in paths:
                f = os.path.join(p, execname)
                if os.path.isfile(f):
                    return f
    else:
        return None

def is_executable(fpath):
    return os.path.exists(fpath) and os.access(fpath, os.X_OK)

def add_options(parser):
    parser.add_option("-v", "--verbose", action="store_true",
                      default=False,
                      help=("Output informational messages"
                            " [default: %default]"))
    parser.add_option("--src", action="append",
                      help=("Top-level source directory [default: %default]"))
    parser.add_option("--build", action="append",
                      help=("Build types to run [default: %default]"))
    parser.add_option("--cc", default=find_executable("cc"),
                      help=("The C compiler to use [default: %default]"))
    parser.add_option("--cxx", default=find_executable("c++"),
                      help=("The C++ compiler to use [default: %default]"))
    parser.add_option("--threads", default=4, type="int",
                      help=("The number of worker threads to use "
                            "[default: %default]"))
    parser.add_option("--jobs", "-j", default=8, type="int",
                      help=("The number of simultaneous build jobs "
                            "[default: %default]"))
    parser.add_option("--prefix",
                      help=("Root install directory [default: %default]"))
    parser.add_option("--builddir",
                      help=("Root build directory [default: %default]"))
    parser.add_option("--extra-llvm-config-flags", default="",
                      help=("Extra flags to pass to llvm configure [default: %default]"))
    parser.add_option("--force-configure", default=False, action="store_true",
                      help=("Force reconfigure of all components"))
    parser.add_option("--no-dragonegg", default=False, action="store_true",
                      help=("Do not build dragonegg"))
    parser.add_option("--no-install", default=False, action="store_true",
                      help=("Do not do installs"))
    parser.add_option("--keep-going", default=False, action="store_true",
                      help=("Keep going after failures"))
    parser.add_option("--no-flavor-prefix", default=False, action="store_true",
                      help=("Do not append the build flavor to the install path"))
    parser.add_option("--enable-werror", default=False, action="store_true",
                      help=("Build with -Werror"))
    return

def check_options(parser, options, valid_builds):
    # See if we're building valid flavors.
    for build in options.build:
        if (build not in valid_builds):
            parser.error("'" + build + "' is not a valid build flavor "
                         + str(valid_builds))

    # See if we can find source directories.
    for src in options.src:
        for component in components:
            component = component.rstrip("2")
            compsrc = src + "/" + component
            if (not os.path.isdir(compsrc)):
                parser.error("'" + compsrc + "' does not exist")

    # See if we can find the compilers
    options.cc = find_executable(options.cc)
    options.cxx = find_executable(options.cxx)

    return

# Find a unique short name for the given set of paths.  This searches
# back through path components until it finds unique component names
# among all given paths.
def get_path_abbrevs(paths):
    # Find the number of common starting characters in the last component
    # of the paths.
    unique_paths = list(paths)

    class NotFoundException(Exception): pass

    # Find a unique component of each path.
    unique_bases = unique_paths[:]
    found = 0
    while len(unique_paths) > 0:
        bases = [os.path.basename(src) for src in unique_paths]
        components = { c for c in bases }
        # Account for single entry in paths.
        if len(components) > 1 or len(components) == len(bases):
            # We found something unique.
            for c in components:
                if bases.count(c) == 1:
                   index = bases.index(c)
                   unique_bases[index] = c
                   # Remove the corresponding path from the set under
                   # consideration.
                   unique_paths[index] = None
            unique_paths = [ p for p in unique_paths if p is not None ]
        unique_paths = [os.path.dirname(src) for src in unique_paths]

    if len(unique_paths) > 0:
        raise NotFoundException()

    abbrevs = dict(zip(paths, [base for base in unique_bases]))

    return abbrevs

# Given a set of unique names, find a short character sequence that
# uniquely identifies them.
def get_short_abbrevs(unique_bases):
    # Find a unique start character for each path base.
    my_unique_bases = unique_bases[:]
    unique_char_starts = unique_bases[:]
    while len(my_unique_bases) > 0:
        for start, char_tuple in enumerate(zip(*[base
                                                 for base in my_unique_bases])):
            chars = { c for c in char_tuple }
            # Account for single path.
            if len(chars) > 1 or len(chars) == len(char_tuple):
                # We found something unique.
                for c in chars:
                    if char_tuple.count(c) == 1:
                        index = char_tuple.index(c)
                        unique_char_starts[index] = start
                        # Remove the corresponding path from the set under
                        # consideration.
                        my_unique_bases[index] = None
                my_unique_bases = [ b for b in my_unique_bases
                                    if b is not None ]
                break

    if len(my_unique_bases) > 0:
        raise NotFoundException()

    abbrevs = [abbrev[start_index:start_index+3]
               for abbrev, start_index
               in zip([base for base in unique_bases],
                      [index for index in unique_char_starts])]

    abbrevs = dict(zip(unique_bases, abbrevs))

    return abbrevs

class Builder(threading.Thread):
    class ExecutableNotFound(Exception): pass
    class FileNotExecutable(Exception): pass

    def __init__(self, work_queue, jobs,
                 build_abbrev, source_abbrev,
                 options):
        super().__init__()
        self.work_queue = work_queue
        self.jobs = jobs
        self.cc = options.cc
        self.cxx = options.cxx
        self.build_abbrev = build_abbrev
        self.source_abbrev = source_abbrev
        self.build_prefix = options.builddir
        self.install_prefix = options.prefix
        self.options = options
        self.component_abbrev = dict(
            llvm="llvm",
            dragonegg="degg")
    def run(self):
        while True:
            try:
                source, build = self.work_queue.get()
                self.dobuild(source, build)
            except:
                traceback.print_exc()
            finally:
                self.work_queue.task_done()

    def execute(self, command, execdir, env, component):
        prefix = self.component_abbrev[component.replace("-", "_")]
        pwd = os.getcwd()
        if not os.path.exists(execdir):
            os.makedirs(execdir)

        execenv = os.environ.copy()

        for key, value in env.items():
            execenv[key] = value

        self.logger.debug("[" + prefix + "] " + "env " + str(env) + " "
                          + " ".join(command));

        try:
            proc = subprocess.Popen(command,
                                    cwd=execdir,
                                    env=execenv,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)

            line = proc.stdout.readline()
            while line:
                self.logger.info("[" + prefix + "] "
                                 + str(line, "utf-8").rstrip())
                line = proc.stdout.readline()

            (stdoutdata, stderrdata) = proc.communicate()
            retcode = proc.wait()

            return retcode

        except:
            traceback.print_exc()

    # Get a list of C++ include directories to pass to clang.
    def get_includes(self):
        # Assume we're building with g++ for now.
        command = [self.cxx]
        command += ["-v", "-x", "c++", "/dev/null", "-fsyntax-only"]
        includes = []
        self.logger.debug(command)
        try:
            proc = subprocess.Popen(command,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)

            gather = False
            line = proc.stdout.readline()
            while line:
                self.logger.debug(line)
                if re.search("End of search list", str(line)) is not None:
                    self.logger.debug("Stop Gather")
                    gather = False
                if gather:
                    includes.append(str(line, "utf-8").strip())
                if re.search("#include <...> search starts", str(line)) is not None:
                    self.logger.debug("Start Gather")
                    gather = True
                line = proc.stdout.readline()

        except:
            traceback.print_exc()
        self.logger.debug(includes)
        return includes

    def dobuild(self, source, build):
        build_suffix = ""

        ssabbrev = get_short_abbrevs([ab for ab in self.source_abbrev.values()])

        prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + self.build_abbrev[build] + "]"
        if (not self.options.no_flavor_prefix):
            self.install_prefix += "/" + self.source_abbrev[source] + "/" + build

        build_suffix += "/" + self.source_abbrev[source] + "/" + build

        self.logger = logging.getLogger(prefix)

        self.logger.debug(self.install_prefix)

        # Assume we're building with gcc for now.
        cxxincludes = self.get_includes()
        cxxroot = os.path.dirname(cxxincludes[0]) # Remove the version
        cxxroot = os.path.dirname(cxxroot)        # Remove the c++
        cxxroot = os.path.dirname(cxxroot)        # Remove the include

        configure_flags = dict(
            llvm=dict(debug=["--prefix=" + self.install_prefix,
                             "--enable-assertions",
                             "--disable-optimized",
                             "--with-gcc-toolchain=" + cxxroot],
                      release=["--prefix=" + self.install_prefix,
                               "--enable-optimized",
                               "--with-gcc-toolchain=" + cxxroot],
                      paranoid=["--prefix=" + self.install_prefix,
                                "--enable-assertions",
                                "--enable-expensive-checks",
                                "--disable-optimized",
                                "--with-gcc-toolchain=" + cxxroot]),
            dragonegg=dict(debug=[],
                           release=[],
                           paranoid=[]))

        if (self.options.enable_werror):
            configure_flags["llvm"]["debug"].append("--enable-werror")
            configure_flags["llvm"]["release"].append("--enable-werror")
            configure_flags["llvm"]["paranoid"].append("--enable-werror")

        configure_env = dict(
            llvm=dict(debug=dict(CC=self.cc,
                                 CXX=self.cxx),
                      release=dict(CC=self.cc,
                                   CXX=self.cxx),
                      paranoid=dict(CC=self.cc,
                                    CXX=self.cxx)),
            dragonegg=dict(debug=dict(CC=self.cc,
                                      CXX=self.cxx),
                           release=dict(CC=self.cc,
                                        CXX=self.cxx),
                           paranoid=dict(CC=self.cc,
                                         CXX=self.cxx)))

        make_flags = dict(
            llvm=dict(debug=["-j" + str(self.jobs)],
                      release=["-j" + str(self.jobs)],
                      paranoid=["-j" + str(self.jobs)]),
            dragonegg=dict(debug=["-j" + str(self.jobs)],
                           release=["-j" + str(self.jobs)],
                           paranoid=["-j" + str(self.jobs)]))

        make_env = dict(
            llvm=dict(debug=dict(),
                      release=dict(),
                      paranoid=dict()),
            dragonegg=dict(debug=dict(GCC=self.cc,
                                      LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
                           release=dict(GCC=self.cc,
                                        LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
                           paranoid=dict(GCC=self.cc,
                                         LLVM_CONFIG=self.install_prefix + "/bin/llvm-config")))

        make_install_flags = dict(
            llvm=dict(debug=["install"],
                      release=["install"],
                      paranoid=["install"]),
            dragonegg=dict(debug=["install"],
                           release=["install"],
                           paranoid=["install"]))

        make_install_env = dict(
            llvm=dict(debug=dict(),
                      release=dict(),
                      paranoid=dict()),
            dragonegg=dict(debug=dict(),
                           release=dict(),
                           paranoid=dict()))

        make_check_flags = dict(
            llvm=dict(debug=["check"],
                      release=["check"],
                      paranoid=["check"]),
            dragonegg=dict(debug=["check"],
                           release=["check"],
                           paranoid=["check"]))

        make_check_env = dict(
            llvm=dict(debug=dict(),
                      release=dict(),
                      paranoid=dict()),
            dragonegg=dict(debug=dict(),
                           release=dict(),
                           paranoid=dict()))

        for component in components:
            comp = component[:]

            if (self.options.no_dragonegg):
                if (comp == 'dragonegg'):
                    self.logger.info("Skipping " + component + " in "
                                     + builddir)
                    continue

            srcdir = source + "/" + comp.rstrip("2")
            builddir = self.build_prefix + "/" + comp + "/" + build_suffix
            installdir = self.install_prefix

            comp_key = comp.replace("-", "_")

            config_args = configure_flags[comp_key][build][:]
            config_args.extend(getattr(self.options,
                                       "extra_" + comp_key.rstrip("2")
                                       + "_config_flags",
                                       "").split())

            self.logger.info("Configuring " + component + " in " + builddir)
            configrc = self.configure(component, srcdir, builddir,
                                      config_args,
                                      configure_env[comp_key][build])

            if (configrc == None) :
                self.logger.info("[None] Failed to configure " + component + " in " + installdir)

            if (configrc == 0 or self.options.keep_going) :
                self.logger.info("Building " + component + " in " + builddir)
                self.logger.info("Build: make " + str(make_flags[comp_key][build]))
                buildrc = self.make(component, srcdir, builddir,
                                    make_flags[comp_key][build],
                                    make_env[comp_key][build])

                if (buildrc == None) :
                    self.logger.info("[None] Failed to build " + component + " in " + installdir)

                if (buildrc == 0 or self.options.keep_going) :
                    self.logger.info("Testing " + component + " in " + builddir)
                    self.logger.info("Test: make "
                                     + str(make_check_flags[comp_key][build]))
                    testrc = self.make(component, srcdir, builddir,
                                       make_check_flags[comp_key][build],
                                       make_check_env[comp_key][build])

                    if (testrc == None) :
                        self.logger.info("[None] Failed to test " + component + " in " + installdir)

                    if ((testrc == 0  or self.options.keep_going)
                        and not self.options.no_install):
                        self.logger.info("Installing " + component + " in " + installdir)
                        self.make(component, srcdir, builddir,
                                  make_install_flags[comp_key][build],
                                  make_install_env[comp_key][build])
                    else :
                        self.logger.info("Failed testing " + component + " in " + installdir)

                else :
                    self.logger.info("Failed to build " + component + " in " + installdir)

            else :
                self.logger.info("Failed to configure " + component + " in " + installdir)

    def configure(self, component, srcdir, builddir, flags, env):
        prefix = self.component_abbrev[component.replace("-", "_")]

        self.logger.debug("Configure " + str(flags) + " " + str(srcdir) + " -> "
                          + str(builddir))

        configure_files = dict(
            llvm=[(srcdir + "/configure", builddir + "/Makefile")],
            dragonegg=[(None,None)])


        doconfig = False
        for conf, mf in configure_files[component.replace("-", "_")]:
            if conf is None:
                # No configure necessary
                return 0

            if not os.path.exists(conf):
                self.logger.info("[" + prefix + "] Configure failed, no configure script " + conf)
                return -1

            if os.path.exists(conf) and os.path.exists(mf):
                confstat = os.stat(conf)
                makestat = os.stat(mf)
                if confstat.st_mtime > makestat.st_mtime:
                    doconfig = True
                    break
            else:
                doconfig = True
                break

        if not doconfig and not self.options.force_configure:
            return 0

        program = srcdir + "/configure"
        if not is_executable(program):
            self.logger.info("[" + prefix + "] Configure failed, cannot execute " + program)
            return -1

        args = [program]
        args += ["--verbose"]
        args += flags
        return self.execute(args, builddir, env, component)

    def make(self, component, srcdir, builddir, flags, env):
        program = find_executable("make")
        if program is None:
            raise ExecutableNotFound

        if not is_executable(program):
            raise FileNotExecutable

        args = [program]
        args += flags
        return self.execute(args, builddir, env, component)

# Global constants
build_abbrev = dict(debug="dbg", release="opt", paranoid="par")
components = ["llvm", "dragonegg"]

# Parse options
parser = optparse.OptionParser(version="%prog 1.0")
add_options(parser)
(options, args) = parser.parse_args()
check_options(parser, options, build_abbrev.keys());

if options.verbose:
    logging.basicConfig(level=logging.DEBUG,
                        format='%(name)-13s: %(message)s')
else:
    logging.basicConfig(level=logging.INFO,
                        format='%(name)-13s: %(message)s')

source_abbrev = get_path_abbrevs(set(options.src))

work_queue = queue.Queue()

jobs = options.jobs // options.threads
if jobs == 0:
    jobs = 1

numthreads = options.threads

logging.getLogger().info("Building with " + str(options.jobs) + " jobs and "
                         + str(numthreads) + " threads using " + str(jobs)
                         + " make jobs")

logging.getLogger().info("CC  = " + str(options.cc))
logging.getLogger().info("CXX = " + str(options.cxx))

for t in range(numthreads):
    builder = Builder(work_queue, jobs,
                      build_abbrev, source_abbrev,
                      options)
    builder.daemon = True
    builder.start()

for build in set(options.build):
    for source in set(options.src):
        work_queue.put((source, build))

work_queue.join()
