/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package builder

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"

	"mynewt.apache.org/newt/newt/image"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/repo"
	"mynewt.apache.org/newt/newt/resolve"
	"mynewt.apache.org/newt/newt/symbol"
	"mynewt.apache.org/newt/newt/syscfg"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

type Builder struct {
	PkgMap map[*resolve.ResolvePackage]*BuildPackage

	apiMap           map[string]*BuildPackage
	appPkg           *BuildPackage
	bspPkg           *BuildPackage
	compilerPkg      *BuildPackage
	targetPkg        *BuildPackage
	testPkg          *BuildPackage
	compilerInfo     *toolchain.CompilerInfo
	targetBuilder    *TargetBuilder
	cfg              syscfg.Cfg
	linkerScripts    []string
	buildName        string
	linkElf          string
	injectedSettings map[string]string
}

func NewBuilder(
	t *TargetBuilder,
	buildName string,
	rpkgs []*resolve.ResolvePackage,
	apiMap map[string]*resolve.ResolvePackage,
	cfg syscfg.Cfg) (*Builder, error) {

	b := &Builder{
		PkgMap: make(map[*resolve.ResolvePackage]*BuildPackage, len(rpkgs)),
		cfg:    cfg,

		buildName:        buildName,
		apiMap:           make(map[string]*BuildPackage, len(apiMap)),
		linkElf:          "",
		targetBuilder:    t,
		injectedSettings: map[string]string{},
	}

	for _, rpkg := range rpkgs {
		if _, err := b.addPackage(rpkg); err != nil {
			return nil, err
		}
	}

	// Create a pseudo build package for the generated sysinit code.
	if _, err := b.addSysinitBpkg(); err != nil {
		return nil, err
	}

	for api, rpkg := range apiMap {
		bpkg := b.PkgMap[rpkg]
		if bpkg == nil {
			for _, rpkg := range b.sortedRpkgs() {
				log.Debugf("    * %s", rpkg.Lpkg.Name())
			}
			return nil, util.FmtNewtError(
				"Unexpected unsatisfied API: %s; required by: %s", api,
				rpkg.Lpkg.Name())
		}

		b.apiMap[api] = bpkg
	}

	return b, nil
}

func (b *Builder) addPackage(rpkg *resolve.ResolvePackage) (
	*BuildPackage, error) {

	// Don't allow nil entries to the map
	if rpkg == nil {
		panic("Cannot add nil package builder map")
	}

	bpkg := b.PkgMap[rpkg]
	if bpkg == nil {
		bpkg = NewBuildPackage(rpkg)

		switch bpkg.rpkg.Lpkg.Type() {
		case pkg.PACKAGE_TYPE_APP:
			if b.appPkg != nil {
				return nil, pkgTypeConflictErr(b.appPkg, bpkg)
			}
			b.appPkg = bpkg

		case pkg.PACKAGE_TYPE_BSP:
			if b.bspPkg != nil {
				return nil, pkgTypeConflictErr(b.bspPkg, bpkg)
			}
			b.bspPkg = bpkg

		case pkg.PACKAGE_TYPE_COMPILER:
			if b.compilerPkg != nil {
				return nil, pkgTypeConflictErr(b.compilerPkg, bpkg)
			}
			b.compilerPkg = bpkg

		case pkg.PACKAGE_TYPE_TARGET:
			if b.targetPkg != nil {
				return nil, pkgTypeConflictErr(b.targetPkg, bpkg)
			}
			b.targetPkg = bpkg
		}

		b.PkgMap[rpkg] = bpkg
	}

	return bpkg, nil
}

func pkgTypeConflictErr(p1 *BuildPackage, p2 *BuildPackage) error {
	return util.FmtNewtError("Two %s packages in build: %s, %s",
		pkg.PackageTypeNames[p1.rpkg.Lpkg.Type()],
		p1.rpkg.Lpkg.Name(),
		p2.rpkg.Lpkg.Name())
}

