You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/03/07 12:56:22 UTC
[2/2] incubator-mynewt-newt git commit: newt build command
newt build command
The test command probably doesn't work
The binary paths are ridiculous (way too many subdirectories)
Lots more...
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/6f357ff9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/6f357ff9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/6f357ff9
Branch: refs/heads/rename_project_app
Commit: 6f357ff90e24c3036aca80b0fff8db4c8d06d3b3
Parents: ca12c25
Author: Christopher Collins <cc...@gmail.com>
Authored: Mon Mar 7 03:43:53 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Mon Mar 7 03:56:03 2016 -0800
----------------------------------------------------------------------
newt/builder/build.go | 281 +++++++++++++++++++++++++++++++++++---
newt/builder/buildpackage.go | 196 ++++++++++++++++----------
newt/builder/cmds.go | 19 ++-
newt/cli/util.go | 41 +-----
newt/newt.go | 2 +
newt/pkg/localpackage.go | 22 ++-
newt/pkg/package.go | 4 +-
newt/project/project.go | 7 +-
newt/toolchain/compiler.go | 232 +++++++++++++++++++------------
newt/toolchain/deps.go | 67 ++++++---
10 files changed, 613 insertions(+), 258 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/builder/build.go
----------------------------------------------------------------------
diff --git a/newt/builder/build.go b/newt/builder/build.go
index 057c28c..91fa80d 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -20,14 +20,21 @@
package builder
import (
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "mynewt.apache.org/newt/newt/cli"
"mynewt.apache.org/newt/newt/pkg"
"mynewt.apache.org/newt/newt/target"
+ "mynewt.apache.org/newt/newt/toolchain"
"mynewt.apache.org/newt/util"
)
type Builder struct {
Packages map[*pkg.LocalPackage]*BuildPackage
identities map[string]bool
+ apis map[string]*BuildPackage
target *target.Target
}
@@ -40,29 +47,61 @@ func (b *Builder) AddIdentity(identity string) {
b.identities[identity] = true
}
-func (b *Builder) GetPackage(pkg *pkg.LocalPackage) (*BuildPackage, bool) {
+func (b *Builder) AddPackage(pkg *pkg.LocalPackage) {
+ // Don't allow nil entries to the map
if pkg == nil {
- panic("Package should not equal NIL")
+ panic("Cannot add nil package builder map")
}
- bpkg, ok := b.Packages[pkg]
- if !ok {
- return nil, false
+ b.Packages[pkg] = NewBuildPackage(pkg)
+}
+
+func (b *Builder) AddApi(apiString string, bpkg *BuildPackage) {
+ curBpkg := b.apis[apiString]
+ if curBpkg != nil {
+ cli.StatusMessage(util.VERBOSITY_QUIET,
+ "Warning: API conflict: %s <-> %s\n", curBpkg.Name(), bpkg.Name())
} else {
- return bpkg, true
+ b.apis[apiString] = bpkg
}
}
-func (b *Builder) AddPackage(pkg *pkg.LocalPackage) {
- // Don't allow nil entries to the map
- if pkg == nil {
- panic("Cannot add nil package builder map")
+func (b *Builder) populateApis() {
+ // Satisfy API requirements.
+ for _, bpkg := range b.Packages {
+ for _, api := range bpkg.Apis() {
+ b.AddApi(api, bpkg)
+ }
}
+}
- b.Packages[pkg] = NewBuildPackage(pkg)
+// Returns true if at least one new API was satisfied.
+func (b *Builder) satisfyApis() (bool, error) {
+ moreWork := false
+
+ for _, bpkg := range b.Packages {
+ for _, reqApi := range bpkg.ReqApis() {
+ apiBpkg := b.apis[reqApi]
+ if apiBpkg == nil {
+ return false, util.NewNewtError(fmt.Sprintf("Could not "+
+ "satisfy API requirement; package=%s api=%s",
+ bpkg.Name(), reqApi))
+ }
+
+ dep := &pkg.Dependency{
+ Name: apiBpkg.Name(),
+ Repo: apiBpkg.Repo().Name(),
+ }
+ bpkg.AddDep(dep)
+ bpkg.DelReqApi(reqApi)
+ moreWork = true
+ }
+ }
+
+ return moreWork, nil
}
-func (b *Builder) LoadDeps() error {
+func (b *Builder) loadDeps() error {
for {
reprocess := false
for _, bpkg := range b.Packages {
@@ -80,30 +119,233 @@ func (b *Builder) LoadDeps() error {
break
}
}
+ return nil
+}
+
+func (b *Builder) unloadAllPackages() {
+ for _, bpkg := range b.Packages {
+ bpkg.loaded = false
+ }
+}
+
+func (b *Builder) FinalizePackages() error {
+ keepGoing := true
+ for keepGoing {
+ var err error
+
+ keepGoing, err = b.satisfyApis()
+ if err != nil {
+ return err
+ }
+
+ if keepGoing {
+ b.unloadAllPackages()
+ }
+
+ err = b.loadDeps()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Recursively compiles all the .c and .s files in the specified directory.
+// Architecture-specific files are also compiled.
+func buildDir(srcDir string, c *toolchain.Compiler, t *target.Target,
+ ignDirs []string) error {
+
+ var err error
+
+ cli.StatusMessage(util.VERBOSITY_VERBOSE,
+ "compiling src in base directory: %s\n", srcDir)
+
+ // First change into the pkg src directory, and build all the objects
+ // there
+ err = os.Chdir(srcDir)
+ if err != nil {
+ return util.NewNewtError(err.Error())
+ }
+
+ // Don't recurse into destination directories.
+ ignDirs = append(ignDirs, "obj")
+ ignDirs = append(ignDirs, "bin")
+
+ // Ignore architecture-specific source files for now. Use a temporary
+ // string array here so that the "arch" directory is not ignored in the
+ // subsequent architecture-specific compile phase.
+ baseIgnDirs := append(ignDirs, "arch")
+
+ if err = c.RecursiveCompile(toolchain.COMPILER_TYPE_C,
+ baseIgnDirs); err != nil {
+ return err
+ }
+
+ archDir := srcDir + "/arch/" + t.Arch + "/"
+ cli.StatusMessage(util.VERBOSITY_VERBOSE,
+ "compiling architecture specific src pkgs in directory: %s\n",
+ archDir)
+
+ if cli.NodeExist(archDir) {
+ if err := os.Chdir(archDir); err != nil {
+ return util.NewNewtError(err.Error())
+ }
+ if err := c.RecursiveCompile(toolchain.COMPILER_TYPE_C,
+ ignDirs); err != nil {
+ return err
+ }
+
+ // compile assembly sources in recursive compile as well
+ if err = c.RecursiveCompile(toolchain.COMPILER_TYPE_ASM,
+ ignDirs); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (b *Builder) archivePath(bpkg *BuildPackage) string {
+ binDir := bpkg.BasePath() + "/bin/" + b.target.Package().Name()
+ archiveFile := binDir + "/lib" + filepath.Base(bpkg.Name()) + ".a"
+ return archiveFile
+}
+
+func (b *Builder) buildPackage(bpkg *BuildPackage,
+ baseCi *toolchain.CompilerInfo, compilerPkg *pkg.LocalPackage) error {
+
+ srcDir := bpkg.BasePath() + "/src"
+ if cli.NodeNotExist(srcDir) {
+ // Nothing to compile.
+ return nil
+ }
+
+ c, err := toolchain.NewCompiler(compilerPkg.BasePath(),
+ "default", // XXX
+ b.target.Package().Name())
+ if err != nil {
+ return err
+ }
+ c.AddInfo(baseCi)
+
+ ci, err := bpkg.FullCompilerInfo(b)
+ if err != nil {
+ return err
+ }
+ c.AddInfo(ci)
+
+ // For now, ignore test code. Tests get built later if the test
+ // identity is in effect.
+ ignDirs := []string{"test"}
+
+ // Compile the source files.
+ err = buildDir(srcDir, c, b.target, ignDirs)
+ if err != nil {
+ return err
+ }
+
+ // Archive everything into a static library, which can be linked with a
+ // main program
+ if err := os.Chdir(bpkg.BasePath() + "/"); err != nil {
+ return util.NewNewtError(err.Error())
+ }
+
+ archiveFile := b.archivePath(bpkg)
+ if err := os.MkdirAll(filepath.Dir(archiveFile), 0755); err != nil {
+ return util.NewNewtError(err.Error())
+ }
+ if err = c.CompileArchive(archiveFile); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (b *Builder) linkApp(appPackage *BuildPackage,
+ baseCi *toolchain.CompilerInfo, compilerPkg *pkg.LocalPackage) error {
+
+ c, err := toolchain.NewCompiler(compilerPkg.BasePath(),
+ "default", // XXX
+ b.target.Package().Name())
+ if err != nil {
+ return err
+ }
+
+ c.AddInfo(baseCi)
+ binDir := appPackage.BasePath() + "/bin/" + b.target.Package().Name()
+ if cli.NodeNotExist(binDir) {
+ os.MkdirAll(binDir, 0755)
+ }
+
+ ci, err := appPackage.FullCompilerInfo(b)
+ if err != nil {
+ return err
+ }
+ c.AddInfo(ci)
+
+ pkgNames := []string{}
+ for _, bpkg := range b.Packages {
+ archivePath := b.archivePath(bpkg)
+ if cli.NodeExist(archivePath) {
+ pkgNames = append(pkgNames, archivePath)
+ }
+ }
+
+ elfFile := binDir + "/" + appPackage.Name()
+ err = c.CompileElf(elfFile, pkgNames)
+ if err != nil {
+ return err
+ }
return nil
}
func (b *Builder) Build() error {
+ compilerPkg := b.target.Compiler()
+ if compilerPkg == nil {
+ return util.NewNewtError("compiler package not found")
+ }
+
b.AddPackage(b.target.Bsp())
b.AddPackage(b.target.App())
b.AddPackage(b.target.Compiler())
- if err := b.LoadDeps(); err != nil {
+ if err := b.FinalizePackages(); err != nil {
return err
}
- bspPackage, ok := b.GetPackage(b.target.Bsp())
- if !ok {
+ bspPackage := b.Packages[b.target.Bsp()]
+ if bspPackage == nil {
return util.NewNewtError("BSP package not found!")
}
- baseCi := NewCompilerInfo()
- baseCi.AddCompilerInfo(bspPackage.PackageCompilerInfo())
+ bspCi, err := bspPackage.FullCompilerInfo(b)
+ if err != nil {
+ return err
+ }
- // Loop through all packages and build them
+ appPackage := b.Packages[b.target.App()]
+ if appPackage == nil {
+ return util.NewNewtError("App package not found")
+ }
+ appCi, err := appPackage.FullCompilerInfo(b)
+ if err != nil {
+ return err
+ }
+
+ baseCi := toolchain.NewCompilerInfo()
+ baseCi.AddCompilerInfo(bspCi)
+ baseCi.AddCompilerInfo(appCi)
+
+ for _, bpkg := range b.Packages {
+ err = b.buildPackage(bpkg, baseCi, compilerPkg)
+ if err != nil {
+ return err
+ }
+ }
- // Now, get the App, and link the application
+ b.linkApp(appPackage, baseCi, compilerPkg)
return nil
}
@@ -113,6 +355,7 @@ func (b *Builder) Init(target *target.Target) error {
b.Packages = map[*pkg.LocalPackage]*BuildPackage{}
b.identities = map[string]bool{}
+ b.apis = map[string]*BuildPackage{}
return nil
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/builder/buildpackage.go
----------------------------------------------------------------------
diff --git a/newt/builder/buildpackage.go b/newt/builder/buildpackage.go
index e35fcca..0f61cf3 100644
--- a/newt/builder/buildpackage.go
+++ b/newt/builder/buildpackage.go
@@ -20,52 +20,101 @@
package builder
import (
+ "fmt"
+ "path/filepath"
+
"mynewt.apache.org/newt/newt/cli"
"mynewt.apache.org/newt/newt/pkg"
"mynewt.apache.org/newt/newt/project"
+ "mynewt.apache.org/newt/newt/toolchain"
"mynewt.apache.org/newt/util"
)
-type CompilerInfo struct {
- Includes []string
- Cflags []string
- Lflags []string
- Aflags []string
-}
-
type BuildPackage struct {
*pkg.LocalPackage
- pkgCi *CompilerInfo
- fullCi *CompilerInfo
+ fullCi *toolchain.CompilerInfo
isBsp bool
loaded bool
}
-func (ci *CompilerInfo) AddCompilerInfo(newCi *CompilerInfo) {
- ci.Includes = append(ci.Includes, newCi.Includes...)
- ci.Cflags = append(ci.Cflags, newCi.Cflags...)
- ci.Lflags = append(ci.Lflags, newCi.Lflags...)
- ci.Aflags = append(ci.Aflags, newCi.Aflags...)
+// Recursively iterates through an pkg's dependencies, adding each pkg
+// encountered to the supplied set.
+func (bpkg *BuildPackage) collectDepsAux(b *Builder,
+ set *map[*BuildPackage]bool) error {
+
+ if (*set)[bpkg] {
+ return nil
+ }
+
+ (*set)[bpkg] = true
+
+ for _, dep := range bpkg.Deps() {
+ if dep.Name == "" {
+ break
+ }
+
+ // Get pkg structure
+ dpkg, err := project.GetProject().ResolveDependency(dep)
+ if err != nil {
+ return err
+ }
+
+ dbpkg := b.Packages[dpkg]
+ if dbpkg == nil {
+ return util.NewNewtError(fmt.Sprintf("Package not found (%s)",
+ dpkg.Name()))
+ }
+
+ err = dbpkg.collectDepsAux(b, set)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
}
-func NewCompilerInfo() *CompilerInfo {
- ci := &CompilerInfo{}
- ci.Includes = []string{}
- ci.Cflags = []string{}
- ci.Lflags = []string{}
- ci.Aflags = []string{}
+// Recursively iterates through an pkg's dependencies. The resulting array
+// contains a pointer to each encountered pkg.
+func (bpkg *BuildPackage) collectDeps(b *Builder) ([]*BuildPackage, error) {
+ set := map[*BuildPackage]bool{}
+
+ err := bpkg.collectDepsAux(b, &set)
+ if err != nil {
+ return nil, err
+ }
+
+ arr := []*BuildPackage{}
+ for p, _ := range set {
+ arr = append(arr, p)
+ }
- return ci
+ return arr, nil
}
-func (bpkg *BuildPackage) PackageCompilerInfo() *CompilerInfo {
- return bpkg.pkgCi
+// Calculates the include paths exported by the specified pkg and all of
+// its recursive dependencies.
+func (bpkg *BuildPackage) recursiveIncludePaths(b *Builder) ([]string, error) {
+ deps, err := bpkg.collectDeps(b)
+ if err != nil {
+ return nil, err
+ }
+
+ incls := []string{}
+ for _, p := range deps {
+ incls = append(incls, p.publicIncludeDirs(b)...)
+ }
+ for _, p := range deps {
+ incls = append(incls, p.publicIncludeDirs(b)...)
+ }
+
+ return incls, nil
}
-func (bpkg *BuildPackage) FullCompilerInfo(b *Builder) (*CompilerInfo, error) {
+func (bpkg *BuildPackage) FullCompilerInfo(b *Builder) (*toolchain.CompilerInfo, error) {
if !bpkg.loaded {
return nil, util.NewNewtError("Package must be loaded before Compiler info is fetched")
}
@@ -74,29 +123,19 @@ func (bpkg *BuildPackage) FullCompilerInfo(b *Builder) (*CompilerInfo, error) {
return bpkg.fullCi, nil
}
- ci := NewCompilerInfo()
- ci.AddCompilerInfo(bpkg.pkgCi)
+ ci := toolchain.NewCompilerInfo()
+ ci.Cflags = cli.GetStringSliceIdentities(bpkg.Viper, b.Identities(),
+ "pkg.cflags")
+ ci.Lflags = cli.GetStringSliceIdentities(bpkg.Viper, b.Identities(),
+ "pkg.lflags")
+ ci.Aflags = cli.GetStringSliceIdentities(bpkg.Viper, b.Identities(),
+ "pkg.aflags")
- // Go through every dependency, and add the compiler information for that
- // dependency
- for _, dep := range bpkg.Deps() {
- pkg, err := project.GetProject().ResolveDependency(dep)
- if err != nil {
- return nil, err
- }
-
- if pkg == nil {
- return nil, util.NewNewtError("Cannot resolve dep " + dep.String())
- }
-
- bpkg, ok := b.GetPackage(pkg)
- if !ok {
- return nil, util.NewNewtError("Unknown build info for package " + pkg.Name())
- }
-
- ci.AddCompilerInfo(bpkg.PackageCompilerInfo())
+ includePaths, err := bpkg.recursiveIncludePaths(b)
+ if err != nil {
+ return nil, err
}
-
+ ci.Includes = append(bpkg.privateIncludeDirs(b), includePaths...)
bpkg.fullCi = ci
return bpkg.fullCi, nil
@@ -107,7 +146,8 @@ func (bpkg *BuildPackage) loadIdentities(b *Builder) (map[string]bool, bool) {
foundNewIdent := false
- newIdents := cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.identities")
+ newIdents := cli.GetStringSliceIdentities(bpkg.Viper, idents,
+ "pkg.identities")
for _, nident := range newIdents {
_, ok := idents[nident]
if !ok {
@@ -117,13 +157,15 @@ func (bpkg *BuildPackage) loadIdentities(b *Builder) (map[string]bool, bool) {
}
if foundNewIdent {
- return b.Identities(), foundNewIdent
+ return b.Identities(), true
} else {
- return idents, foundNewIdent
+ return idents, false
}
}
-func (bpkg *BuildPackage) loadDeps(b *Builder, idents map[string]bool) (bool, error) {
+func (bpkg *BuildPackage) loadDeps(b *Builder,
+ idents map[string]bool) (bool, error) {
+
proj := project.GetProject()
foundNewDep := false
@@ -141,17 +183,18 @@ func (bpkg *BuildPackage) loadDeps(b *Builder, idents map[string]bool) (bool, er
}
if pkg == nil {
- return false, util.NewNewtError("Could not resolve package dependency " +
- newDep.String())
+ return false,
+ util.NewNewtError("Could not resolve package dependency " +
+ newDep.String())
}
- _, ok := b.GetPackage(pkg)
- if !ok {
+ if b.Packages[pkg] == nil {
foundNewDep = true
b.AddPackage(pkg)
}
if !bpkg.HasDep(newDep) {
+ foundNewDep = true
bpkg.AddDep(newDep)
}
}
@@ -159,6 +202,31 @@ func (bpkg *BuildPackage) loadDeps(b *Builder, idents map[string]bool) (bool, er
return foundNewDep, nil
}
+func (bpkg *BuildPackage) publicIncludeDirs(b *Builder) []string {
+ pkgBase := filepath.Base(bpkg.Name())
+
+ return []string{
+ bpkg.BasePath() + "/include",
+ bpkg.BasePath() + "/include/" + pkgBase + "/arch/" + b.target.Arch,
+ }
+}
+
+func (bpkg *BuildPackage) privateIncludeDirs(b *Builder) []string {
+ srcDir := bpkg.BasePath() + "/src/"
+
+ incls := []string{}
+ incls = append(incls, srcDir)
+ incls = append(incls, srcDir+"/arch/"+b.target.Arch)
+
+ if cli.CheckBoolMap(b.Identities(), "test") {
+ testSrcDir := srcDir + "/test"
+ incls = append(incls, testSrcDir)
+ incls = append(incls, testSrcDir+"/arch/"+b.target.Arch)
+ }
+
+ return incls
+}
+
func (bpkg *BuildPackage) Load(b *Builder) (bool, error) {
if bpkg.loaded {
return true, nil
@@ -178,31 +246,15 @@ func (bpkg *BuildPackage) Load(b *Builder) (bool, error) {
// Now, load the rest of the package, this should happen only once.
apis := cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.caps")
- for _, apiStr := range apis {
- api, err := pkg.NewDependency(bpkg.Repo(), apiStr)
- if err != nil {
- return false, err
- }
+ for _, api := range apis {
bpkg.AddApi(api)
}
reqApis := cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.req_caps")
- for _, apiStr := range reqApis {
- api, err := pkg.NewDependency(bpkg.Repo(), apiStr)
- if err != nil {
- return false, err
- }
- bpkg.AddReqApi(api)
+ for _, reqApi := range reqApis {
+ bpkg.AddReqApi(reqApi)
}
- ci := NewCompilerInfo()
- ci.Cflags = cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.cflags")
- ci.Lflags = cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.lflags")
- ci.Aflags = cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.aflags")
- ci.Includes = cli.GetStringSliceIdentities(bpkg.Viper, idents, "pkg.includes")
-
- bpkg.pkgCi = ci
-
bpkg.loaded = true
return true, nil
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/builder/cmds.go
----------------------------------------------------------------------
diff --git a/newt/builder/cmds.go b/newt/builder/cmds.go
index 3e1dc63..99e438e 100644
--- a/newt/builder/cmds.go
+++ b/newt/builder/cmds.go
@@ -23,16 +23,23 @@ import (
"fmt"
"github.com/spf13/cobra"
+ "mynewt.apache.org/newt/newt/cli"
"mynewt.apache.org/newt/newt/target"
+ "mynewt.apache.org/newt/util"
)
func buildRunCmd(cmd *cobra.Command, args []string) {
- b, err := NewBuilder(&target.Target{
- BspName: "$apache-mynewt-world/hw/bsp/native",
- AppName: "apps/blinky",
- CompilerName: "$apache-mynewt-world/compiler/sim",
- Arch: "sim",
- })
+ if len(args) < 1 {
+ cli.NewtUsage(cmd, nil)
+ }
+
+ targetName := args[0]
+ t := target.GetTargets()[targetName]
+ if t == nil {
+ cli.NewtUsage(cmd, util.NewNewtError("invalid target name"))
+ }
+
+ b, err := NewBuilder(t)
if err != nil {
fmt.Println(err)
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/cli/util.go
----------------------------------------------------------------------
diff --git a/newt/cli/util.go b/newt/cli/util.go
index 02cb986..b845b1b 100644
--- a/newt/cli/util.go
+++ b/newt/cli/util.go
@@ -21,7 +21,6 @@ package cli
import (
"bufio"
- "bytes"
"fmt"
"io/ioutil"
"log"
@@ -113,7 +112,7 @@ func Init(level string, silent bool, quiet bool, verbose bool) {
}
}
-func checkBoolMap(mapVar map[string]bool, item string) bool {
+func CheckBoolMap(mapVar map[string]bool, item string) bool {
v, ok := mapVar[item]
return v && ok
}
@@ -384,44 +383,6 @@ func ReadLines(path string) ([]string, error) {
return lines, nil
}
-// Determines if a file was previously built with a command line invocation
-// different from the one specified.
-//
-// @param dstFile The output file whose build invocation is being
-// tested.
-// @param cmd The command that would be used to generate the
-// specified destination file.
-//
-// @return true if the command has changed or if the
-// destination file was never built;
-// false otherwise.
-func CommandHasChanged(dstFile string, cmd string) bool {
- cmdFile := dstFile + ".cmd"
- prevCmd, err := ioutil.ReadFile(cmdFile)
- if err != nil {
- return true
- }
-
- return bytes.Compare(prevCmd, []byte(cmd)) != 0
-}
-
-// Writes a file containing the command-line invocation used to generate the
-// specified file. The file that this function writes can be used later to
-// determine if the set of compiler options has changed.
-//
-// @param dstFile The output file whose build invocation is being
-// recorded.
-// @param cmd The command to write.
-func WriteCommandFile(dstFile string, cmd string) error {
- cmdPath := dstFile + ".cmd"
- err := ioutil.WriteFile(cmdPath, []byte(cmd), 0644)
- if err != nil {
- return err
- }
-
- return nil
-}
-
// Removes all duplicate strings from the specified array, while preserving
// order.
func UniqueStrings(elems []string) []string {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/newt.go
----------------------------------------------------------------------
diff --git a/newt/newt.go b/newt/newt.go
index 68b0883..4cb8ad6 100644
--- a/newt/newt.go
+++ b/newt/newt.go
@@ -84,6 +84,8 @@ func newtCmd() *cobra.Command {
}
func main() {
+ cli.Init("ERROR", false, false, false)
+
cmd := newtCmd()
project.AddCommands(cmd)
pkg.AddCommands(cmd)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/pkg/localpackage.go
----------------------------------------------------------------------
diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go
index f3de061..a95ef44 100644
--- a/newt/pkg/localpackage.go
+++ b/newt/pkg/localpackage.go
@@ -60,9 +60,9 @@ type LocalPackage struct {
// Dependencies for this package
deps []*Dependency
// APIs that this package exports
- apis []*Dependency
+ apis []string
// APIs that this package requires
- reqApis []*Dependency
+ reqApis []string
// Pointer to pkg.yml configuration structure
Viper *viper.Viper
@@ -166,19 +166,28 @@ func (pkg *LocalPackage) Deps() []*Dependency {
return pkg.deps
}
-func (pkg *LocalPackage) AddApi(api *Dependency) {
+func (pkg *LocalPackage) AddApi(api string) {
pkg.apis = append(pkg.apis, api)
}
-func (pkg *LocalPackage) Apis() []*Dependency {
+func (pkg *LocalPackage) Apis() []string {
return pkg.apis
}
-func (pkg *LocalPackage) AddReqApi(api *Dependency) {
+func (pkg *LocalPackage) AddReqApi(api string) {
pkg.reqApis = append(pkg.reqApis, api)
}
-func (pkg *LocalPackage) ReqApis() []*Dependency {
+func (pkg *LocalPackage) DelReqApi(api string) {
+ for i, entry := range pkg.reqApis {
+ if api == entry {
+ pkg.reqApis = append(pkg.reqApis[:i], pkg.reqApis[i+1:]...)
+ return
+ }
+ }
+}
+
+func (pkg *LocalPackage) ReqApis() []string {
return pkg.reqApis
}
@@ -207,7 +216,6 @@ func (pkg *LocalPackage) Save() error {
}
filepath := dirpath + "/" + PACKAGE_FILE_NAME
- fmt.Printf("filepath=%s\n", filepath)
file, err := os.Create(filepath)
if err != nil {
return util.NewNewtError(err.Error())
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/pkg/package.go
----------------------------------------------------------------------
diff --git a/newt/pkg/package.go b/newt/pkg/package.go
index 94f0c57..bfb9eb1 100644
--- a/newt/pkg/package.go
+++ b/newt/pkg/package.go
@@ -69,9 +69,9 @@ type Package interface {
// Dependency list for this package
Deps() []*Dependency
// APIs exported by this package
- Apis() []*Dependency
+ Apis() []string
// APIs required by this package
- ReqApis() []*Dependency
+ ReqApis() []string
}
// Description of a package
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/project/project.go
----------------------------------------------------------------------
diff --git a/newt/project/project.go b/newt/project/project.go
index fb145df..23e3ce3 100644
--- a/newt/project/project.go
+++ b/newt/project/project.go
@@ -203,18 +203,15 @@ func (proj *Project) Init(dir string) error {
}
func (proj *Project) ResolveDependency(dep *pkg.Dependency) (*pkg.LocalPackage, error) {
- var myPkg *pkg.LocalPackage = nil
-
for _, pkgList := range proj.packages {
for _, pkg := range *pkgList {
if dep.SatisfiesDependency(pkg) {
- myPkg = pkg
- break
+ return pkg, nil
}
}
}
- return myPkg, nil
+ return nil, util.NewNewtError("Can't resolve dependency: " + dep.Name)
}
func findProjectDir(dir string) (string, error) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/toolchain/compiler.go
----------------------------------------------------------------------
diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go
index 17aacb6..82bc537 100644
--- a/newt/toolchain/compiler.go
+++ b/newt/toolchain/compiler.go
@@ -29,7 +29,8 @@ import (
"strings"
"time"
- _ "mynewt.apache.org/newt/newt/util"
+ "mynewt.apache.org/newt/newt/cli"
+ . "mynewt.apache.org/newt/util"
)
const (
@@ -37,17 +38,18 @@ const (
COMPILER_TYPE_ASM = 1
)
+type CompilerInfo struct {
+ Includes []string
+ Cflags []string
+ Lflags []string
+ Aflags []string
+}
+
type Compiler struct {
- ConfigPath string
TargetName string
- BaseIncludes map[string]bool
ObjPathList map[string]bool
LinkerScript string
- Cflags string
- Aflags string
- Lflags string
-
depTracker DepTracker
ccPath string
asPath string
@@ -55,30 +57,42 @@ type Compiler struct {
odPath string
osPath string
ocPath string
- ldFlags string
ldResolveCircularDeps bool
ldMapFile bool
+
+ info CompilerInfo
+}
+
+func NewCompilerInfo() *CompilerInfo {
+ ci := &CompilerInfo{}
+ ci.Includes = []string{}
+ ci.Cflags = []string{}
+ ci.Lflags = []string{}
+ ci.Aflags = []string{}
+
+ return ci
}
-func NewCompiler(ccPath string, cDef string, tName string, includes []string) (
- *Compiler, error) {
+func (ci *CompilerInfo) AddCompilerInfo(newCi *CompilerInfo) {
+ ci.Includes = append(ci.Includes, newCi.Includes...)
+ ci.Cflags = append(ci.Cflags, newCi.Cflags...)
+ ci.Lflags = append(ci.Lflags, newCi.Lflags...)
+ ci.Aflags = append(ci.Aflags, newCi.Aflags...)
+}
+
+func NewCompiler(compilerDir string, cDef string,
+ tName string) (*Compiler, error) {
c := &Compiler{
- ConfigPath: ccPath,
- TargetName: tName,
- BaseIncludes: map[string]bool{},
- ObjPathList: map[string]bool{},
+ TargetName: tName,
+ ObjPathList: map[string]bool{},
}
c.depTracker = NewDepTracker(c)
- for _, incl := range includes {
- c.BaseIncludes[incl] = true
- }
- StatusMessage(VERBOSITY_VERBOSE,
- "Loading compiler %s, target %s, def %s\n", ccPath, tName, cDef)
-
- err := c.ReadSettings(cDef)
+ cli.StatusMessage(cli.VERBOSITY_VERBOSE,
+ "Loading compiler %s, target %s, def %s\n", compilerDir, tName, cDef)
+ err := c.load(compilerDir, cDef)
if err != nil {
return nil, err
}
@@ -86,8 +100,8 @@ func NewCompiler(ccPath string, cDef string, tName string, includes []string) (
return c, nil
}
-func (c *Compiler) ReadSettings(cDef string) error {
- v, err := ReadConfig(c.ConfigPath, "pkg")
+func (c *Compiler) load(compilerDir string, cDef string) error {
+ v, err := ReadConfig(compilerDir, "compiler")
if err != nil {
return err
}
@@ -102,22 +116,27 @@ func (c *Compiler) ReadSettings(cDef string) error {
cflags := v.GetStringSlice("compiler.flags." + cDef)
for _, flag := range cflags {
if strings.HasPrefix(flag, "compiler.flags") {
- c.Cflags += " " + strings.Trim(v.GetString(flag), "\n")
+ c.info.Cflags = append(c.info.Cflags,
+ strings.Trim(v.GetString(flag), "\n"))
} else {
- c.Cflags += " " + strings.Trim(flag, "\n")
+ c.info.Cflags = append(c.info.Cflags, strings.Trim(flag, "\n"))
}
}
- c.ldFlags = v.GetString("compiler.ld.flags")
+ c.info.Lflags = v.GetStringSlice("compiler.ld.flags")
c.ldResolveCircularDeps = v.GetBool("compiler.ld.resolve_circular_deps")
c.ldMapFile = v.GetBool("compiler.ld.mapfile")
log.Printf("[INFO] ccPath = %s, arPath = %s, flags = %s", c.ccPath,
- c.arPath, c.Cflags)
+ c.arPath, c.info.Cflags)
return nil
}
+func (c *Compiler) AddInfo(info *CompilerInfo) {
+ c.info.AddCompilerInfo(info)
+}
+
// Skips compilation of the specified C or assembly file, but adds the name of
// the object file that would have been generated to the compiler's list of
// object files. This function is used when the object file is already up to
@@ -144,17 +163,25 @@ func (c *Compiler) SkipSourceFile(srcFile string) error {
// Generates a string consisting of all the necessary include path (-I)
// options. The result is sorted and contains no duplicate paths.
-func (c *Compiler) IncludesString() string {
- includes := make([]string, 0, len(c.BaseIncludes))
- for k, _ := range c.BaseIncludes {
- includes = append(includes, filepath.ToSlash(k))
+func (c *Compiler) includesString() string {
+ if len(c.info.Includes) == 0 {
+ return ""
}
- sort.Strings(includes)
-
+ includes := cli.SortFields(c.info.Includes...)
return "-I" + strings.Join(includes, " -I")
}
+func (c *Compiler) cflagsString() string {
+ cflags := cli.SortFields(c.info.Cflags...)
+ return strings.Join(cflags, " ")
+}
+
+func (c *Compiler) lflagsString() string {
+ lflags := cli.SortFields(c.info.Lflags...)
+ return strings.Join(lflags, " ")
+}
+
// Calculates the command-line invocation necessary to compile the specified C
// or assembly file.
//
@@ -182,7 +209,7 @@ func (c *Compiler) CompileFileCmd(file string,
}
cmd += " -c " + "-o " + objPath + " " + file +
- " " + c.Cflags + " " + c.IncludesString()
+ " " + c.cflagsString() + " " + c.includesString()
return cmd, nil
}
@@ -194,19 +221,36 @@ func (c *Compiler) GenDepsForFile(file string) error {
wd, _ := os.Getwd()
objDir := wd + "/obj/" + c.TargetName + "/"
- if NodeNotExist(objDir) {
+ if cli.NodeNotExist(objDir) {
os.MkdirAll(objDir, 0755)
}
depFile := objDir + strings.TrimSuffix(file, filepath.Ext(file)) + ".d"
depFile = filepath.ToSlash(depFile)
- cFlags := c.Cflags + " " + c.IncludesString()
var cmd string
var err error
- cmd = c.ccPath + " " + cFlags + " -MM -MG " + file + " > " + depFile
- _, err = ShellCommand(cmd)
+ cmd = c.ccPath + " " + c.cflagsString() + " " + c.includesString() +
+ " -MM -MG " + file + " > " + depFile
+ _, err = cli.ShellCommand(cmd)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Writes a file containing the command-line invocation used to generate the
+// specified file. The file that this function writes can be used later to
+// determine if the set of compiler options has changed.
+//
+// @param dstFile The output file whose build invocation is being
+// recorded.
+// @param cmd The command to write.
+func writeCommandFile(dstFile string, cmd string) error {
+ cmdPath := dstFile + ".cmd"
+ err := ioutil.WriteFile(cmdPath, []byte(cmd), 0644)
if err != nil {
return err
}
@@ -222,7 +266,7 @@ func (c *Compiler) CompileFile(file string, compilerType int) error {
wd, _ := os.Getwd()
objDir := wd + "/obj/" + c.TargetName + "/"
- if NodeNotExist(objDir) {
+ if cli.NodeNotExist(objDir) {
os.MkdirAll(objDir, 0755)
}
@@ -238,20 +282,20 @@ func (c *Compiler) CompileFile(file string, compilerType int) error {
switch compilerType {
case COMPILER_TYPE_C:
- StatusMessage(VERBOSITY_DEFAULT, "Compiling %s\n", file)
+ cli.StatusMessage(cli.VERBOSITY_DEFAULT, "Compiling %s\n", file)
case COMPILER_TYPE_ASM:
- StatusMessage(VERBOSITY_DEFAULT, "Assembling %s\n", file)
+ cli.StatusMessage(cli.VERBOSITY_DEFAULT, "Assembling %s\n", file)
default:
return NewNewtError("Unknown compiler type")
}
- rsp, err := ShellCommand(cmd)
+ rsp, err := cli.ShellCommand(cmd)
if err != nil {
- StatusMessage(VERBOSITY_QUIET, string(rsp))
+ cli.StatusMessage(cli.VERBOSITY_QUIET, string(rsp))
return err
}
- err = WriteCommandFile(objPath, cmd)
+ err = writeCommandFile(objPath, cmd)
if err != nil {
return err
}
@@ -266,19 +310,20 @@ func (c *Compiler) CompileFile(file string, compilerType int) error {
//
// @param match The file glob specifying which C files to
// compile.
-func (c *Compiler) Compile(match string) error {
- files, _ := filepath.Glob(match)
+func (c *Compiler) CompileC() error {
+ files, _ := filepath.Glob("*.c")
wd, err := os.Getwd()
if err != nil {
return err
}
- log.Printf("[INFO] Compiling C if outdated (%s/%s) %s", wd, match,
+ log.Printf("[INFO] Compiling C if outdated (%s/*.c) %s", wd,
strings.Join(files, " "))
for _, file := range files {
file = filepath.ToSlash(file)
- compileRequired, err := c.depTracker.CompileRequired(file, 0)
+ compileRequired, err := c.depTracker.CompileRequired(file,
+ COMPILER_TYPE_C)
if err != nil {
return err
}
@@ -299,18 +344,19 @@ func (c *Compiler) Compile(match string) error {
//
// @param match The file glob specifying which assembly files
// to compile.
-func (c *Compiler) CompileAs(match string) error {
- files, _ := filepath.Glob(match)
+func (c *Compiler) CompileAs() error {
+ files, _ := filepath.Glob("*.s")
wd, err := os.Getwd()
if err != nil {
return err
}
- log.Printf("[INFO] Compiling assembly if outdated (%s/%s) %s", wd, match,
+ log.Printf("[INFO] Compiling assembly if outdated (%s/*.s) %s", wd,
strings.Join(files, " "))
for _, file := range files {
- compileRequired, err := c.depTracker.CompileRequired(file, 1)
+ compileRequired, err := c.depTracker.CompileRequired(file,
+ COMPILER_TYPE_ASM)
if err != nil {
return err
}
@@ -357,7 +403,7 @@ func (c *Compiler) RecursiveClean(path string, tName string) error {
return nil
}
-func (c *Compiler) processEntry(wd string, node os.FileInfo, match string, cType int,
+func (c *Compiler) processEntry(wd string, node os.FileInfo, cType int,
ignDirs []string) error {
// check to see if we ignore this element
for _, entry := range ignDirs {
@@ -368,13 +414,14 @@ func (c *Compiler) processEntry(wd string, node os.FileInfo, match string, cType
// if not, recurse into the directory
os.Chdir(wd + "/" + node.Name())
- return c.RecursiveCompile(match, cType, ignDirs)
+ return c.RecursiveCompile(cType, ignDirs)
}
-func (c *Compiler) RecursiveCompile(match string, cType int, ignDirs []string) error {
+func (c *Compiler) RecursiveCompile(cType int, ignDirs []string) error {
// Get a list of files in the current directory, and if they are a directory,
// and that directory is not in the ignDirs variable, then recurse into that
// directory and compile the files in there
+
wd, err := os.Getwd()
if err != nil {
return NewNewtError(err.Error())
@@ -388,20 +435,23 @@ func (c *Compiler) RecursiveCompile(match string, cType int, ignDirs []string) e
for _, node := range dirList {
if node.IsDir() {
- err = c.processEntry(wd, node, match, cType, ignDirs)
+ err = c.processEntry(wd, node, cType, ignDirs)
if err != nil {
return err
}
}
}
- os.Chdir(wd)
+ err = os.Chdir(wd)
+ if err != nil {
+ return err
+ }
switch cType {
case 0:
- return c.Compile(match)
+ return c.CompileC()
case 1:
- return c.CompileAs(match)
+ return c.CompileAs()
default:
return NewNewtError("Wrong compiler type specified to RecursiveCompile")
}
@@ -430,21 +480,21 @@ func (c *Compiler) getObjFiles(baseObjFiles []string) string {
func (c *Compiler) CompileBinaryCmd(dstFile string, options map[string]bool,
objFiles []string) string {
- objList := c.getObjFiles(UniqueStrings(objFiles))
+ objList := c.getObjFiles(cli.UniqueStrings(objFiles))
- cmd := c.ccPath + " -o " + dstFile + " " + " " + c.Cflags
+ cmd := c.ccPath + " -o " + dstFile + " " + " " + c.cflagsString()
if c.ldResolveCircularDeps {
cmd += " -Wl,--start-group " + objList + " -Wl,--end-group "
} else {
cmd += " " + objList
}
- cmd += " " + c.ldFlags
+ cmd += " " + c.lflagsString()
if c.LinkerScript != "" {
cmd += " -T " + c.LinkerScript
}
- if checkBoolMap(options, "mapFile") {
+ if cli.CheckBoolMap(options, "mapFile") {
cmd += " -Wl,-Map=" + dstFile + ".map"
}
@@ -461,20 +511,20 @@ func (c *Compiler) CompileBinaryCmd(dstFile string, options map[string]bool,
func (c *Compiler) CompileBinary(dstFile string, options map[string]bool,
objFiles []string) error {
- objList := c.getObjFiles(UniqueStrings(objFiles))
+ objList := c.getObjFiles(cli.UniqueStrings(objFiles))
- StatusMessage(VERBOSITY_DEFAULT, "Linking %s\n", path.Base(dstFile))
- StatusMessage(VERBOSITY_VERBOSE, "Linking %s with input files %s\n",
+ cli.StatusMessage(cli.VERBOSITY_DEFAULT, "Linking %s\n", path.Base(dstFile))
+ cli.StatusMessage(cli.VERBOSITY_VERBOSE, "Linking %s with input files %s\n",
dstFile, objList)
cmd := c.CompileBinaryCmd(dstFile, options, objFiles)
- rsp, err := ShellCommand(cmd)
+ rsp, err := cli.ShellCommand(cmd)
if err != nil {
- StatusMessage(VERBOSITY_QUIET, string(rsp))
+ cli.StatusMessage(cli.VERBOSITY_QUIET, string(rsp))
return err
}
- err = WriteCommandFile(dstFile, cmd)
+ err = writeCommandFile(dstFile, cmd)
if err != nil {
return err
}
@@ -496,17 +546,17 @@ func (c *Compiler) generateExtras(elfFilename string,
var cmd string
- if checkBoolMap(options, "listFile") {
+ if cli.CheckBoolMap(options, "listFile") {
listFile := elfFilename + ".lst"
// if list file exists, remove it
- if NodeExist(listFile) {
+ if cli.NodeExist(listFile) {
if err := os.RemoveAll(listFile); err != nil {
return err
}
}
cmd = c.odPath + " -wxdS " + elfFilename + " >> " + listFile
- _, err := ShellCommand(cmd)
+ _, err := cli.ShellCommand(cmd)
if err != nil {
// XXX: gobjdump appears to always crash. Until we get that sorted
// out, don't fail the link process if lst generation fails.
@@ -517,21 +567,21 @@ func (c *Compiler) generateExtras(elfFilename string,
for _, sect := range sects {
cmd = c.odPath + " -s -j " + sect + " " + elfFilename + " >> " +
listFile
- ShellCommand(cmd)
+ cli.ShellCommand(cmd)
}
cmd = c.osPath + " " + elfFilename + " >> " + listFile
- _, err = ShellCommand(cmd)
+ _, err = cli.ShellCommand(cmd)
if err != nil {
return err
}
}
- if checkBoolMap(options, "binFile") {
+ if cli.CheckBoolMap(options, "binFile") {
binFile := elfFilename + ".bin"
cmd = c.ocPath + " -R .bss -R .bss.core -R .bss.core.nz -O binary " +
elfFilename + " " + binFile
- _, err := ShellCommand(cmd)
+ _, err := cli.ShellCommand(cmd)
if err != nil {
return err
}
@@ -548,16 +598,20 @@ func (c *Compiler) generateExtras(elfFilename string,
// @param options Some build options specifying how the elf file
// gets generated.
// @param objFiles An array of the source .o and .a filenames.
-func (c *Compiler) CompileElf(binFile string, options map[string]bool,
- objFiles []string) error {
-
+func (c *Compiler) CompileElf(binFile string, objFiles []string) error {
binFile += ".elf"
+ options := map[string]bool{"mapFile": c.ldMapFile,
+ "listFile": true, "binFile": true}
+
linkRequired, err := c.depTracker.LinkRequired(binFile, options, objFiles)
if err != nil {
return err
}
if linkRequired {
+ if err := os.MkdirAll(filepath.Dir(binFile), 0755); err != nil {
+ return NewNewtError(err.Error())
+ }
err := c.CompileBinary(binFile, options, objFiles)
if err != nil {
return err
@@ -590,7 +644,9 @@ func (c *Compiler) CompileArchiveCmd(archiveFile string,
//
// @param archiveFile The filename of the library to archive.
// @param objFiles An array of the source .o filenames.
-func (c *Compiler) CompileArchive(archiveFile string, objFiles []string) error {
+func (c *Compiler) CompileArchive(archiveFile string) error {
+ objFiles := []string{}
+
arRequired, err := c.depTracker.ArchiveRequired(archiveFile, objFiles)
if err != nil {
return err
@@ -599,11 +655,11 @@ func (c *Compiler) CompileArchive(archiveFile string, objFiles []string) error {
return nil
}
- objList := c.getObjFiles(objFiles)
-
- StatusMessage(VERBOSITY_DEFAULT, "Archiving %s\n", path.Base(archiveFile))
- StatusMessage(VERBOSITY_VERBOSE, "Archiving %s with object files %s",
- archiveFile, objList)
+ cli.StatusMessage(cli.VERBOSITY_DEFAULT, "Archiving %s\n",
+ path.Base(archiveFile))
+ objList := c.getObjFiles([]string{})
+ cli.StatusMessage(cli.VERBOSITY_VERBOSE, "Archiving %s with object "+
+ "files %s\n", archiveFile, objList)
// Delete the old archive, if it exists.
err = os.Remove(archiveFile)
@@ -612,13 +668,13 @@ func (c *Compiler) CompileArchive(archiveFile string, objFiles []string) error {
}
cmd := c.CompileArchiveCmd(archiveFile, objFiles)
- rsp, err := ShellCommand(cmd)
+ rsp, err := cli.ShellCommand(cmd)
if err != nil {
- StatusMessage(VERBOSITY_QUIET, string(rsp))
+ cli.StatusMessage(cli.VERBOSITY_QUIET, string(rsp))
return err
}
- err = WriteCommandFile(archiveFile, cmd)
+ err = writeCommandFile(archiveFile, cmd)
if err != nil {
return err
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/6f357ff9/newt/toolchain/deps.go
----------------------------------------------------------------------
diff --git a/newt/toolchain/deps.go b/newt/toolchain/deps.go
index ce3c128..b2ddc06 100644
--- a/newt/toolchain/deps.go
+++ b/newt/toolchain/deps.go
@@ -20,12 +20,15 @@
package toolchain
import (
+ "bytes"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
"time"
- _ "mynewt.apache.org/newt/newt/util"
+ "mynewt.apache.org/newt/newt/cli"
+ "mynewt.apache.org/newt/util"
)
type DepTracker struct {
@@ -53,7 +56,7 @@ func NewDepTracker(c *Compiler) DepTracker {
//
// This function ignores all lines except for the first.
func ParseDepsFile(filename string) ([]string, error) {
- lines, err := ReadLines(filename)
+ lines, err := cli.ReadLines(filename)
if err != nil {
return nil, err
}
@@ -65,13 +68,13 @@ func ParseDepsFile(filename string) ([]string, error) {
// Assume only the first line is important.
tokens := strings.Fields(lines[0])
if len(tokens) == 0 {
- return nil, NewNewtError("Invalid Makefile dependency file; first " +
+ return nil, util.NewNewtError("Invalid Makefile dependency file; first " +
"line is blank")
}
dFileTok := tokens[0]
if dFileTok[len(dFileTok)-1:] != ":" {
- return nil, NewNewtError("Invalid Makefile dependency file; first " +
+ return nil, util.NewNewtError("Invalid Makefile dependency file; first " +
"line missing ':'")
}
@@ -82,7 +85,7 @@ func ParseDepsFile(filename string) ([]string, error) {
// modification time of the specified file. If the specified file is older
// than the tracker's currently most-recent time, this function has no effect.
func (tracker *DepTracker) ProcessFileTime(file string) error {
- modTime, err := FileModificationTime(file)
+ modTime, err := cli.FileModificationTime(file)
if err != nil {
return err
}
@@ -94,6 +97,31 @@ func (tracker *DepTracker) ProcessFileTime(file string) error {
return nil
}
+// Determines if a file was previously built with a command line invocation
+// different from the one specified.
+//
+// @param dstFile The output file whose build invocation is being
+// tested.
+// @param cmd The command that would be used to generate the
+// specified destination file.
+//
+// @return true if the command has changed or if the
+// destination file was never built;
+// false otherwise.
+func commandHasChanged(dstFile string, cmd string) bool {
+ cmdFile := dstFile + ".cmd"
+ prevCmd, err := ioutil.ReadFile(cmdFile)
+ if err != nil {
+ return true
+ }
+
+ rc := bytes.Compare(prevCmd, []byte(cmd)) != 0
+ if rc {
+ cli.StatusMessage(util.VERBOSITY_VERBOSE, "oldcmd=%s\nnewcmd=%s\n", prevCmd, cmd)
+ }
+ return rc
+}
+
// Determines if the specified C or assembly file needs to be built. A compile
// is required if any of the following is true:
// * The destination object file does not exist.
@@ -118,17 +146,18 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
if err != nil {
return false, err
}
- if CommandHasChanged(objFile, cmd) {
- StatusMessage(VERBOSITY_VERBOSE, "%s - rebuild required; different command\n", srcFile)
+ if commandHasChanged(objFile, cmd) {
+ cli.StatusMessage(util.VERBOSITY_VERBOSE, "%s - rebuild required; "+
+ "different command\n", srcFile)
return true, nil
}
- srcModTime, err := FileModificationTime(srcFile)
+ srcModTime, err := cli.FileModificationTime(srcFile)
if err != nil {
return false, err
}
- objModTime, err := FileModificationTime(objFile)
+ objModTime, err := cli.FileModificationTime(objFile)
if err != nil {
return false, err
}
@@ -136,14 +165,14 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
// If the object doesn't exist or is older than the source file, a build is
// required; no need to check dependencies.
if srcModTime.After(objModTime) {
- StatusMessage(VERBOSITY_VERBOSE, "%s - rebuild required; source newer than obj\n", srcFile)
+ cli.StatusMessage(util.VERBOSITY_VERBOSE, "%s - rebuild required; source newer than obj\n", srcFile)
return true, nil
}
// Determine if the dependency (.d) file needs to be generated. If it
// doesn't exist or is older than the source file, it is out of date and
// needs to be created.
- depModTime, err := FileModificationTime(depFile)
+ depModTime, err := cli.FileModificationTime(depFile)
if err != nil {
return false, err
}
@@ -163,7 +192,7 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
// Check if any dependencies are newer than the destination object file.
for _, dep := range deps {
- if NodeNotExist(dep) {
+ if cli.NodeNotExist(dep) {
// The dependency has been deleted; the .d file is out of date.
// Recreate the dependency file and repeat this entire function.
err := tracker.compiler.GenDepsForFile(srcFile)
@@ -173,14 +202,14 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
return tracker.CompileRequired(srcFile, compilerType)
} else {
- depModTime, err = FileModificationTime(dep)
+ depModTime, err = cli.FileModificationTime(dep)
if err != nil {
return false, err
}
}
if depModTime.After(objModTime) {
- StatusMessage(VERBOSITY_VERBOSE, "%s - rebuild required; obj older than dependency (%s)\n", srcFile, dep)
+ cli.StatusMessage(util.VERBOSITY_VERBOSE, "%s - rebuild required; obj older than dependency (%s)\n", srcFile, dep)
return true, nil
}
}
@@ -201,13 +230,13 @@ func (tracker *DepTracker) ArchiveRequired(archiveFile string,
// If the archive was previously built with a different set of options, a
// rebuild is required.
cmd := tracker.compiler.CompileArchiveCmd(archiveFile, objFiles)
- if CommandHasChanged(archiveFile, cmd) {
+ if commandHasChanged(archiveFile, cmd) {
return true, nil
}
// If the archive doesn't exist or is older than any object file, a rebuild
// is required.
- aModTime, err := FileModificationTime(archiveFile)
+ aModTime, err := cli.FileModificationTime(archiveFile)
if err != nil {
return false, err
}
@@ -235,13 +264,13 @@ func (tracker *DepTracker) LinkRequired(dstFile string,
// If the elf file was previously built with a different set of options, a
// rebuild is required.
cmd := tracker.compiler.CompileBinaryCmd(dstFile, options, objFiles)
- if CommandHasChanged(dstFile, cmd) {
+ if commandHasChanged(dstFile, cmd) {
return true, nil
}
// If the elf file doesn't exist or is older than any input file, a rebuild
// is required.
- dstModTime, err := FileModificationTime(dstFile)
+ dstModTime, err := cli.FileModificationTime(dstFile)
if err != nil {
return false, err
}
@@ -256,7 +285,7 @@ func (tracker *DepTracker) LinkRequired(dstFile string,
objFiles = append(objFiles, tracker.compiler.LinkerScript)
}
for _, obj := range objFiles {
- objModTime, err := FileModificationTime(obj)
+ objModTime, err := cli.FileModificationTime(obj)
if err != nil {
return false, err
}