// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Major workhorse of rustbuild, definition and dependencies between stages of
//! the copmile.
//!
//! The primary purpose of this module is to define the various `Step`s of
//! execution of the build. Each `Step` has a corresponding `Source` indicating
//! what it's actually doing along with a number of dependencies which must be
//! executed first.
//!
//! This module will take the CLI as input and calculate the steps required for
//! the build requested, ensuring that all intermediate pieces are in place.
//! Essentially this module is a `make`-replacement, but not as good.

use std::collections::HashSet;

use {Build, Compiler};

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub struct Step<'a> {
    pub src: Source<'a>,
    pub target: &'a str,
}

/// Macro used to iterate over all targets that are recognized by the build
/// system.
///
/// Whenever a new step is added it will involve adding an entry here, updating
/// the dependencies section below, and then adding an implementation of the
/// step in `build/mod.rs`.
///
/// This macro takes another macro as an argument and then calls that macro with
/// all steps that the build system knows about.
macro_rules! targets {
    ($m:ident) => {
        $m! {
            // Step representing building the stageN compiler. This is just the
            // compiler executable itself, not any of the support libraries
            (rustc, Rustc { stage: u32 }),

            // Steps for the two main cargo builds. These are parameterized over
            // the compiler which is producing the artifact.
            (libstd, Libstd { compiler: Compiler<'a> }),
            (libtest, Libtest { compiler: Compiler<'a> }),
            (librustc, Librustc { compiler: Compiler<'a> }),

            // Links the target produced by the compiler provided into the
            // host's directory also provided.
            (libstd_link, LibstdLink {
                compiler: Compiler<'a>,
                host: &'a str
            }),
            (libtest_link, LibtestLink {
                compiler: Compiler<'a>,
                host: &'a str
            }),
            (librustc_link, LibrustcLink {
                compiler: Compiler<'a>,
                host: &'a str
            }),

            // Various tools that we can build as part of the build.
            (tool_linkchecker, ToolLinkchecker { stage: u32 }),
            (tool_rustbook, ToolRustbook { stage: u32 }),
            (tool_error_index, ToolErrorIndex { stage: u32 }),
            (tool_cargotest, ToolCargoTest { stage: u32 }),
            (tool_tidy, ToolTidy { stage: u32 }),
            (tool_compiletest, ToolCompiletest { stage: u32 }),

            // Steps for long-running native builds. Ideally these wouldn't
            // actually exist and would be part of build scripts, but for now
            // these are here.
            //
            // There aren't really any parameters to this, but empty structs
            // with braces are unstable so we just pick something that works.
            (llvm, Llvm { _dummy: () }),
            (compiler_rt, CompilerRt { _dummy: () }),
            (test_helpers, TestHelpers { _dummy: () }),
            (debugger_scripts, DebuggerScripts { stage: u32 }),

            // Steps for various pieces of documentation that we can generate,
            // the 'doc' step is just a pseudo target to depend on a bunch of
            // others.
            (doc, Doc { stage: u32 }),
            (doc_book, DocBook { stage: u32 }),
            (doc_nomicon, DocNomicon { stage: u32 }),
            (doc_style, DocStyle { stage: u32 }),
            (doc_standalone, DocStandalone { stage: u32 }),
            (doc_std, DocStd { stage: u32 }),
            (doc_test, DocTest { stage: u32 }),
            (doc_rustc, DocRustc { stage: u32 }),
            (doc_error_index, DocErrorIndex { stage: u32 }),

            // Steps for running tests. The 'check' target is just a pseudo
            // target to depend on a bunch of others.
            (check, Check { stage: u32, compiler: Compiler<'a> }),
            (check_target, CheckTarget { stage: u32, compiler: Compiler<'a> }),
            (check_linkcheck, CheckLinkcheck { stage: u32 }),
            (check_cargotest, CheckCargoTest { stage: u32 }),
            (check_tidy, CheckTidy { stage: u32 }),
            (check_rpass, CheckRPass { compiler: Compiler<'a> }),
            (check_rpass_full, CheckRPassFull { compiler: Compiler<'a> }),
            (check_rpass_valgrind, CheckRPassValgrind { compiler: Compiler<'a> }),
            (check_rfail, CheckRFail { compiler: Compiler<'a> }),
            (check_rfail_full, CheckRFailFull { compiler: Compiler<'a> }),
            (check_cfail, CheckCFail { compiler: Compiler<'a> }),
            (check_cfail_full, CheckCFailFull { compiler: Compiler<'a> }),
            (check_pfail, CheckPFail { compiler: Compiler<'a> }),
            (check_pretty, CheckPretty { compiler: Compiler<'a> }),
            (check_pretty_rpass, CheckPrettyRPass { compiler: Compiler<'a> }),
            (check_pretty_rpass_full, CheckPrettyRPassFull { compiler: Compiler<'a> }),
            (check_pretty_rfail, CheckPrettyRFail { compiler: Compiler<'a> }),
            (check_pretty_rfail_full, CheckPrettyRFailFull { compiler: Compiler<'a> }),
            (check_pretty_rpass_valgrind, CheckPrettyRPassValgrind { compiler: Compiler<'a> }),
            (check_codegen, CheckCodegen { compiler: Compiler<'a> }),
            (check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }),
            (check_incremental, CheckIncremental { compiler: Compiler<'a> }),
            (check_ui, CheckUi { compiler: Compiler<'a> }),
            (check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }),
            (check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }),
            (check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }),
            (check_docs, CheckDocs { compiler: Compiler<'a> }),
            (check_error_index, CheckErrorIndex { compiler: Compiler<'a> }),
            (check_rmake, CheckRMake { compiler: Compiler<'a> }),
            (check_crate_std, CheckCrateStd { compiler: Compiler<'a> }),
            (check_crate_test, CheckCrateTest { compiler: Compiler<'a> }),
            (check_crate_rustc, CheckCrateRustc { compiler: Compiler<'a> }),

            // Distribution targets, creating tarballs
            (dist, Dist { stage: u32 }),
            (dist_docs, DistDocs { stage: u32 }),
            (dist_mingw, DistMingw { _dummy: () }),
            (dist_rustc, DistRustc { stage: u32 }),
            (dist_std, DistStd { compiler: Compiler<'a> }),

            // Misc targets
            (android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }),
        }
    }
}

// Define the `Source` enum by iterating over all the steps and peeling out just
// the types that we want to define.

macro_rules! item { ($a:item) => ($a) }

macro_rules! define_source {
    ($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
        item! {
            #[derive(Hash, Eq, PartialEq, Clone, Debug)]
            pub enum Source<'a> {
                $($name { $($args)* }),*
            }
        }
    }
}

targets!(define_source);

/// Calculate a list of all steps described by `build`.
///
/// This will inspect the flags passed in on the command line and use that to
/// build up a list of steps to execute. These steps will then be transformed
/// into a topologically sorted list which when executed left-to-right will
/// correctly sequence the entire build.
pub fn all(build: &Build) -> Vec<Step> {
    let mut ret = Vec::new();
    let mut all = HashSet::new();
    for target in top_level(build) {
        fill(build, &target, &mut ret, &mut all);
    }
    return ret;

    fn fill<'a>(build: &'a Build,
                target: &Step<'a>,
                ret: &mut Vec<Step<'a>>,
                set: &mut HashSet<Step<'a>>) {
        if set.insert(target.clone()) {
            for dep in target.deps(build) {
                fill(build, &dep, ret, set);
            }
            ret.push(target.clone());
        }
    }
}

/// Determines what top-level targets are requested as part of this build,
/// returning them as a list.
fn top_level(build: &Build) -> Vec<Step> {
    let mut targets = Vec::new();
    let stage = build.flags.stage.unwrap_or(2);

    let host = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.host.iter().next()
                     .unwrap_or(&build.config.build),
    };
    let target = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.target.iter().next().map(|x| &x[..])
                     .unwrap_or(host.target)
    };

    // First, try to find steps on the command line.
    add_steps(build, stage, &host, &target, &mut targets);

    // If none are specified, then build everything.
    if targets.len() == 0 {
        let t = Step {
            src: Source::Llvm { _dummy: () },
            target: &build.config.build,
        };
        if build.config.docs {
          targets.push(t.doc(stage));
        }
        for host in build.config.host.iter() {
            if !build.flags.host.contains(host) {
                continue
            }
            let host = t.target(host);
            if host.target == build.config.build {
                targets.push(host.librustc(host.compiler(stage)));
            } else {
                targets.push(host.librustc_link(t.compiler(stage), host.target));
            }
            for target in build.config.target.iter() {
                if !build.flags.target.contains(target) {
                    continue
                }

                if host.target == build.config.build {
                    targets.push(host.target(target)
                                     .libtest(host.compiler(stage)));
                } else {
                    targets.push(host.target(target)
                                     .libtest_link(t.compiler(stage), host.target));
                }
            }
        }
    }

    return targets

}

fn add_steps<'a>(build: &'a Build,
                 stage: u32,
                 host: &Step<'a>,
                 target: &Step<'a>,
                 targets: &mut Vec<Step<'a>>) {
    struct Context<'a> {
        stage: u32,
        compiler: Compiler<'a>,
        _dummy: (),
        host: &'a str,
    }
    for step in build.flags.step.iter() {

        // The macro below insists on hygienic access to all local variables, so
        // we shove them all in a struct and subvert hygiene by accessing struct
        // fields instead,
        let cx = Context {
            stage: stage,
            compiler: host.target(&build.config.build).compiler(stage),
            _dummy: (),
            host: host.target,
        };
        macro_rules! add_step {
            ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => ({$(
                let name = stringify!($short).replace("_", "-");
                if &step[..] == &name[..] {
                    targets.push(target.$short($(cx.$arg),*));
                    continue
                }
                drop(name);
            )*})
        }

        targets!(add_step);

        panic!("unknown step: {}", step);
    }
}

macro_rules! constructors {
    ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
        fn $short(&self, $($arg: $t),*) -> Step<'a> {
            Step {
                src: Source::$name { $($arg: $arg),* },
                target: self.target,
            }
        }
    )*}
}

impl<'a> Step<'a> {
    fn compiler(&self, stage: u32) -> Compiler<'a> {
        Compiler::new(stage, self.target)
    }

    fn target(&self, target: &'a str) -> Step<'a> {
        Step { target: target, src: self.src.clone() }
    }

    // Define ergonomic constructors for each step defined above so they can be
    // easily constructed.
    targets!(constructors);

    /// Mapping of all dependencies for rustbuild.
    ///
    /// This function receives a step, the build that we're building for, and
    /// then returns a list of all the dependencies of that step.
    pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
        match self.src {
            Source::Rustc { stage: 0 } => {
                Vec::new()
            }
            Source::Rustc { stage } => {
                let compiler = Compiler::new(stage - 1, &build.config.build);
                vec![self.librustc(compiler)]
            }
            Source::Librustc { compiler } => {
                vec![self.libtest(compiler), self.llvm(())]
            }
            Source::Libtest { compiler } => {
                vec![self.libstd(compiler)]
            }
            Source::Libstd { compiler } => {
                vec![self.compiler_rt(()),
                     self.rustc(compiler.stage).target(compiler.host)]
            }
            Source::LibrustcLink { compiler, host } => {
                vec![self.librustc(compiler),
                     self.libtest_link(compiler, host)]
            }
            Source::LibtestLink { compiler, host } => {
                vec![self.libtest(compiler), self.libstd_link(compiler, host)]
            }
            Source::LibstdLink { compiler, host } => {
                vec![self.libstd(compiler),
                     self.target(host).rustc(compiler.stage)]
            }
            Source::CompilerRt { _dummy } => Vec::new(),
            Source::Llvm { _dummy } => Vec::new(),
            Source::TestHelpers { _dummy } => Vec::new(),
            Source::DebuggerScripts { stage: _ } => Vec::new(),

            // Note that all doc targets depend on artifacts from the build
            // architecture, not the target (which is where we're generating
            // docs into).
            Source::DocStd { stage } => {
                let compiler = self.target(&build.config.build).compiler(stage);
                vec![self.libstd(compiler)]
            }
            Source::DocTest { stage } => {
                let compiler = self.target(&build.config.build).compiler(stage);
                vec![self.libtest(compiler)]
            }
            Source::DocBook { stage } |
            Source::DocNomicon { stage } |
            Source::DocStyle { stage } => {
                vec![self.target(&build.config.build).tool_rustbook(stage)]
            }
            Source::DocErrorIndex { stage } => {
                vec![self.target(&build.config.build).tool_error_index(stage)]
            }
            Source::DocStandalone { stage } => {
                vec![self.target(&build.config.build).rustc(stage)]
            }
            Source::DocRustc { stage } => {
                vec![self.doc_test(stage)]
            }
            Source::Doc { stage } => {
                let mut deps = vec![
                    self.doc_book(stage), self.doc_nomicon(stage),
                    self.doc_style(stage), self.doc_standalone(stage),
                    self.doc_std(stage),
                    self.doc_error_index(stage),
                ];

                if build.config.compiler_docs {
                    deps.push(self.doc_rustc(stage));
                }

                deps
            }
            Source::Check { stage, compiler } => {
                // Check is just a pseudo step which means check all targets,
                // so just depend on checking all targets.
                build.config.target.iter().map(|t| {
                    self.target(t).check_target(stage, compiler)
                }).collect()
            }
            Source::CheckTarget { stage, compiler } => {
                // CheckTarget here means run all possible test suites for this
                // target. Most of the time, however, we can't actually run
                // anything if we're not the build triple as we could be cross
                // compiling.
                //
                // As a result, the base set of targets here is quite stripped
                // down from the standard set of targets. These suites have
                // their own internal logic to run in cross-compiled situations
                // if they'll run at all. For example compiletest knows that
                // when testing Android targets we ship artifacts to the
                // emulator.
                //
                // When in doubt the rule of thumb for adding to this list is
                // "should this test suite run on the android bot?"
                let mut base = vec![
                    self.check_rpass(compiler),
                    self.check_rfail(compiler),
                    self.check_crate_std(compiler),
                    self.check_crate_test(compiler),
                    self.check_debuginfo(compiler),
                    self.dist(stage),
                ];

                // If we're testing the build triple, then we know we can
                // actually run binaries and such, so we run all possible tests
                // that we know about.
                if self.target == build.config.build {
                    base.extend(vec![
                        // docs-related
                        self.check_docs(compiler),
                        self.check_error_index(compiler),
                        self.check_rustdoc(compiler),

                        // UI-related
                        self.check_cfail(compiler),
                        self.check_pfail(compiler),
                        self.check_ui(compiler),

                        // codegen-related
                        self.check_incremental(compiler),
                        self.check_codegen(compiler),
                        self.check_codegen_units(compiler),

                        // misc compiletest-test suites
                        self.check_rpass_full(compiler),
                        self.check_rfail_full(compiler),
                        self.check_cfail_full(compiler),
                        self.check_pretty_rpass_full(compiler),
                        self.check_pretty_rfail_full(compiler),
                        self.check_rpass_valgrind(compiler),
                        self.check_rmake(compiler),
                        self.check_mir_opt(compiler),

                        // crates
                        self.check_crate_rustc(compiler),

                        // pretty
                        self.check_pretty(compiler),
                        self.check_pretty_rpass(compiler),
                        self.check_pretty_rfail(compiler),
                        self.check_pretty_rpass_valgrind(compiler),

                        // misc
                        self.check_linkcheck(stage),
                        self.check_tidy(stage),
                    ]);
                }
                return base
            }
            Source::CheckLinkcheck { stage } => {
                vec![self.tool_linkchecker(stage), self.doc(stage)]
            }
            Source::CheckCargoTest { stage } => {
                vec![self.tool_cargotest(stage),
                     self.librustc(self.compiler(stage))]
            }
            Source::CheckTidy { stage } => {
                vec![self.tool_tidy(stage)]
            }
            Source::CheckMirOpt { compiler} |
            Source::CheckPrettyRPass { compiler } |
            Source::CheckPrettyRFail { compiler } |
            Source::CheckRFail { compiler } |
            Source::CheckPFail { compiler } |
            Source::CheckCodegen { compiler } |
            Source::CheckCodegenUnits { compiler } |
            Source::CheckIncremental { compiler } |
            Source::CheckUi { compiler } |
            Source::CheckRustdoc { compiler } |
            Source::CheckPretty { compiler } |
            Source::CheckCFail { compiler } |
            Source::CheckRPassValgrind { compiler } |
            Source::CheckRPass { compiler } => {
                let mut base = vec![
                    self.libtest(compiler),
                    self.target(compiler.host).tool_compiletest(compiler.stage),
                    self.test_helpers(()),
                ];
                if self.target.contains("android") {
                    base.push(self.android_copy_libs(compiler));
                }
                base
            }
            Source::CheckDebuginfo { compiler } => {
                vec![
                    self.libtest(compiler),
                    self.target(compiler.host).tool_compiletest(compiler.stage),
                    self.test_helpers(()),
                    self.debugger_scripts(compiler.stage),
                ]
            }
            Source::CheckRPassFull { compiler } |
            Source::CheckRFailFull { compiler } |
            Source::CheckCFailFull { compiler } |
            Source::CheckPrettyRPassFull { compiler } |
            Source::CheckPrettyRFailFull { compiler } |
            Source::CheckPrettyRPassValgrind { compiler } |
            Source::CheckRMake { compiler } => {
                vec![self.librustc(compiler),
                     self.target(compiler.host).tool_compiletest(compiler.stage)]
            }
            Source::CheckDocs { compiler } => {
                vec![self.libstd(compiler)]
            }
            Source::CheckErrorIndex { compiler } => {
                vec![self.libstd(compiler),
                     self.target(compiler.host).tool_error_index(compiler.stage)]
            }
            Source::CheckCrateStd { compiler } => {
                vec![self.libtest(compiler)]
            }
            Source::CheckCrateTest { compiler } => {
                vec![self.libtest(compiler)]
            }
            Source::CheckCrateRustc { compiler } => {
                vec![self.libtest(compiler)]
            }

            Source::ToolLinkchecker { stage } |
            Source::ToolTidy { stage } => {
                vec![self.libstd(self.compiler(stage))]
            }
            Source::ToolErrorIndex { stage } |
            Source::ToolRustbook { stage } => {
                vec![self.librustc(self.compiler(stage))]
            }
            Source::ToolCargoTest { stage } => {
                vec![self.libstd(self.compiler(stage))]
            }
            Source::ToolCompiletest { stage } => {
                vec![self.libtest(self.compiler(stage))]
            }

            Source::DistDocs { stage } => vec![self.doc(stage)],
            Source::DistMingw { _dummy: _ } => Vec::new(),
            Source::DistRustc { stage } => {
                vec![self.rustc(stage)]
            }
            Source::DistStd { compiler } => {
                // We want to package up as many target libraries as possible
                // for the `rust-std` package, so if this is a host target we
                // depend on librustc and otherwise we just depend on libtest.
                if build.config.host.iter().any(|t| t == self.target) {
                    vec![self.librustc(compiler)]
                } else {
                    vec![self.libtest(compiler)]
                }
            }

            Source::Dist { stage } => {
                let mut base = Vec::new();

                for host in build.config.host.iter() {
                    let host = self.target(host);
                    base.push(host.dist_rustc(stage));
                    if host.target.contains("windows-gnu") {
                        base.push(host.dist_mingw(()));
                    }

                    let compiler = self.compiler(stage);
                    for target in build.config.target.iter() {
                        let target = self.target(target);
                        if build.config.docs {
                            base.push(target.dist_docs(stage));
                        }
                        base.push(target.dist_std(compiler));
                    }
                }
                return base
            }

            Source::AndroidCopyLibs { compiler } => {
                vec![self.libtest(compiler)]
            }
        }
    }
}