// Recursively compiles all the .c and .s files in the specified directory.
// Architecture-specific files are also compiled.
func collectCompileEntriesDir(srcDir string, c *toolchain.Compiler,
	arch string, ignDirs []string) ([]toolchain.CompilerJob, error) {

	// Quietly succeed if the source directory doesn't exist.
	if util.NodeNotExist(srcDir) {
		return nil, nil
	}

	util.StatusMessage(util.VERBOSITY_VERBOSE,
		"Compiling src in base directory: %s\n", srcDir)

	// Start from the source directory.
	c.SetSrcDir(srcDir)

	// Ignore architecture-specific source files for now.  Use a temporary
	// string slice here so that the "arch" directory is not ignored in the
	// subsequent architecture-specific compile phase.
	ignDirsArch := append(ignDirs, "arch")

	entries := []toolchain.CompilerJob{}

	subEntries, err := c.RecursiveCollectEntries(toolchain.COMPILER_TYPE_C,
		ignDirsArch)
	if err != nil {
		return nil, err
	}
	entries = append(entries, subEntries...)

	// Compile CPP files
	subEntries, err = c.RecursiveCollectEntries(toolchain.COMPILER_TYPE_CPP,
		ignDirsArch)
	if err != nil {
		return nil, err
	}
	entries = append(entries, subEntries...)

	// Copy in pre-compiled library files
	subEntries, err = c.RecursiveCollectEntries(
		toolchain.COMPILER_TYPE_ARCHIVE, ignDirsArch)
	if err != nil {
		return nil, err
	}
	entries = append(entries, subEntries...)

	archDir := srcDir + "/arch/" + arch + "/"
	if util.NodeExist(archDir) {
		util.StatusMessage(util.VERBOSITY_VERBOSE,
			"Compiling architecture specific src pkgs in directory: %s\n",
			archDir)
		c.SetSrcDir(archDir)

		// Compile C source.
		subEntries, err = c.RecursiveCollectEntries(
			toolchain.COMPILER_TYPE_C, ignDirs)
		if err != nil {
			return nil, err
		}
		entries = append(entries, subEntries...)

		// Compile CPP source
		subEntries, err = c.RecursiveCollectEntries(
			toolchain.COMPILER_TYPE_CPP, ignDirs)
		if err != nil {
			return nil, err
		}
		entries = append(entries, subEntries...)

		// Compile assembly source (only architecture-specific).
		subEntries, err = c.RecursiveCollectEntries(
			toolchain.COMPILER_TYPE_ASM, ignDirs)
		if err != nil {
			return nil, err
		}
		entries = append(entries, subEntries...)

		// Copy in pre-compiled library files
		subEntries, err = c.RecursiveCollectEntries(
			toolchain.COMPILER_TYPE_ARCHIVE, ignDirs)
		if err != nil {
			return nil, err
		}
		entries = append(entries, subEntries...)
	}

	return entries, nil
}

// Determines which build profile to use when building the specified package.
// 1. If the package specifies a "pkg.build_profile" value, that is returned:
//
//      pkg.build_profile: debug
//
// 2. Else if the target specifies this package in its
//    "target.package_profiles" map, that value is returned:
//
//      target.package_profiles:
//          'apps/blinky': debug
//          '@apache-mynewt-core/sys/log/full': debug
//
// 3. Else, "" is returned (falls back to the target's general build profile).
func (b *Builder) buildProfileFor(bpkg *BuildPackage) string {
	bp := bpkg.BuildProfile(b)
	if bp != "" {
		return bp
	}

	tgt := b.targetBuilder.GetTarget()
	return tgt.PkgProfiles[bpkg.rpkg.Lpkg.FullName()]
}

func (b *Builder) newCompiler(bpkg *BuildPackage,
	dstDir string) (*toolchain.Compiler, error) {

	var buildProfile string
	if bpkg != nil {
		buildProfile = b.buildProfileFor(bpkg)
	}

	c, err := b.targetBuilder.NewCompiler(dstDir, buildProfile)
	if err != nil {
		return nil, err
	}

	c.AddInfo(b.compilerInfo)

	if bpkg != nil {
		log.Debugf("Generating build flags for package %s",
			bpkg.rpkg.Lpkg.FullName())
		ci, err := bpkg.CompilerInfo(b)
		if err != nil {
			return nil, err
		}
		c.AddInfo(ci)
	}

	return c, nil
}

