func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err error) {
	cleanSource(paths, "tmp", "routes")
	var sourceInfo *model.SourceInfo
	if c.HistoricBuildMode {
		sourceInfo, err = parser.ProcessSource(paths)
	} else {
		sourceInfo, err = parser2.ProcessSource(paths)
	}
	if err != nil {
		return
	}
	if dbImportPath, found := paths.Config.String("db.import"); found {
		sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, strings.Split(dbImportPath, ",")...)
	}
	controllers := sourceInfo.ControllerSpecs()
	sort.Stable(ByString(controllers))
	templateArgs := map[string]interface{}{
		"ImportPath":     paths.ImportPath,
		"Controllers":    controllers,
		"ValidationKeys": sourceInfo.ValidationKeys,
		"ImportPaths":    calcImportAliases(sourceInfo),
		"TestSuites":     sourceInfo.TestSuites(),
	}
	cleanSource(paths, "tmp", "routes")
	if err = genSource(paths, "tmp", "main.go", RevelMainTemplate, templateArgs); err != nil {
		return
	}
	if err = genSource(paths, filepath.Join("tmp", "run"), "run.go", RevelRunTemplate, templateArgs); err != nil {
		return
	}
	if err = genSource(paths, "routes", "routes.go", RevelRoutesTemplate, templateArgs); err != nil {
		return
	}
	buildTags := paths.Config.StringDefault("build.tags", "")
	goPath, err := exec.LookPath("go")
	if err != nil {
		utils.Logger.Fatal("Go executable not found in PATH.")
	}
	binName := filepath.Join("target", "app", paths.ImportPath, filepath.Base(paths.BasePath))
	goos := runtime.GOOS
	if goosEnv := os.Getenv("GOOS"); goosEnv != "" {
		goos = goosEnv
	}
	if goos == "windows" {
		binName += ".exe"
	}
	gotten := make(map[string]struct{})
	contains := func(s []string, e string) bool {
		for _, a := range s {
			if a == e {
				return true
			}
		}
		return false
	}
	if len(c.GoModFlags) > 0 {
		for _, gomod := range c.GoModFlags {
			goModCmd := exec.Command(goPath, append([]string{"mod"}, strings.Split(gomod, " ")...)...)
			utils.CmdInit(goModCmd, !c.Vendored, c.AppPath)
			output, err := goModCmd.CombinedOutput()
			utils.Logger.Info("Gomod applied ", "output", string(output))
			if err != nil {
				utils.Logger.Error("Gomod Failed continuing ", "error", err, "output", string(output))
			}
		}
	}
	for {
		appVersion := getAppVersion(paths)
		if appVersion == "" {
			appVersion = "noVersionProvided"
		}
		buildTime := time.Now().UTC().Format(time.RFC3339)
		versionLinkerFlags := fmt.Sprintf("-X '%s/app.AppVersion=%s' -X '%s/app.BuildTime=%s'",
			paths.ImportPath, appVersion, paths.ImportPath, buildTime)
		flags := []string{}
		if len(c.BuildFlags) == 0 {
			flags = []string{
				"build",
				"-ldflags", versionLinkerFlags,
				"-tags", buildTags,
				"-o", binName}
		} else {
			if !contains(c.BuildFlags, "build") {
				flags = []string{"build"}
			}
			if !contains(flags, "-ldflags") {
				ldflags := "-ldflags= " + versionLinkerFlags
				for i := range c.BuildFlags {
					ldflags += " -X '" + c.BuildFlags[i] + "'"
				}
				flags = append(flags, ldflags)
			}
			if !contains(flags, "-tags") && buildTags != "" {
				flags = append(flags, "-tags", buildTags)
			}
			if !contains(flags, "-o") {
				flags = append(flags, "-o", binName)
			}
		}
		flags = append(flags, path.Join(paths.ImportPath, "app", "tmp"))
		buildCmd := exec.Command(goPath, flags...)
		if !c.Vendored {
			gopath := c.GoPath
			for _, o := range paths.ModulePathMap {
				gopath += string(filepath.ListSeparator) + o.Path
			}
			buildCmd.Env = append(os.Environ(),
				"GOPATH=" + gopath,
			)
		}
		utils.CmdInit(buildCmd, !c.Vendored, c.AppPath)
		utils.Logger.Info("Exec:", "args", buildCmd.Args, "working dir", buildCmd.Dir)
		output, err := buildCmd.CombinedOutput()
		if err == nil {
			utils.Logger.Info("Build successful continuing")
			return NewApp(binName, paths, sourceInfo.PackageMap), nil
		}
		stOutput := string(output)
		utils.Logger.Infof("Got error on build of app %s", stOutput)
		matches := importErrorPattern.FindAllStringSubmatch(stOutput, -1)
		utils.Logger.Info("Build failed checking for missing imports", "message", stOutput, "missing_imports", len(matches))
		if matches == nil {
			utils.Logger.Info("Build failed no missing imports", "message", stOutput)
			return nil, newCompileError(paths, output)
		}
		utils.Logger.Warn("Detected missing packages, importing them", "packages", len(matches))
		for _, match := range matches {
			pkgName := match[1]
			utils.Logger.Info("Trying to import ", "package", pkgName)
			if _, alreadyTried := gotten[pkgName]; alreadyTried {
				utils.Logger.Error("Failed to import ", "package", pkgName)
				return nil, newCompileError(paths, output)
			}
			gotten[pkgName] = struct{}{}
			if err := c.PackageResolver(pkgName); err != nil {
				utils.Logger.Error("Unable to resolve package", "package", pkgName, "error", err)
				return nil, newCompileError(paths, []byte(err.Error()))
			}
		}
	}
	utils.Logger.Fatal("Not reachable")
	return nil, nil
}
Build the app:
1. Generate the the main.go file.
2. Run the appropriate "go build" command.
Requires that revel.Init has been called previously.
Returns the path to the built binary, and an error if there was a problem building it.
package harness
import (
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/revel/cmd/model"
	_ "github.com/revel/cmd/parser"
	"github.com/revel/cmd/utils"
	"github.com/revel/cmd/parser2"
	"github.com/revel/cmd/parser"
)
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
type ByString []*model.TypeInfo
func (c ByString) Len() int {
	return len(c)
}
func (c ByString) Swap(i, j int) {
	c[i], c[j] = c[j], c[i]
}
func (c ByString) Less(i, j int) bool {
	return c[i].String() < c[j].String()
}