func (b *Builder) collectCompileEntriesBpkg(bpkg *BuildPackage) (
	[]toolchain.CompilerJob, error) {

	c, err := b.newCompiler(bpkg, b.PkgBinDir(bpkg))
	if err != nil {
		return nil, err
	}

	srcDirs := []string{}

	if len(bpkg.SourceDirectories) > 0 {
		for _, relDir := range bpkg.SourceDirectories {
			dir := bpkg.rpkg.Lpkg.BasePath() + "/" + relDir
			if util.NodeNotExist(dir) {
				return nil, util.NewNewtError(fmt.Sprintf(
					"Specified source directory %s, does not exist.",
					dir))
			}
			srcDirs = append(srcDirs, dir)
		}
	} else {
		srcDir := bpkg.rpkg.Lpkg.BasePath() + "/src"
		if util.NodeNotExist(srcDir) {
			// Nothing to compile.
			return nil, nil
		}

		srcDirs = append(srcDirs, srcDir)
	}

	entries := []toolchain.CompilerJob{}
	for _, dir := range srcDirs {
		subEntries, err := collectCompileEntriesDir(dir, c,
			b.targetBuilder.bspPkg.Arch, nil)
		if err != nil {
			return nil, err
		}

		entries = append(entries, subEntries...)
	}

	return entries, nil
}

func (b *Builder) CollectCompileEntriesBpkg(bpkg *BuildPackage) (
	[]toolchain.CompilerJob, error) {
	return b.collectCompileEntriesBpkg(bpkg)
}

func (b *Builder) createArchive(c *toolchain.Compiler,
	bpkg *BuildPackage) error {

	// Create a static library ("archive").
	c.SetSrcDir(bpkg.rpkg.Lpkg.RelativePath())
	archiveFile := b.ArchivePath(bpkg)
	if err := c.CompileArchive(archiveFile); err != nil {
		return err
	}

	return nil
}

func (b *Builder) RemovePackages(cmn map[string]bool) error {
	for pkgName, _ := range cmn {
		for lp, bpkg := range b.PkgMap {
			if bpkg.rpkg.Lpkg.Name() == pkgName {
				delete(b.PkgMap, lp)
			}
		}
	}
	return nil
}

func (b *Builder) ExtractSymbolInfo() (error, *symbol.SymbolMap) {
	syms := symbol.NewSymbolMap()
	for _, bpkg := range b.PkgMap {
		err, sm := b.ParseObjectLibrary(bpkg)
		if err == nil {
			syms, err = (*syms).Merge(sm)
			if err != nil {
				return err, nil
			}
		}
	}
	return nil, syms
}

func (b *Builder) link(elfName string, linkerScripts []string,
	keepSymbols []string) error {

	c, err := b.newCompiler(b.appPkg, b.FileBinDir(elfName))
	if err != nil {
		return err
	}

	/* Always used the trimmed archive files. */
	pkgNames := []string{}

	for _, bpkg := range b.sortedBuildPackages() {
		archiveNames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a")
		for i, archiveName := range archiveNames {
			archiveNames[i] = filepath.ToSlash(archiveName)
		}
		pkgNames = append(pkgNames, archiveNames...)

		// Collect lflags from all constituent packages.  Discard everything
		// from the compiler info except lflags; that is all that is relevant
		// to the link command.
		ci, err := bpkg.CompilerInfo(b)
		if err != nil {
			return err
		}
		c.AddInfo(&toolchain.CompilerInfo{Lflags: ci.Lflags})
	}

	c.LinkerScripts = linkerScripts
	err = c.CompileElf(elfName, pkgNames, keepSymbols, b.linkElf)
	if err != nil {
		return err
	}

	return nil
}

// Populates the builder with all the packages that need to be built and
// configures each package's build settings.  After this function executes,
// packages are ready to be built.
func (b *Builder) PrepBuild() error {
	// Populate the base set of compiler flags.  Flags from the following
	// packages get applied to every source file:
	//     * target
	//     * app (if present)
	//     * bsp
	//     * compiler (not added here)
	//
	// In the case of conflicting flags, the higher priority package's flag
	// wins.  Package priorities are assigned as follows (highest priority
	// first):
	//     * target
	//     * app (if present)
	//     * bsp
	//     * <library package>
	//     * compiler
	baseCi := toolchain.NewCompilerInfo()

	// Target flags.
	log.Debugf("Generating build flags for target %s",
		b.targetPkg.rpkg.Lpkg.FullName())
	targetCi, err := b.targetPkg.CompilerInfo(b)
	if err != nil {
		return err
	}
	baseCi.AddCompilerInfo(targetCi)

	// App flags.
	if b.appPkg != nil {
		log.Debugf("Generating build flags for app %s",
			b.appPkg.rpkg.Lpkg.FullName())
		appCi, err := b.appPkg.CompilerInfo(b)
		if err != nil {
			return err
		}

		baseCi.AddCompilerInfo(appCi)
	}

	// Bsp flags.
	log.Debugf("Generating build flags for bsp %s",
		b.bspPkg.rpkg.Lpkg.FullName())
	bspCi, err := b.bspPkg.CompilerInfo(b)
	if err != nil {
		return err
	}

	// Define a cpp symbol indicating the BSP architecture, name of the
	// BSP and app.

	archName := b.targetBuilder.bspPkg.Arch
	bspCi.Cflags = append(bspCi.Cflags, "-DARCH_"+util.CIdentifier(archName))
	bspCi.Cflags = append(bspCi.Cflags, "-DARCH_NAME="+archName+"")

	if b.appPkg != nil {
		appName := filepath.Base(b.appPkg.rpkg.Lpkg.Name())
		bspCi.Cflags = append(bspCi.Cflags, "-DAPP_"+util.CIdentifier(appName))
		bspCi.Cflags = append(bspCi.Cflags, "-DAPP_NAME="+appName+"")
	}

	bspName := filepath.Base(b.bspPkg.rpkg.Lpkg.Name())
	bspCi.Cflags = append(bspCi.Cflags, "-DBSP_"+util.CIdentifier(bspName))
	bspCi.Cflags = append(bspCi.Cflags, "-DBSP_NAME="+bspName+"")

	baseCi.AddCompilerInfo(bspCi)

	// All packages have access to the generated code header directory.
	baseCi.Includes = append(baseCi.Includes,
		GeneratedIncludeDir(b.targetPkg.rpkg.Lpkg.Name()))

	// Let multiplatform libraries know that a Mynewt binary is being build.
	baseCi.Cflags = append(baseCi.Cflags, "-DMYNEWT=1")

	// Note: The compiler package's flags get added at the end, after the flags
	// for library package being built are calculated.
	b.compilerInfo = baseCi

	return nil
}

func (b *Builder) AddCompilerInfo(info *toolchain.CompilerInfo) {
	b.compilerInfo.AddCompilerInfo(info)
}

func (b *Builder) addSysinitBpkg() (*BuildPackage, error) {
	lpkg := pkg.NewLocalPackage(b.targetPkg.rpkg.Lpkg.Repo().(*repo.Repo),
		GeneratedBaseDir(b.targetPkg.rpkg.Lpkg.Name()))
	lpkg.SetName(pkg.ShortName(b.targetPkg.rpkg.Lpkg) + "-sysinit-" +
		b.buildName)
	lpkg.SetType(pkg.PACKAGE_TYPE_GENERATED)

	rpkg := resolve.NewResolvePkg(lpkg)
	return b.addPackage(rpkg)
}

// Runs build jobs while any remain.  On failure, signals the other workers to
// stop via the stop channel.  On error, the error object is signaled via the
// results channel.  On successful completion, nil is signaled via the results
// channel.
func buildWorker(
	id int,
	jobs <-chan toolchain.CompilerJob,
	stop chan struct{},
	results chan error) {

	// Execute each job until failure or until a stop is signalled.
	for {
		select {
		case s := <-stop:
			// Re-enqueue the stop signal for the other routines.
			stop <- s

			// Terminate this go routine.
			results <- nil
			return

		case j := <-jobs:
			if err := toolchain.RunJob(j); err != nil {
				// Stop the other routines.
				stop <- struct{}{}

				// Report the error back to the master thread and terminate.
				results <- err
				return
			}

		default:
			// Terminate this go routine.
			results <- nil
			return
		}
	}
}

func (b *Builder) Build() error {
	b.CleanArtifacts()

	// Build the packages alphabetically to ensure a consistent order.
	bpkgs := b.sortedBuildPackages()

	// Calculate the list of jobs.  Each record represents a single file that
	// needs to be compiled.
	entries := []toolchain.CompilerJob{}
	bpkgCompilerMap := map[*BuildPackage]*toolchain.Compiler{}
	for _, bpkg := range bpkgs {
		subEntries, err := b.collectCompileEntriesBpkg(bpkg)
		if err != nil {
			return err
		}
		entries = append(entries, subEntries...)

		if len(subEntries) > 0 {
			bpkgCompilerMap[bpkg] = subEntries[0].Compiler
		}
	}

	// Build each file in parallel.
	jobs := make(chan toolchain.CompilerJob, len(entries))
	defer close(jobs)

	stop := make(chan struct{}, newtutil.NewtNumJobs)
	defer close(stop)

	errors := make(chan error, newtutil.NewtNumJobs)
	defer close(errors)

	for _, entry := range entries {
		jobs <- entry
	}

	for i := 0; i < newtutil.NewtNumJobs; i++ {
		go buildWorker(i, jobs, stop, errors)
	}

	var err error
	for i := 0; i < newtutil.NewtNumJobs; i++ {
		subErr := <-errors
		if err == nil && subErr != nil {
			err = subErr
		}
	}
	if err != nil {
		return err
	}

	for _, bpkg := range bpkgs {
		c := bpkgCompilerMap[bpkg]
		if c != nil {
			if err := b.createArchive(c, bpkg); err != nil {
				return err
			}
		}
	}

	var compileCommands []toolchain.CompileCommand

	for _, bpkg := range bpkgs {
		c := bpkgCompilerMap[bpkg]
		if c != nil {
			compileCommands = append(compileCommands,
				c.GetCompileCommands()...)
		}
	}

	projectPath := interfaces.GetProject().Path() + "/"
	for i := range compileCommands {
		compileCommands[i].Directory = projectPath
	}

	cmdBytes, err := json.MarshalIndent(compileCommands, "", "    ")
	if err != nil {
		log.Error("Unable to encode compilation commands as JSON")
		return nil
	}

	cmdPath := b.CompileCmdsPath()
	errWrite := ioutil.WriteFile(cmdPath, cmdBytes, 0644)
	if errWrite != nil {
		return util.FmtNewtError(
			"Unable to write compile_commands.json file; reason: %s",
			errWrite.Error())
	}

	return nil
}

func (b *Builder) Link(linkerScripts []string) error {
	if err := b.link(b.AppElfPath(), linkerScripts, nil); err != nil {
		return err
	}
	return nil
}

func (b *Builder) KeepLink(
	linkerScripts []string, keepMap *symbol.SymbolMap) error {

	keepSymbols := make([]string, 0)

	if keepMap != nil {
		for _, info := range *keepMap {
			keepSymbols = append(keepSymbols, info.Name)
		}
	}
	if err := b.link(b.AppElfPath(), linkerScripts, keepSymbols); err != nil {
		return err
	}
	return nil
}

func (b *Builder) TentativeLink(linkerScripts []string) error {
	if err := b.link(b.AppTentativeElfPath(), linkerScripts, nil); err != nil {
		return err
	}
	return nil
}

func (b *Builder) pkgWithPath(path string) *BuildPackage {
	for _, bpkg := range b.PkgMap {
		if bpkg.rpkg.Lpkg.BasePath() == path {
			return bpkg
		}
	}

	return nil
}

func (b *Builder) FetchSymbolMap() (error, *symbol.SymbolMap) {
	loaderSm := symbol.NewSymbolMap()

	for _, bpkg := range b.PkgMap {
		err, sm := b.ParseObjectLibrary(bpkg)
		if err == nil {
			util.StatusMessage(util.VERBOSITY_VERBOSE,
				"Size of %s Loader Map %d\n", bpkg.rpkg.Lpkg.Name(), len(*sm))
			loaderSm, err = loaderSm.Merge(sm)
			if err != nil {
				return err, nil
			}
		}
	}

	return nil, loaderSm
}

func (b *Builder) GetTarget() *target.Target {
	return b.targetBuilder.GetTarget()
}

func (b *Builder) buildRomElf(common *symbol.SymbolMap) error {
	// check dependencies on the ROM ELF.  This is really dependent on
	// all of the .a files, but since we already depend on the loader
	// .as to build the initial elf, we only need to check the app .a
	c, err := b.targetBuilder.NewCompiler(b.AppElfPath(), "")
	d := toolchain.NewDepTracker(c)
	if err != nil {
		return err
	}

	archNames := []string{}

	// build the set of archive file names
	for _, bpkg := range b.PkgMap {
		archiveNames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a")
		archNames = append(archNames, archiveNames...)
	}

	bld, err := d.RomElfBuildRequired(b.AppLinkerElfPath(),
		b.AppElfPath(), archNames)
	if err != nil {
		return err
	}

	if !bld {
		return nil
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT,
		"Generating ROM elf \n")

	/* the linker needs these symbols kept for the split app
	 * to initialize the loader data and bss */
	common.Add(*symbol.NewElfSymbol("__HeapBase"))
	common.Add(*symbol.NewElfSymbol("__bss_start__"))
	common.Add(*symbol.NewElfSymbol("__bss_end__"))
	common.Add(*symbol.NewElfSymbol("__etext"))
	common.Add(*symbol.NewElfSymbol("__data_start__"))
	common.Add(*symbol.NewElfSymbol("__data_end__"))

	/* the split app may need this to access interrupts */
	common.Add(*symbol.NewElfSymbol("__vector_tbl_reloc__"))
	common.Add(*symbol.NewElfSymbol("__isr_vector"))

	err = b.CopySymbols(common)
	if err != nil {
		return err
	}

	/* These symbols are needed by the split app so it can zero
	 * bss and copy data from the loader app before it restarts,
	 * but we have to rename them since it has its own copies of
	 * these special linker symbols  */
	tmp_sm := symbol.NewSymbolMap()
	tmp_sm.Add(*symbol.NewElfSymbol("__HeapBase"))
	tmp_sm.Add(*symbol.NewElfSymbol("__bss_start__"))
	tmp_sm.Add(*symbol.NewElfSymbol("__bss_end__"))
	tmp_sm.Add(*symbol.NewElfSymbol("__etext"))
	tmp_sm.Add(*symbol.NewElfSymbol("__data_start__"))
	tmp_sm.Add(*symbol.NewElfSymbol("__data_end__"))
	err = c.RenameSymbols(tmp_sm, b.AppLinkerElfPath(), "_loader")

	if err != nil {
		return err
	}
	return nil
}

func (b *Builder) CreateImage(version string,
	keystr string, keyId uint8, loaderImg *image.Image) (*image.Image, error) {

	img, err := image.NewImage(b.AppBinPath(), b.AppImgPath())
	if err != nil {
		return nil, err
	}

	err = img.SetVersion(version)
	if err != nil {
		return nil, err
	}

	if keystr != "" {
		err = img.SetSigningKey(keystr, keyId)
		if err != nil {
			return nil, err
		}
	}

	img.HeaderSize = uint(b.targetBuilder.target.HeaderSize)
	err = img.Generate(loaderImg)
	if err != nil {
		return nil, err
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT,
		"App image succesfully generated: %s\n", img.TargetImg)

	return img, nil
}

// Deletes files that should never be reused for a subsequent build.  This
// list includes:
//     <app>.img
//     <app>.elf.bin
//     manifest.json
func (b *Builder) CleanArtifacts() {
	if b.appPkg == nil {
		return
	}

	paths := []string{
		b.AppImgPath(),
		b.AppBinPath(),
		b.ManifestPath(),
	}

	// Attempt to delete each artifact, ignoring errors.
	for _, p := range paths {
		os.Remove(p)
	}
}
