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/09/13 03:42:00 UTC

incubator-mynewt-newt git commit: newt syscfg / sysinit.

Repository: incubator-mynewt-newt
Updated Branches:
  refs/heads/sterly_refactor [created] 0ae71ef1a


newt syscfg / sysinit.


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/0ae71ef1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/0ae71ef1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/0ae71ef1

Branch: refs/heads/sterly_refactor
Commit: 0ae71ef1a900bba44936069d053f90d8797c8650
Parents: 0baf3a3
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Sep 12 20:35:34 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Sep 12 20:35:34 2016 -0700

----------------------------------------------------------------------
 newt/Godeps/Godeps.json                         |  14 +-
 newt/builder/build.go                           | 270 ++++---
 newt/builder/buildpackage.go                    | 102 +--
 newt/builder/buildutil.go                       |  36 +-
 newt/builder/load.go                            |   3 +-
 newt/builder/targetbuild.go                     |  12 +-
 newt/cli/build_cmds.go                          | 127 ++-
 newt/cli/complete_cmd.go                        |  32 +-
 newt/cli/target_cmds.go                         | 109 ++-
 newt/newt.go                                    |   8 +-
 newt/newtutil/newtutil.go                       |  72 +-
 newt/pkg/localpackage.go                        |  62 +-
 newt/pkg/package.go                             |   5 +-
 newt/pkg/packageutil.go                         |  32 +
 newt/project/project.go                         |   2 -
 newt/syscfg/syscfg.go                           | 801 +++++++++++++++++++
 newt/sysinit/sysinit.go                         | 154 ++++
 newt/toolchain/compiler.go                      |   6 +-
 newt/toolchain/deps.go                          |   8 +
 newt/vendor/mynewt.apache.org/newt/DISCLAIMER   |   8 -
 newt/vendor/mynewt.apache.org/newt/LICENSE      | 244 ------
 newt/vendor/mynewt.apache.org/newt/NOTICE       |   8 -
 newt/vendor/mynewt.apache.org/newt/util/util.go |  21 +
 23 files changed, 1556 insertions(+), 580 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/Godeps/Godeps.json
----------------------------------------------------------------------
diff --git a/newt/Godeps/Godeps.json b/newt/Godeps/Godeps.json
index cf4c345..4dcc675 100644
--- a/newt/Godeps/Godeps.json
+++ b/newt/Godeps/Godeps.json
@@ -1,7 +1,7 @@
 {
 	"ImportPath": "mynewt.apache.org/newt/newt",
 	"GoVersion": "go1.6",
-	"GodepVersion": "v74",
+	"GodepVersion": "v58",
 	"Deps": [
 		{
 			"ImportPath": "github.com/Sirupsen/logrus",
@@ -52,18 +52,18 @@
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/util",
-			"Comment": "mynewt_0_9_0_rc3_tag-91-g904f79b",
-			"Rev": "904f79b15feeefe76a9e4ecc139c56fd54aa4412"
+			"Comment": "mynewt_0_9_0_tag-139-g8dddcf6",
+			"Rev": "8dddcf664861e0904e4c89b2bb4c2d498d4cb3a2"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/viper",
-			"Comment": "mynewt_0_9_0_rc3_tag-91-g904f79b",
-			"Rev": "904f79b15feeefe76a9e4ecc139c56fd54aa4412"
+			"Comment": "mynewt_0_9_0_tag-139-g8dddcf6",
+			"Rev": "8dddcf664861e0904e4c89b2bb4c2d498d4cb3a2"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/yaml",
-			"Comment": "mynewt_0_9_0_rc3_tag-91-g904f79b",
-			"Rev": "904f79b15feeefe76a9e4ecc139c56fd54aa4412"
+			"Comment": "mynewt_0_9_0_tag-139-g8dddcf6",
+			"Rev": "8dddcf664861e0904e4c89b2bb4c2d498d4cb3a2"
 		}
 	]
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/builder/build.go
----------------------------------------------------------------------
diff --git a/newt/builder/build.go b/newt/builder/build.go
index b8cbd39..17b64d1 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -29,7 +29,10 @@ import (
 	log "github.com/Sirupsen/logrus"
 
 	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/symbol"
+	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/sysinit"
 	"mynewt.apache.org/newt/newt/target"
 	"mynewt.apache.org/newt/newt/toolchain"
 	"mynewt.apache.org/newt/util"
@@ -37,58 +40,31 @@ import (
 
 type Builder struct {
 	Packages         map[*pkg.LocalPackage]*BuildPackage
-	features         map[string]bool
 	apis             map[string]*BuildPackage
 	appPkg           *BuildPackage
 	BspPkg           *pkg.LocalPackage
 	compilerInfo     *toolchain.CompilerInfo
-	featureWhiteList []map[string]interface{}
-	featureBlackList []map[string]interface{}
 	target           *TargetBuilder
 	linkerScript     string
 	buildName        string
 	LinkElf          string
-}
-
-func NewBuilder(t *TargetBuilder, buildName string) (*Builder, error) {
-	b := &Builder{}
-
-	b.buildName = buildName
-	/* TODO */
-	b.Init(t)
-
-	return b, nil
-}
+	injectedSettings map[string]string
 
-func (b *Builder) Init(t *TargetBuilder) error {
-
-	b.target = t
-	b.Packages = map[*pkg.LocalPackage]*BuildPackage{}
-	b.features = map[string]bool{}
-	b.apis = map[string]*BuildPackage{}
-	b.LinkElf = ""
-
-	return nil
+	Cfg syscfg.Cfg
 }
 
-func (b *Builder) AllFeatures() map[string]bool {
-	return b.features
-}
-
-func (b *Builder) Features(pkg pkg.Package) map[string]bool {
-	featureList := map[string]bool{}
-
-	for fname, _ := range b.features {
-		if b.CheckValidFeature(pkg, fname) {
-			featureList[fname] = true
-		}
+func NewBuilder(t *TargetBuilder, buildName string) (*Builder, error) {
+	b := &Builder{
+		Packages:         map[*pkg.LocalPackage]*BuildPackage{},
+		buildName:        buildName,
+		apis:             map[string]*BuildPackage{},
+		LinkElf:          "",
+		target:           t,
+		injectedSettings: map[string]string{},
+		Cfg:              syscfg.Cfg{},
 	}
 
-	return featureList
-}
-
-func (b *Builder) AddFeature(feature string) {
-	b.features[feature] = true
+	return b, nil
 }
 
 func (b *Builder) AddPackage(npkg *pkg.LocalPackage) *BuildPackage {
@@ -122,29 +98,56 @@ func (b *Builder) AddApi(apiString string, bpkg *BuildPackage) bool {
 	}
 }
 
-func (b *Builder) loadDeps() error {
-	// Circularly resolve dependencies, identities, APIs, and required APIs
-	// until no new ones exist.
+func (b *Builder) ApiNames() []string {
+	apiNames := make([]string, len(b.apis), len(b.apis))
+
+	i := 0
+	for api, _ := range b.apis {
+		apiNames[i] = api
+		i += 1
+	}
+
+	return apiNames
+}
+
+// @return                      changed,err
+func (b *Builder) reloadCfg() (bool, error) {
+	apis := make([]string, len(b.apis))
+	i := 0
+	for api, _ := range b.apis {
+		apis[i] = api
+		i++
+	}
+
+	cfg, err := syscfg.Read(b.sortedLocalPackages(), apis, b.injectedSettings)
+	if err != nil {
+		return false, err
+	}
+
+	changed := false
+	for k, v := range cfg {
+		oldval, ok := b.Cfg[k]
+		if !ok || len(oldval.History) != len(v.History) {
+			b.Cfg = cfg
+			changed = true
+		}
+	}
+
+	return changed, nil
+}
+
+func (b *Builder) loadDepsOnce() (bool, error) {
+	// Circularly resolve dependencies, APIs, and required APIs until no new
+	// ones exist.
+	newDeps := false
 	for {
 		reprocess := false
 		for _, bpkg := range b.Packages {
-			newDeps, newFeatures, err := bpkg.Resolve(b)
+			newDeps, err := bpkg.Resolve(b, b.Cfg)
 			if err != nil {
-				return err
+				return false, err
 			}
 
-			if newFeatures {
-				// A new supported feature was discovered.  It is impossible
-				// to determine what new dependency and API requirements are
-				// generated as a result.  All packages need to be
-				// reprocessed.
-				for _, bpkg := range b.Packages {
-					bpkg.depsResolved = false
-					bpkg.apisSatisfied = false
-				}
-				reprocess = true
-				break
-			}
 			if newDeps {
 				// The new dependencies need to be processed.  Iterate again
 				// after this iteration completes.
@@ -157,6 +160,43 @@ func (b *Builder) loadDeps() error {
 		}
 	}
 
+	return newDeps, nil
+}
+
+func (b *Builder) loadDeps() error {
+	if _, err := b.loadDepsOnce(); err != nil {
+		return err
+	}
+
+	for {
+		cfgChanged, err := b.reloadCfg()
+		if err != nil {
+			return err
+		}
+		if cfgChanged {
+			// A new supported feature was discovered.  It is impossible
+			// to determine what new dependency and API requirements are
+			// generated as a result.  All packages need to be
+			// reprocessed.
+			for _, bpkg := range b.Packages {
+				bpkg.depsResolved = false
+				bpkg.apisSatisfied = false
+			}
+		}
+
+		newDeps, err := b.loadDepsOnce()
+		if err != nil {
+			return err
+		}
+
+		if !newDeps && !cfgChanged {
+			break
+		}
+	}
+
+	// Log the final syscfg.
+	syscfg.Log(b.Cfg)
+
 	return nil
 }
 
@@ -233,12 +273,6 @@ func (b *Builder) newCompiler(bpkg *BuildPackage,
 		c.AddInfo(ci)
 	}
 
-	// Specify all the source yml files as dependencies.  If a yml file has
-	// changed, a full rebuild is required.
-	for _, bp := range b.Packages {
-		c.AddDeps(bp.CfgFilenames()...)
-	}
-
 	return c, nil
 }
 
@@ -271,25 +305,10 @@ func (b *Builder) buildPackage(bpkg *BuildPackage) error {
 		srcDirs = append(srcDirs, srcDir)
 	}
 
-	// Build the package source in two phases:
-	// 1. Non-test code.
-	// 2. Test code (if the "test" feature is enabled).
-	//
-	// This is done in two passes because the structure of
-	// architecture-specific directories is different for normal code and test
-	// code, and not easy to generalize into a single operation:
-	//     * src/arch/<target-arch>
-	//     * src/test/arch/<target-arch>
 	for _, dir := range srcDirs {
-		if err = buildDir(dir, c, b.target.Bsp.Arch, []string{"test"}); err != nil {
+		if err = buildDir(dir, c, b.target.Bsp.Arch, nil); err != nil {
 			return err
 		}
-		if b.features["TEST"] {
-			testSrcDir := dir + "/test"
-			if err = buildDir(testSrcDir, c, b.target.Bsp.Arch, nil); err != nil {
-				return err
-			}
-		}
 	}
 
 	// Create a static library ("archive").
@@ -347,7 +366,7 @@ func (b *Builder) link(elfName string, linkerScript string,
 	}
 
 	if linkerScript != "" {
-		c.LinkerScript = b.target.Bsp.BasePath() + linkerScript
+		c.LinkerScript = b.target.Bsp.BasePath() + "/" + linkerScript
 	}
 	err = c.CompileElf(elfName, pkgNames, keepSymbols, b.LinkElf)
 	if err != nil {
@@ -363,9 +382,6 @@ func (b *Builder) link(elfName string, linkerScript string,
 func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 	bspPkg *pkg.LocalPackage, targetPkg *pkg.LocalPackage) error {
 
-	b.featureBlackList = []map[string]interface{}{}
-	b.featureWhiteList = []map[string]interface{}{}
-
 	// Seed the builder with the app (if present), bsp, and target packages.
 
 	b.BspPkg = bspPkg
@@ -377,9 +393,6 @@ func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 			appBpkg = b.AddPackage(appPkg)
 		}
 		b.appPkg = appBpkg
-
-		b.featureBlackList = append(b.featureBlackList, appBpkg.FeatureBlackList())
-		b.featureWhiteList = append(b.featureWhiteList, appBpkg.FeatureWhiteList())
 	}
 
 	bspBpkg := b.Packages[bspPkg]
@@ -388,14 +401,8 @@ func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 		bspBpkg = b.AddPackage(bspPkg)
 	}
 
-	b.featureBlackList = append(b.featureBlackList, bspPkg.FeatureBlackList())
-	b.featureWhiteList = append(b.featureWhiteList, bspPkg.FeatureWhiteList())
-
 	targetBpkg := b.AddPackage(targetPkg)
 
-	b.featureBlackList = append(b.featureBlackList, targetBpkg.FeatureBlackList())
-	b.featureWhiteList = append(b.featureWhiteList, targetBpkg.FeatureWhiteList())
-
 	// Populate the full set of packages to be built and resolve the feature
 	// set.
 	if err := b.loadDeps(); err != nil {
@@ -428,12 +435,12 @@ func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 	baseCi := toolchain.NewCompilerInfo()
 
 	// Target flags.
-	log.Debugf("Generating build flags for target %s", b.target.target.FullName())
+	log.Debugf("Generating build flags for target %s",
+		b.target.target.FullName())
 	targetCi, err := targetBpkg.CompilerInfo(b)
 	if err != nil {
 		return err
 	}
-
 	baseCi.AddCompilerInfo(targetCi)
 
 	// App flags.
@@ -443,6 +450,7 @@ func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 		if err != nil {
 			return err
 		}
+
 		baseCi.AddCompilerInfo(appCi)
 	}
 
@@ -468,6 +476,18 @@ func (b *Builder) PrepBuild(appPkg *pkg.LocalPackage,
 	// package being built are calculated.
 	b.compilerInfo = baseCi
 
+	lpkgs := b.sortedLocalPackages()
+	if err := syscfg.EnsureWritten(b.Cfg, lpkgs, b.ApiNames(),
+		targetPkg.BasePath()); err != nil {
+		return err
+	}
+
+	if err := sysinit.EnsureWritten(lpkgs, targetPkg.BasePath()); err != nil {
+		return err
+	}
+
+	b.compilerInfo = baseCi
+
 	return nil
 }
 
@@ -493,29 +513,11 @@ func (b *Builder) matchFeature(flist []map[string]interface{},
 	return false
 }
 
-func (b *Builder) CheckValidFeature(pkg pkg.Package,
-	feature string) bool {
-
-	// If the feature is not in the blacklist, automatically valid
-	if match := b.matchFeature(b.featureBlackList, pkg, feature); !match {
-		return true
-	}
-
-	// If it is in the blacklist, check if its in the whitelist
-	// if not, override the feature definition.
-	if match := b.matchFeature(b.featureWhiteList, pkg, feature); match {
-		return true
-	} else {
-		return false
-	}
-}
-
 func (b *Builder) AddCompilerInfo(info *toolchain.CompilerInfo) {
 	b.compilerInfo.AddCompilerInfo(info)
 }
 
 func (b *Builder) Build() error {
-
 	// Build the packages alphabetically to ensure a consistent order.
 	bpkgs := b.sortedBuildPackages()
 	for _, bpkg := range bpkgs {
@@ -555,32 +557,50 @@ func (b *Builder) TestLink(linkerScript string) error {
 	return nil
 }
 
-func (b *Builder) Test(p *pkg.LocalPackage) error {
+func (b *Builder) pkgWithPath(path string) *BuildPackage {
+	for _, p := range b.Packages {
+		if p.BasePath() == path {
+			return p
+		}
+	}
 
-	// Seed the builder with the package under test.
-	testBpkg := b.AddPackage(p)
+	return nil
+}
 
-	// Define the PKG_TEST symbol while the package under test is being
-	// compiled.  This symbol enables the appropriate main function that
-	// usually comes from an app.
-	testPkgCi, err := testBpkg.CompilerInfo(b)
-	if err != nil {
-		return err
+func (b *Builder) testOwner(p *BuildPackage) *BuildPackage {
+	if p.Type() != pkg.PACKAGE_TYPE_UNITTEST {
+		panic("Expected unittest package; got: " + p.Name())
 	}
-	testPkgCi.Cflags = append(testPkgCi.Cflags, "-DMYNEWT_SELFTEST")
 
+	curPath := p.BasePath()
+
+	for {
+		parentPath := filepath.Dir(curPath)
+		if parentPath == project.GetProject().BasePath || parentPath == "." {
+			return nil
+		}
+
+		parentPkg := b.pkgWithPath(parentPath)
+		if parentPkg != nil && parentPkg.Type() != pkg.PACKAGE_TYPE_UNITTEST {
+			log.Debugf("OWNER=%s", parentPkg.Name())
+			return parentPkg
+		}
+
+		curPath = parentPath
+	}
+}
+
+func (b *Builder) Test(p *pkg.LocalPackage) error {
 	// Build the packages alphabetically to ensure a consistent order.
 	bpkgs := b.sortedBuildPackages()
 	for _, bpkg := range bpkgs {
-		err = b.buildPackage(bpkg)
-		if err != nil {
+		if err := b.buildPackage(bpkg); err != nil {
 			return err
 		}
 	}
 
 	testFilename := b.TestExePath(p.Name())
-	err = b.link(testFilename, "", nil)
-	if err != nil {
+	if err := b.link(testFilename, "", nil); err != nil {
 		return err
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/builder/buildpackage.go
----------------------------------------------------------------------
diff --git a/newt/builder/buildpackage.go b/newt/builder/buildpackage.go
index b2d59fe..2cdd75b 100644
--- a/newt/builder/buildpackage.go
+++ b/newt/builder/buildpackage.go
@@ -30,6 +30,7 @@ import (
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/newt/toolchain"
 	"mynewt.apache.org/newt/util"
 )
@@ -139,20 +140,21 @@ func (bpkg *BuildPackage) CompilerInfo(b *Builder) (*toolchain.CompilerInfo, err
 	}
 
 	ci := toolchain.NewCompilerInfo()
-	ci.Cflags = newtutil.GetStringSliceFeatures(bpkg.Viper, b.Features(bpkg),
+	features := syscfg.FeaturesForLpkg(b.Cfg, bpkg.LocalPackage)
+	ci.Cflags = newtutil.GetStringSliceFeatures(bpkg.Viper, features,
 		"pkg.cflags")
-	ci.Lflags = newtutil.GetStringSliceFeatures(bpkg.Viper, b.Features(bpkg),
+	ci.Lflags = newtutil.GetStringSliceFeatures(bpkg.Viper, features,
 		"pkg.lflags")
-	ci.Aflags = newtutil.GetStringSliceFeatures(bpkg.Viper, b.Features(bpkg),
+	ci.Aflags = newtutil.GetStringSliceFeatures(bpkg.Viper, features,
 		"pkg.aflags")
 
-	for fname, _ := range b.Features(bpkg) {
-		ci.Cflags = append(ci.Cflags, fmt.Sprintf("-DFEATURE_%s", fname))
+	for k, _ := range bpkg.InjectedSettings() {
+		ci.Cflags = append(ci.Cflags, syscfg.FeatureToCflag(k))
 	}
 
 	ci.IgnoreFiles = []*regexp.Regexp{}
 	ignPats := newtutil.GetStringSliceFeatures(bpkg.Viper,
-		b.Features(bpkg), "pkg.ign_files")
+		features, "pkg.ign_files")
 	for _, str := range ignPats {
 		re, err := regexp.Compile(str)
 		if err != nil {
@@ -164,7 +166,7 @@ func (bpkg *BuildPackage) CompilerInfo(b *Builder) (*toolchain.CompilerInfo, err
 
 	ci.IgnoreDirs = []*regexp.Regexp{}
 	ignPats = newtutil.GetStringSliceFeatures(bpkg.Viper,
-		b.Features(bpkg), "pkg.ign_dirs")
+		features, "pkg.ign_dirs")
 	for _, str := range ignPats {
 		re, err := regexp.Compile(str)
 		if err != nil {
@@ -175,38 +177,19 @@ func (bpkg *BuildPackage) CompilerInfo(b *Builder) (*toolchain.CompilerInfo, err
 	}
 
 	bpkg.SourceDirectories = newtutil.GetStringSliceFeatures(bpkg.Viper,
-		b.Features(bpkg), "pkg.src_dirs")
+		features, "pkg.src_dirs")
 
 	includePaths, err := bpkg.recursiveIncludePaths(b)
 	if err != nil {
 		return nil, err
 	}
+
 	ci.Includes = append(bpkg.privateIncludeDirs(b), includePaths...)
 	bpkg.ci = ci
 
 	return bpkg.ci, nil
 }
 
-func (bpkg *BuildPackage) loadFeatures(b *Builder) (map[string]bool, bool) {
-	features := b.AllFeatures()
-
-	foundNewFeature := false
-
-	newFeatures := newtutil.GetStringSliceFeatures(bpkg.Viper, features,
-		"pkg.features")
-	for _, nfeature := range newFeatures {
-		_, ok := features[nfeature]
-		if !ok {
-			b.AddFeature(nfeature)
-			foundNewFeature = true
-			log.Debugf("Detected new feature: %s (%s)", nfeature,
-				bpkg.Name())
-		}
-	}
-
-	return b.Features(bpkg), foundNewFeature
-}
-
 // Searches for a package which can satisfy bpkg's API requirement.  If such a
 // package is found, bpkg's API requirement is marked as satisfied, and the
 // package is added to bpkg's dependency list.
@@ -270,8 +253,7 @@ func (bpkg *BuildPackage) loadDeps(b *Builder,
 
 	// Determine if this package supports any APIs that we haven't seen
 	// yet.  If so, another full iteration is required.
-	apis := newtutil.GetStringSliceFeatures(bpkg.Viper, b.Features(bpkg),
-		"pkg.apis")
+	apis := newtutil.GetStringSliceFeatures(bpkg.Viper, features, "pkg.apis")
 	for _, api := range apis {
 		newApi := b.AddApi(api, bpkg)
 		if newApi {
@@ -285,7 +267,9 @@ func (bpkg *BuildPackage) loadDeps(b *Builder,
 // @return bool                 true if a new dependency was detected as a
 //                                  result of satisfying an API for this
 //                                  package.
-func (bpkg *BuildPackage) satisfyApis(b *Builder) bool {
+func (bpkg *BuildPackage) satisfyApis(b *Builder,
+	features map[string]bool) bool {
+
 	// Assume all this package's APIs are satisfied and that no new
 	// dependencies will be detected.
 	bpkg.apisSatisfied = true
@@ -293,7 +277,7 @@ func (bpkg *BuildPackage) satisfyApis(b *Builder) bool {
 
 	// Determine if any of the package's API requirements can now be satisfied.
 	// If so, another full iteration is required.
-	reqApis := newtutil.GetStringSliceFeatures(bpkg.Viper, b.Features(bpkg),
+	reqApis := newtutil.GetStringSliceFeatures(bpkg.Viper, features,
 		"pkg.req_apis")
 	for _, reqApi := range reqApis {
 		reqStatus, ok := bpkg.reqApiMap[reqApi]
@@ -364,19 +348,25 @@ func (bpkg *BuildPackage) privateIncludeDirs(b *Builder) []string {
 	incls = append(incls, srcDir)
 	incls = append(incls, srcDir+"/arch/"+b.target.Bsp.Arch)
 
-	if b.Features(bpkg)["TEST"] {
-		testSrcDir := srcDir + "/test"
-		incls = append(incls, testSrcDir)
-		incls = append(incls, testSrcDir+"/arch/"+b.target.Bsp.Arch)
-	}
-
-	// If pkgType == SDK, include all the items in "ext" directly into the
-	// include path
-	if bpkg.Type() == pkg.PACKAGE_TYPE_SDK {
+	switch bpkg.Type() {
+	case pkg.PACKAGE_TYPE_SDK:
+		// If pkgType == SDK, include all the items in "ext" directly into the
+		// include path
 		incls = append(incls, b.target.Bsp.BasePath()+"/include/bsp/")
 
 		sdkIncls := bpkg.findSdkIncludes()
 		incls = append(incls, sdkIncls...)
+
+	case pkg.PACKAGE_TYPE_UNITTEST:
+		// A unittest package gets access to its parent package's private
+		// includes.
+		parentPkg := b.testOwner(bpkg)
+		if parentPkg != nil {
+			parentIncls := parentPkg.privateIncludeDirs(b)
+			incls = append(incls, parentIncls...)
+		}
+
+	default:
 	}
 
 	return incls
@@ -396,42 +386,38 @@ func (bpkg *BuildPackage) privateIncludeDirs(b *Builder) []string {
 //
 // @return bool                 true if >=1 dependencies were resolved
 //         bool                 true if >=1 new features were detected
-func (bpkg *BuildPackage) Resolve(b *Builder) (bool, bool, error) {
+func (bpkg *BuildPackage) Resolve(b *Builder,
+	cfg syscfg.Cfg) (bool, error) {
+
 	var err error
 	newDeps := false
-	newFeatures := false
 
-	if !bpkg.depsResolved {
-		var features map[string]bool
+	features := syscfg.FeaturesForLpkg(cfg, bpkg.LocalPackage)
 
-		features, newFeatures = bpkg.loadFeatures(b)
+	if !bpkg.depsResolved {
 		newDeps, err = bpkg.loadDeps(b, features)
 		if err != nil {
-			return false, false, err
+			return false, err
 		}
 
-		bpkg.depsResolved = !newFeatures && !newDeps
-
+		bpkg.depsResolved = !newDeps
 	}
 
 	if !bpkg.apisSatisfied {
-		newApiDep := bpkg.satisfyApis(b)
+		newApiDep := bpkg.satisfyApis(b, features)
 		if newApiDep {
 			newDeps = true
 		}
 	}
 
-	return newDeps, newFeatures, nil
-}
-
-func (bp *BuildPackage) Init(pkg *pkg.LocalPackage) {
-	bp.LocalPackage = pkg
-	bp.reqApiMap = map[string]reqApiStatus{}
+	return newDeps, nil
 }
 
 func NewBuildPackage(pkg *pkg.LocalPackage) *BuildPackage {
-	bpkg := &BuildPackage{}
-	bpkg.Init(pkg)
+	bpkg := &BuildPackage{
+		LocalPackage: pkg,
+		reqApiMap:    map[string]reqApiStatus{},
+	}
 
 	return bpkg
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/builder/buildutil.go
----------------------------------------------------------------------
diff --git a/newt/builder/buildutil.go b/newt/builder/buildutil.go
index ca5a157..f35a1db 100644
--- a/newt/builder/buildutil.go
+++ b/newt/builder/buildutil.go
@@ -23,10 +23,13 @@ import (
 	"bytes"
 	"path/filepath"
 	"sort"
+	"strings"
 
 	log "github.com/Sirupsen/logrus"
 
+	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -77,25 +80,27 @@ func (b *Builder) AppBinBasePath() string {
 	return b.PkgBinDir(pkgName) + "/" + filepath.Base(pkgName)
 }
 
+func TestTargetName(testPkgName string) string {
+	return strings.Replace(testPkgName, "/", "_", -1)
+}
+
 func (b *Builder) TestExePath(pkgName string) string {
-	return b.PkgBinDir(pkgName) + "/test_" + filepath.Base(pkgName)
+	return b.PkgBinDir(pkgName) + "/" + TestTargetName(pkgName)
 }
 
 func (b *Builder) FeatureString() string {
 	var buffer bytes.Buffer
 
-	features := make([]string, 0, len(b.Features(nil)))
-	for f, _ := range b.Features(nil) {
-		features = append(features, f)
+	featureMap := syscfg.Features(b.Cfg)
+	featureSlice := make([]string, 0, len(featureMap))
+	for k, _ := range featureMap {
+		featureSlice = append(featureSlice, k)
 	}
-	sort.Strings(features)
+	sort.Strings(featureSlice)
 
-	first := true
-	for _, feature := range features {
-		if !first {
+	for i, feature := range featureSlice {
+		if i != 0 {
 			buffer.WriteString(" ")
-		} else {
-			first = false
 		}
 
 		buffer.WriteString(feature)
@@ -168,6 +173,17 @@ func (b *Builder) sortedBuildPackages() []*BuildPackage {
 	return sorter.bpkgs
 }
 
+func (b *Builder) sortedLocalPackages() []*pkg.LocalPackage {
+	bpkgs := b.sortedBuildPackages()
+
+	lpkgs := make([]*pkg.LocalPackage, len(bpkgs), len(bpkgs))
+	for i, bpkg := range bpkgs {
+		lpkgs[i] = bpkg.LocalPackage
+	}
+
+	return lpkgs
+}
+
 func (b *Builder) logDepInfo() {
 	// Log feature set.
 	log.Debugf("Feature set: [" + b.FeatureString() + "]")

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/builder/load.go
----------------------------------------------------------------------
diff --git a/newt/builder/load.go b/newt/builder/load.go
index 0c1a85b..9596532 100644
--- a/newt/builder/load.go
+++ b/newt/builder/load.go
@@ -25,6 +25,7 @@ import (
 	"path/filepath"
 
 	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -87,7 +88,7 @@ func (b *Builder) Load(image_slot int, extraJtagCmd string) error {
 	downloadCmd := fmt.Sprintf("%s %s %s %s", envSettings, downloadScript, bspPath,
 		binBaseName)
 
-	features := b.Features(nil)
+	features := syscfg.Features(b.Cfg)
 
 	if _, ok := features["bootloader"]; ok {
 		util.StatusMessage(util.VERBOSITY_DEFAULT,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/builder/targetbuild.go
----------------------------------------------------------------------
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 3d9d96b..96b43f0 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -27,6 +27,7 @@ import (
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"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"
@@ -156,7 +157,7 @@ func (t *TargetBuilder) Build() error {
 	/* Build the Apps */
 	project.ResetDeps(t.AppList)
 
-	if err := t.Bsp.Reload(t.App.Features(t.App.BspPkg)); err != nil {
+	if err := t.Bsp.Reload(syscfg.Features(t.App.Cfg)); err != nil {
 		return err
 	}
 
@@ -181,7 +182,7 @@ func (t *TargetBuilder) Build() error {
 	/* rebuild the loader */
 	project.ResetDeps(t.LoaderList)
 
-	if err = t.Bsp.Reload(t.Loader.Features(t.Loader.BspPkg)); err != nil {
+	if err = t.Bsp.Reload(syscfg.Features(t.Loader.Cfg)); err != nil {
 		return err
 	}
 
@@ -403,10 +404,11 @@ func (t *TargetBuilder) Test(p *pkg.LocalPackage) error {
 	// used:
 	//     * TEST:      ensures that the test code gets compiled.
 	//     * SELFTEST:  indicates that there is no app.
-	t.App.AddFeature("TEST")
-	t.App.AddFeature("SELFTEST")
+	t.App.injectedSettings["TEST"] = "1"
+	p.InjectedSettings()["SELFTEST"] = "1"
 
-	err = t.App.PrepBuild(p, bspPkg, targetPkg)
+	t.App.AddPackage(p)
+	err = t.App.PrepBuild(nil, bspPkg, targetPkg)
 
 	if err != nil {
 		return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/cli/build_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/build_cmds.go b/newt/cli/build_cmds.go
index bc19cf5..a26deb7 100644
--- a/newt/cli/build_cmds.go
+++ b/newt/cli/build_cmds.go
@@ -22,6 +22,7 @@ package cli
 import (
 	"fmt"
 	"os"
+	"path/filepath"
 
 	"github.com/spf13/cobra"
 	"mynewt.apache.org/newt/newt/builder"
@@ -33,12 +34,68 @@ import (
 
 const TARGET_TEST_NAME = "unittest"
 
-var extraJtagCmd string
+var testablePkgMap map[*pkg.LocalPackage]struct{}
+
+func testablePkgs() map[*pkg.LocalPackage]struct{} {
+	if testablePkgMap != nil {
+		return testablePkgMap
+	}
+
+	testablePkgMap := map[*pkg.LocalPackage]struct{}{}
+
+	// Create a map of path => lclPkg.
+	proj := project.GetProject()
+	allPkgs := proj.PackagesOfType(-1)
+	pathLpkgMap := make(map[string]*pkg.LocalPackage, len(allPkgs))
+	for _, p := range allPkgs {
+		lpkg := p.(*pkg.LocalPackage)
+		pathLpkgMap[lpkg.BasePath()] = lpkg
+	}
+
+	// Add all unit test packages to the testable package map.
+	testPkgs := proj.PackagesOfType(pkg.PACKAGE_TYPE_UNITTEST)
+	for _, p := range testPkgs {
+		lclPack := p.(*pkg.LocalPackage)
+		testablePkgMap[lclPack] = struct{}{}
+	}
+
+	// Next add first ancestor of each test package.
+	for testPkg, _ := range testablePkgMap {
+		for cur := filepath.Dir(testPkg.BasePath()); cur != proj.BasePath; cur = filepath.Dir(cur) {
+			lpkg := pathLpkgMap[cur]
+			if lpkg != nil && lpkg.Type() != pkg.PACKAGE_TYPE_UNITTEST {
+				testablePkgMap[lpkg] = struct{}{}
+				break
+			}
+		}
+	}
 
-func pkgIsTestable(pack *pkg.LocalPackage) bool {
-	return util.NodeExist(pack.BasePath() + "/src/test")
+	return testablePkgMap
 }
 
+func pkgToUnitTests(pack *pkg.LocalPackage) []*pkg.LocalPackage {
+	// If the user specified a unittest package, just test that one.
+	if pack.Type() == pkg.PACKAGE_TYPE_UNITTEST {
+		return []*pkg.LocalPackage{pack}
+	}
+
+	// Otherwise, return all the package's direct descendants that are unit
+	// test packages.
+	result := []*pkg.LocalPackage{}
+	srcPath := pack.BasePath()
+	for p, _ := range testablePkgs() {
+		if p.Type() == pkg.PACKAGE_TYPE_UNITTEST &&
+			filepath.Dir(p.BasePath()) == srcPath {
+
+			result = append(result, p)
+		}
+	}
+
+	return result
+}
+
+var extraJtagCmd string
+
 func buildRunCmd(cmd *cobra.Command, args []string) {
 	if err := project.Initialize(); err != nil {
 		NewtUsage(cmd, err)
@@ -132,10 +189,17 @@ func cleanRunCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
-func testRunCmd(cmd *cobra.Command, args []string) {
-	if err := project.Initialize(); err != nil {
-		NewtUsage(cmd, err)
+func pkgnames(pkgs []*pkg.LocalPackage) string {
+	s := ""
+
+	for _, p := range pkgs {
+		s += p.Name() + " "
 	}
+
+	return s
+}
+
+func testRunCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 1 {
 		NewtUsage(cmd, nil)
 	}
@@ -152,26 +216,26 @@ func testRunCmd(cmd *cobra.Command, args []string) {
 				NewtUsage(cmd, err)
 			}
 
-			if !pkgIsTestable(pack) {
+			testPkgs := pkgToUnitTests(pack)
+			if len(testPkgs) == 0 {
 				NewtUsage(nil, util.FmtNewtError("Package %s contains no "+
 					"unit tests", pack.FullName()))
 			}
 
-			packs = append(packs, pack)
+			packs = append(packs, testPkgs...)
 		}
 	}
 
+	proj := project.GetProject()
+
 	if testAll {
-		packs = []*pkg.LocalPackage{}
-		for _, repoHash := range project.GetProject().PackageList() {
-			for _, pack := range *repoHash {
-				lclPack := pack.(*pkg.LocalPackage)
-
-				if pkgIsTestable(lclPack) {
-					packs = append(packs, lclPack)
-				}
-			}
+		packItfs := proj.PackagesOfType(pkg.PACKAGE_TYPE_UNITTEST)
+		packs = make([]*pkg.LocalPackage, len(packItfs))
+		for i, p := range packItfs {
+			packs[i] = p.(*pkg.LocalPackage)
 		}
+
+		packs = pkg.SortLclPkgs(packs)
 	}
 
 	if len(packs) == 0 {
@@ -186,13 +250,36 @@ func testRunCmd(cmd *cobra.Command, args []string) {
 			NewtUsage(nil, err)
 		}
 
-		// Use the standard unit test target for all tests.
-		t := ResolveTarget(TARGET_TEST_NAME)
-		if t == nil {
+		// Each unit test package gets its own target.  This target is a copy
+		// of the base unit test package, just with an appropriate name.  The
+		// reason each test needs a unique target is: syscfg and sysinit are
+		// target-specific.  If each test package shares a target, they will
+		// overwrite these generated headers each time they are run.  Worse, if
+		// two tests are run back-to-back, the timestamps may indicate that the
+		// headers have not changed between tests, causing build failures.
+		baseTarget := ResolveTarget(TARGET_TEST_NAME)
+		if baseTarget == nil {
 			NewtUsage(nil, util.NewNewtError("Can't find unit test target: "+
 				TARGET_TEST_NAME))
 		}
 
+		targetName := fmt.Sprintf("%s/%s/%s",
+			TARGET_DEFAULT_DIR, TARGET_TEST_NAME,
+			builder.TestTargetName(pack.Name()))
+
+		t := ResolveTarget(targetName)
+		if t == nil {
+			targetName, err := ResolveNewTargetName(targetName)
+			if err != nil {
+				NewtUsage(nil, err)
+			}
+
+			t = baseTarget.Clone(proj.LocalRepo(), targetName)
+			if err := t.Save(); err != nil {
+				NewtUsage(nil, err)
+			}
+		}
+
 		b, err := builder.NewTargetBuilder(t)
 		if err != nil {
 			NewtUsage(nil, err)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/cli/complete_cmd.go
----------------------------------------------------------------------
diff --git a/newt/cli/complete_cmd.go b/newt/cli/complete_cmd.go
index c01410c..b2e83b6 100644
--- a/newt/cli/complete_cmd.go
+++ b/newt/cli/complete_cmd.go
@@ -54,35 +54,17 @@ func targetList() []string {
 	return targetNames
 }
 
-/* return a list of all packages */
+/* @return                      A slice of all testable package names. */
 func packageList() []string {
-
-	err := project.Initialize()
-
-	var list []string
-
-	if err != nil {
-		return list
-	}
-	for _, repoHash := range project.GetProject().PackageList() {
-		for _, pack := range *repoHash {
-			lclPack := pack.(*pkg.LocalPackage)
-
-			if pkgIsTestable(lclPack) {
-				list = append(list, lclPack.FullName())
-			}
+	packs := testablePkgs()
+	names := make([]string, 0, len(packs))
+	for pack, _ := range packs {
+		if pack.Type() != pkg.PACKAGE_TYPE_UNITTEST {
+			names = append(names, pack.FullName())
 		}
 	}
-	return list
-}
 
-func isValueInList(value string, list []string) int {
-	for i, v := range list {
-		if v == value {
-			return i
-		}
-	}
-	return -1
+	return names
 }
 
 func completeRunCmd(cmd *cobra.Command, args []string) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/cli/target_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go
index b9ebada..364fbaf 100644
--- a/newt/cli/target_cmds.go
+++ b/newt/cli/target_cmds.go
@@ -29,8 +29,10 @@ import (
 	"strings"
 
 	"github.com/spf13/cobra"
+	"mynewt.apache.org/newt/newt/builder"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/newt/target"
 	"mynewt.apache.org/newt/util"
 )
@@ -333,6 +335,90 @@ func targetCopyCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
+func printSetting(entry syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"  * Setting: %s\n", entry.Name)
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"    * Description: %s\n", entry.Description)
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"    * Value: %s", entry.Value)
+
+	unfixed := syscfg.UnfixedValue(entry)
+	if unfixed != entry.Value {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, " [%s]", unfixed)
+	}
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+
+	if len(entry.History) > 1 {
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"    * Overridden: ")
+		for i := 1; i < len(entry.History); i++ {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "%s, ",
+				entry.History[i].Source.Name())
+		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"default=%s\n", entry.History[0].Value)
+	}
+}
+
+func printPkgCfg(pkgName string, cfg syscfg.Cfg, entries []syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "* PACKAGE: %s\n", pkgName)
+
+	settingNames := make([]string, len(entries))
+	for i, entry := range entries {
+		settingNames[i] = entry.Name
+	}
+	sort.Strings(settingNames)
+
+	for _, name := range settingNames {
+		printSetting(cfg[name])
+	}
+}
+
+func printCfg(cfg syscfg.Cfg) {
+	pkgNameEntryMap := syscfg.EntriesByPkg(cfg)
+
+	pkgNames := make([]string, 0, len(pkgNameEntryMap))
+	for pkgName, _ := range pkgNameEntryMap {
+		pkgNames = append(pkgNames, pkgName)
+	}
+	sort.Strings(pkgNames)
+
+	for i, pkgName := range pkgNames {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printPkgCfg(pkgName, cfg, pkgNameEntryMap[pkgName])
+	}
+}
+
+func targetConfigCmd(cmd *cobra.Command, args []string) {
+	if err := project.Initialize(); err != nil {
+		NewtUsage(cmd, err)
+	}
+	if len(args) != 1 {
+		NewtUsage(cmd, util.NewNewtError("Must specify target name"))
+	}
+
+	t, err := resolveExistingTargetArg(args[0])
+	if err != nil {
+		NewtUsage(cmd, err)
+	}
+
+	b, err := builder.NewTargetBuilder(t)
+	if err != nil {
+		NewtUsage(nil, err)
+	}
+
+	if err := b.PrepBuild(); err != nil {
+		NewtUsage(nil, err)
+	}
+
+	printCfg(b.App.Cfg)
+}
+
 func AddTargetCommands(cmd *cobra.Command) {
 	targetHelpText := ""
 	targetHelpEx := ""
@@ -415,12 +501,25 @@ func AddTargetCommands(cmd *cobra.Command) {
 	copyHelpEx += "  newt target copy blinky_sim my_target"
 
 	copyCmd := &cobra.Command{
-		Use:     "copy",
-		Short:   "Copy target",
-		Long:    copyHelpText,
-		Example: copyHelpEx,
-		Run:     targetCopyCmd,
+		Use:       "copy",
+		Short:     "Copy target",
+		Long:      copyHelpText,
+		Example:   copyHelpEx,
+		Run:       targetCopyCmd,
+		ValidArgs: targetList(),
 	}
 
 	targetCmd.AddCommand(copyCmd)
+
+	configHelpText := "View a target's system configuration."
+
+	configCmd := &cobra.Command{
+		Use:       "config <target-name>",
+		Short:     "View target system configuration",
+		Long:      configHelpText,
+		Run:       targetConfigCmd,
+		ValidArgs: targetList(),
+	}
+
+	targetCmd.AddCommand(configCmd)
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/newt.go
----------------------------------------------------------------------
diff --git a/newt/newt.go b/newt/newt.go
index 03fb8de..f1e0c2d 100644
--- a/newt/newt.go
+++ b/newt/newt.go
@@ -28,6 +28,7 @@ import (
 
 	"mynewt.apache.org/newt/newt/cli"
 	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -114,13 +115,14 @@ func newtCmd() *cobra.Command {
 }
 
 func main() {
-
 	cmd := newtCmd()
 
 	/* some of the setup code logs which messes with autocomplete */
 	hold_lvl := log.GetLevel()
 	log.SetLevel(log.FatalLevel)
 
+	initErr := project.Initialize()
+
 	cli.AddCompleteCommands(cmd)
 	cli.AddProjectCommands(cmd)
 	cli.AddTargetCommands(cmd)
@@ -146,6 +148,10 @@ func main() {
 		cmd.SilenceUsage = false
 	}
 
+	if initErr != nil {
+		cli.NewtUsage(nil, initErr)
+	}
+
 	log.SetLevel(hold_lvl)
 	cmd.Execute()
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/newtutil/newtutil.go
----------------------------------------------------------------------
diff --git a/newt/newtutil/newtutil.go b/newt/newtutil/newtutil.go
index 42e68fb..947ab49 100644
--- a/newt/newtutil/newtutil.go
+++ b/newt/newtutil/newtutil.go
@@ -27,6 +27,8 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/spf13/cast"
+
 	"mynewt.apache.org/newt/util"
 	"mynewt.apache.org/newt/viper"
 )
@@ -34,6 +36,51 @@ import (
 var NewtVersionStr string = "Apache Newt (incubating) version: 0.9.0"
 var NewtBlinkyTag string = "mynewt_0_9_0_tag"
 
+func GetSliceFeatures(v *viper.Viper, features map[string]bool,
+	key string) []interface{} {
+
+	val := v.Get(key)
+	vals := []interface{}{val}
+
+	// Process the features in alphabetical order to ensure consistent
+	// results across repeated runs.
+	var featureKeys []string
+	for feature, _ := range features {
+		featureKeys = append(featureKeys, feature)
+	}
+	sort.Strings(featureKeys)
+
+	for _, feature := range featureKeys {
+		overwriteVal := v.Get(key + "." + feature + ".OVERWRITE")
+		if overwriteVal != nil {
+			return []interface{}{overwriteVal}
+		}
+
+		appendVal := v.Get(key + "." + feature)
+		if appendVal != nil {
+			vals = append(vals, appendVal)
+		}
+	}
+
+	return vals
+}
+
+func GetStringMapFeatures(v *viper.Viper, features map[string]bool,
+	key string) map[string]interface{} {
+
+	result := map[string]interface{}{}
+
+	slice := GetSliceFeatures(v, features, key)
+	for _, itf := range slice {
+		sub := cast.ToStringMap(itf)
+		for k, v := range sub {
+			result[k] = v
+		}
+	}
+
+	return result
+}
+
 func GetStringFeatures(v *viper.Viper, features map[string]bool,
 	key string) string {
 	val := v.GetString(key)
@@ -87,28 +134,15 @@ func GetBoolFeatures(v *viper.Viper, features map[string]bool,
 func GetStringSliceFeatures(v *viper.Viper, features map[string]bool,
 	key string) []string {
 
-	val := v.GetStringSlice(key)
+	vals := GetSliceFeatures(v, features, key)
 
-	// string empty items
-	result := []string{}
-	for _, item := range val {
-		if item == "" || item == " " {
-			continue
-		}
-		result = append(result, item)
+	strVals := []string{}
+	for _, v := range vals {
+		subVals := cast.ToStringSlice(v)
+		strVals = append(strVals, subVals...)
 	}
 
-	for item, _ := range features {
-		overwriteVal := v.GetStringSlice(key + "." + item + ".OVERWRITE")
-		if overwriteVal != nil {
-			result = overwriteVal
-			break
-		}
-
-		result = append(result, v.GetStringSlice(key+"."+item)...)
-	}
-
-	return result
+	return strVals
 }
 
 // Parses a string of the following form:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/pkg/localpackage.go
----------------------------------------------------------------------
diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go
index 0e73d8d..86c5777 100644
--- a/newt/pkg/localpackage.go
+++ b/newt/pkg/localpackage.go
@@ -60,15 +60,15 @@ type LocalPackage struct {
 	desc *PackageDesc
 	// Dependencies for this package
 	deps []*Dependency
-	// APIs that this package exports
-	apis []string
-	// APIs that this package requires
-	reqApis []string
 
-	// This is only used for top-level packages, but make no distinction
-	// and always read it in.
-	featureBlackList map[string]interface{}
-	featureWhiteList map[string]interface{}
+	// Package init function name and stage.  These are used to generate the
+	// sysinit C file.
+	initFnName string
+	initStage  int
+
+	// Extra package-specific settings that don't come from syscfg.  For
+	// example, SELFTEST gets set when the newt test command is used.
+	injectedSettings map[string]string
 
 	// Pointer to pkg.yml configuration structure
 	Viper *viper.Viper
@@ -82,8 +82,10 @@ func NewLocalPackage(r *repo.Repo, pkgDir string) *LocalPackage {
 		desc: &PackageDesc{},
 		// XXX: Initialize viper object; clients should not need to check for
 		// nil pointer.
+		repo:             r,
+		basePath:         filepath.Clean(pkgDir) + "/", // XXX: Remove slash.
+		injectedSettings: map[string]string{},
 	}
-	pkg.Init(r, pkgDir)
 	return pkg
 }
 
@@ -101,7 +103,7 @@ func (pkg *LocalPackage) FullName() string {
 }
 
 func (pkg *LocalPackage) BasePath() string {
-	return pkg.basePath
+	return filepath.Clean(pkg.basePath)
 }
 
 func (pkg *LocalPackage) Type() interfaces.PackageType {
@@ -201,22 +203,6 @@ func (pkg *LocalPackage) Deps() []*Dependency {
 	return pkg.deps
 }
 
-func (pkg *LocalPackage) AddApi(api string) {
-	pkg.apis = append(pkg.apis, api)
-}
-
-func (pkg *LocalPackage) Apis() []string {
-	return pkg.apis
-}
-
-func (pkg *LocalPackage) AddReqApi(api string) {
-	pkg.reqApis = append(pkg.reqApis, api)
-}
-
-func (pkg *LocalPackage) ReqApis() []string {
-	return pkg.reqApis
-}
-
 func (pkg *LocalPackage) readDesc(v *viper.Viper) (*PackageDesc, error) {
 	pdesc := &PackageDesc{}
 
@@ -228,11 +214,6 @@ func (pkg *LocalPackage) readDesc(v *viper.Viper) (*PackageDesc, error) {
 	return pdesc, nil
 }
 
-func (pkg *LocalPackage) Init(repo *repo.Repo, pkgDir string) {
-	pkg.repo = repo
-	pkg.basePath = filepath.Clean(pkgDir) + "/"
-}
-
 func (pkg *LocalPackage) sequenceString(key string) string {
 	var buffer bytes.Buffer
 
@@ -314,8 +295,8 @@ func (pkg *LocalPackage) Load() error {
 		}
 	}
 
-	pkg.featureBlackList = v.GetStringMap("pkg.feature_blacklist")
-	pkg.featureWhiteList = v.GetStringMap("pkg.feature_whitelist")
+	pkg.initFnName = v.GetString("pkg.init_function")
+	pkg.initStage = v.GetInt("pkg.init_stage")
 
 	// Read the package description from the file
 	pkg.desc, err = pkg.readDesc(v)
@@ -328,12 +309,16 @@ func (pkg *LocalPackage) Load() error {
 	return nil
 }
 
-func (pkg *LocalPackage) FeatureBlackList() map[string]interface{} {
-	return pkg.featureBlackList
+func (pkg *LocalPackage) InitStage() int {
+	return pkg.initStage
+}
+
+func (pkg *LocalPackage) InitFnName() string {
+	return pkg.initFnName
 }
 
-func (pkg *LocalPackage) FeatureWhiteList() map[string]interface{} {
-	return pkg.featureWhiteList
+func (pkg *LocalPackage) InjectedSettings() map[string]string {
+	return pkg.injectedSettings
 }
 
 func (pkg *LocalPackage) Clone(newRepo *repo.Repo,
@@ -356,8 +341,7 @@ func (pkg *LocalPackage) Clone(newRepo *repo.Repo,
 }
 
 func LoadLocalPackage(repo *repo.Repo, pkgDir string) (*LocalPackage, error) {
-	pkg := &LocalPackage{}
-	pkg.Init(repo, pkgDir)
+	pkg := NewLocalPackage(repo, pkgDir)
 	err := pkg.Load()
 	return pkg, err
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/pkg/package.go
----------------------------------------------------------------------
diff --git a/newt/pkg/package.go b/newt/pkg/package.go
index 4fa988c..644889e 100644
--- a/newt/pkg/package.go
+++ b/newt/pkg/package.go
@@ -1,5 +1,4 @@
 /**
-   PACKAGE_TYPE_LIB: "lib",
 * 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
@@ -16,7 +15,7 @@
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
-*/
+ */
 
 package pkg
 
@@ -37,6 +36,7 @@ const (
 	PACKAGE_TYPE_COMPILER
 	PACKAGE_TYPE_LIB
 	PACKAGE_TYPE_TARGET
+	PACKAGE_TYPE_UNITTEST
 )
 
 var PackageTypeNames = map[interfaces.PackageType]string{
@@ -46,6 +46,7 @@ var PackageTypeNames = map[interfaces.PackageType]string{
 	PACKAGE_TYPE_COMPILER: "compiler",
 	PACKAGE_TYPE_LIB:      "lib",
 	PACKAGE_TYPE_TARGET:   "target",
+	PACKAGE_TYPE_UNITTEST: "unittest",
 }
 
 // An interface, representing information about a Package

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/pkg/packageutil.go
----------------------------------------------------------------------
diff --git a/newt/pkg/packageutil.go b/newt/pkg/packageutil.go
new file mode 100644
index 0000000..f3f6132
--- /dev/null
+++ b/newt/pkg/packageutil.go
@@ -0,0 +1,32 @@
+package pkg
+
+import (
+	"sort"
+)
+
+type lpkgSorter struct {
+	pkgs []*LocalPackage
+}
+
+func (s lpkgSorter) Len() int {
+	return len(s.pkgs)
+}
+func (s lpkgSorter) Swap(i, j int) {
+	s.pkgs[i], s.pkgs[j] = s.pkgs[j], s.pkgs[i]
+}
+func (s lpkgSorter) Less(i, j int) bool {
+	return s.pkgs[i].Name() < s.pkgs[j].Name()
+}
+
+func SortLclPkgs(pkgs []*LocalPackage) []*LocalPackage {
+	sorter := lpkgSorter{
+		pkgs: make([]*LocalPackage, 0, len(pkgs)),
+	}
+
+	for _, p := range pkgs {
+		sorter.pkgs = append(sorter.pkgs, p)
+	}
+
+	sort.Sort(sorter)
+	return sorter.pkgs
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/project/project.go
----------------------------------------------------------------------
diff --git a/newt/project/project.go b/newt/project/project.go
index 78585af..29646e5 100644
--- a/newt/project/project.go
+++ b/newt/project/project.go
@@ -497,7 +497,6 @@ func findProjectDir(dir string) (string, error) {
 
 		log.Debugf("Searching for project file %s", projFile)
 		if util.NodeExist(projFile) {
-			log.Infof("Project file found at %s", projFile)
 			break
 		}
 
@@ -518,7 +517,6 @@ func (proj *Project) loadPackageList() error {
 	// packages / store them in the project package list.
 	repos := proj.Repos()
 	for name, repo := range repos {
-		log.Debugf("Loading packages in repository %s", repo.Path())
 		list, err := pkg.ReadLocalPackages(repo, repo.Path())
 		if err != nil {
 			return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/syscfg/syscfg.go
----------------------------------------------------------------------
diff --git a/newt/syscfg/syscfg.go b/newt/syscfg/syscfg.go
new file mode 100644
index 0000000..c94abfb
--- /dev/null
+++ b/newt/syscfg/syscfg.go
@@ -0,0 +1,801 @@
+/**
+ * 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 syscfg
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/spf13/cast"
+
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/util"
+)
+
+const SYSCFG_INCLUDE_SUBDIR = "include/syscfg"
+const SYSCFG_HEADER_FILENAME = "syscfg.h"
+
+const SYSCFG_PREFIX_API = "MYNEWT_API_"
+const SYSCFG_PREFIX_PKG = "MYNEWT_PKG_"
+const SYSCFG_PREFIX_SETTING = "MYNEWT_VAL_"
+
+type CfgSettingType int
+
+const (
+	CFG_SETTING_TYPE_RAW CfgSettingType = iota
+	CFG_SETTING_TYPE_TASK_PRIO
+	CFG_SETTING_TYPE_INTERRUPT_PRIO
+)
+
+const SYSCFG_PRIO_ANY = "any"
+
+// Reserve last 16 priorities for the system (sanity, idle).
+const SYSCFG_TASK_PRIO_MAX = 0xef
+
+// The range of interrupt priorities is hardware dependent, so don't limit
+// these here.
+const SYSCFG_INTERRUPT_PRIO_MAX = 0xffffffff
+
+var cfgSettingNameTypeMap = map[string]CfgSettingType{
+	"raw":                CFG_SETTING_TYPE_RAW,
+	"task_priority":      CFG_SETTING_TYPE_TASK_PRIO,
+	"interrupt_priority": CFG_SETTING_TYPE_INTERRUPT_PRIO,
+}
+
+type CfgPoint struct {
+	Value  string
+	Source *pkg.LocalPackage
+}
+
+type CfgEntry struct {
+	Name        string
+	Value       string
+	History     []CfgPoint
+	Description string
+	SettingType CfgSettingType
+}
+
+type Cfg map[string]CfgEntry
+
+type cfgRoster struct {
+	settings    map[string]string
+	pkgsPresent map[string]bool
+	apisPresent map[string]bool
+}
+
+func WritePreamble(w io.Writer) {
+	fmt.Fprintf(w, "/**\n * This file was generated by %s\n */\n\n",
+		newtutil.NewtVersionStr)
+}
+
+func ValueIsTrue(val string) bool {
+	if val == "" {
+		return false
+	}
+
+	i, err := util.AtoiNoOct(val)
+	if err == nil && i == 0 {
+		return false
+	}
+
+	return true
+}
+
+func Features(cfg Cfg) map[string]bool {
+	features := map[string]bool{}
+	for k, v := range cfg {
+		if v.IsTrue() {
+			features[k] = true
+		}
+	}
+
+	return features
+}
+
+func FeaturesForLpkg(cfg Cfg, lpkg *pkg.LocalPackage) map[string]bool {
+	features := Features(cfg)
+
+	for k, v := range lpkg.InjectedSettings() {
+		_, ok := features[k]
+		if ok {
+			log.Warnf("Attempt to override syscfg setting %s with "+
+				"injected feature from package %s", k, lpkg.Name())
+		} else {
+			if ValueIsTrue(v) {
+				features[k] = true
+			}
+		}
+	}
+
+	return features
+}
+
+func (point CfgPoint) Name() string {
+	if point.Source == nil {
+		return "newt"
+	} else {
+		return point.Source.Name()
+	}
+}
+
+func (entry *CfgEntry) IsTrue() bool {
+	return ValueIsTrue(entry.Value)
+}
+
+func appendValue(entry *CfgEntry, lpkg *pkg.LocalPackage, value interface{}) {
+	strval := fmt.Sprintf("%+v", value)
+	point := CfgPoint{Value: strval, Source: lpkg}
+	entry.History = append(entry.History, point)
+	entry.Value = strval
+}
+
+func FeatureToCflag(featureName string) string {
+	return fmt.Sprintf("-D%s=1", settingName(featureName))
+}
+
+func stringValue(val interface{}) string {
+	return strings.TrimSpace(cast.ToString(val))
+}
+
+func readSetting(name string, lpkg *pkg.LocalPackage,
+	vals map[interface{}]interface{}) (CfgEntry, error) {
+
+	entry := CfgEntry{}
+
+	entry.Name = name
+	entry.Description = stringValue(vals["description"])
+	entry.Value = stringValue(vals["value"])
+	if vals["type"] == nil {
+		entry.SettingType = CFG_SETTING_TYPE_RAW
+	} else {
+		var ok bool
+		typename := stringValue(vals["type"])
+		entry.SettingType, ok = cfgSettingNameTypeMap[typename]
+		if !ok {
+			return entry, util.FmtNewtError(
+				"setting %s specifies invalid type: %s", name, typename)
+		}
+	}
+
+	appendValue(&entry, lpkg, entry.Value)
+
+	return entry, nil
+}
+
+func readOnce(cfg Cfg, lpkg *pkg.LocalPackage) error {
+	v := lpkg.Viper
+
+	features := FeaturesForLpkg(cfg, lpkg)
+	settings := newtutil.GetStringMapFeatures(v, features, "pkg.syscfg_defs")
+	if settings != nil {
+		for k, v := range settings {
+			vals := v.(map[interface{}]interface{})
+			entry, err := readSetting(k, lpkg, vals)
+			if err != nil {
+				return util.FmtNewtError("Config for package %s: %s",
+					lpkg.Name(), err.Error())
+			}
+
+			if _, exists := cfg[k]; exists {
+				// XXX: Better error message.
+				return util.FmtNewtError("setting %s redefined", k)
+			}
+			cfg[k] = entry
+		}
+	}
+
+	values := newtutil.GetStringMapFeatures(v, features, "pkg.syscfg_vals")
+	if values != nil {
+		for k, v := range values {
+			entry, ok := cfg[k]
+			if ok {
+				appendValue(&entry, lpkg, v)
+				cfg[k] = entry
+			} else {
+				log.Warnf("ignoring override of undefined setting; "+
+					"%s sets %s=%+v", lpkg.Name(), k, v)
+			}
+
+		}
+	}
+
+	return nil
+}
+
+func Log(cfg Cfg) {
+	keys := make([]string, len(cfg))
+	i := 0
+	for k, _ := range cfg {
+		keys[i] = k
+		i++
+	}
+	sort.Strings(keys)
+
+	log.Debugf("syscfg settings (%d entries):", len(cfg))
+	for _, k := range keys {
+		entry := cfg[k]
+
+		str := fmt.Sprintf("    %s=%s [", k, entry.Value)
+
+		for i, p := range entry.History {
+			if i != 0 {
+				str += ", "
+			}
+			str += fmt.Sprintf("%s:%s", p.Name(), p.Value)
+		}
+		str += "]"
+
+		log.Debug(str)
+	}
+}
+
+func escapeStr(s string) string {
+	s = strings.Replace(s, "/", "_", -1)
+	s = strings.Replace(s, "-", "_", -1)
+	s = strings.Replace(s, " ", "_", -1)
+	s = strings.ToUpper(s)
+	return s
+}
+
+func isSettingVal(s string) bool {
+	return strings.HasPrefix(s, SYSCFG_PREFIX_SETTING)
+}
+
+func isPkgVal(s string) bool {
+	return strings.HasPrefix(s, SYSCFG_PREFIX_PKG)
+}
+
+func isApiVal(s string) bool {
+	return strings.HasPrefix(s, SYSCFG_PREFIX_API)
+}
+
+func settingName(setting string) string {
+	return SYSCFG_PREFIX_SETTING + escapeStr(setting)
+}
+
+func pkgPresentName(pkgName string) string {
+	return SYSCFG_PREFIX_PKG + escapeStr(pkgName)
+}
+
+func apiPresentName(apiName string) string {
+	return SYSCFG_PREFIX_API + strings.ToUpper(apiName)
+}
+
+func Read(lpkgs []*pkg.LocalPackage, apis []string,
+	injectedSettings map[string]string) (Cfg, error) {
+
+	cfg := Cfg{}
+	for k, v := range injectedSettings {
+		cfg[k] = CfgEntry{
+			Name:        k,
+			Description: "Injected setting",
+			Value:       v,
+			History: []CfgPoint{{
+				Value:  v,
+				Source: nil,
+			}},
+		}
+	}
+
+	// Read system configuration files.  In case of conflicting settings, the
+	// higher priority pacakge's setting wins.  Package priorities are assigned
+	// as follows (highest priority first):
+	//     * target
+	//     * app (if present)
+	//     * unittest (if no app)
+	//     * bsp
+
+	var app *pkg.LocalPackage
+	var bsp *pkg.LocalPackage
+	var target *pkg.LocalPackage
+	var unittest *pkg.LocalPackage
+
+	for _, lpkg := range lpkgs {
+		switch lpkg.Type() {
+		case pkg.PACKAGE_TYPE_LIB:
+			if err := readOnce(cfg, lpkg); err != nil {
+				return cfg, err
+			}
+
+		case pkg.PACKAGE_TYPE_APP:
+			app = lpkg
+
+		case pkg.PACKAGE_TYPE_BSP:
+			bsp = lpkg
+
+		case pkg.PACKAGE_TYPE_TARGET:
+			target = lpkg
+
+		case pkg.PACKAGE_TYPE_UNITTEST:
+			unittest = lpkg
+		}
+	}
+
+	if bsp != nil {
+		if err := readOnce(cfg, bsp); err != nil {
+			return cfg, err
+		}
+	}
+	if app != nil {
+		if err := readOnce(cfg, app); err != nil {
+			return cfg, err
+		}
+	} else if unittest != nil {
+		if err := readOnce(cfg, unittest); err != nil {
+			return cfg, err
+		}
+	}
+	if target != nil {
+		if err := readOnce(cfg, target); err != nil {
+			return cfg, err
+		}
+	}
+
+	roster := buildCfgRoster(cfg, lpkgs, apis)
+	if err := fixupSettings(cfg, roster); err != nil {
+		return cfg, err
+	}
+
+	return cfg, nil
+}
+
+func mostRecentPoint(entry CfgEntry) CfgPoint {
+	if len(entry.History) == 0 {
+		panic("invalid cfg entry; len(history) == 0")
+	}
+
+	return entry.History[len(entry.History)-1]
+}
+
+func calcPriorities(cfg Cfg, settingType CfgSettingType, max int,
+	allowDups bool) error {
+
+	// setting-name => entry
+	anyEntries := map[string]CfgEntry{}
+
+	// priority-value => entry
+	valEntries := map[int]CfgEntry{}
+
+	for name, entry := range cfg {
+		if entry.SettingType == settingType {
+			if entry.Value == SYSCFG_PRIO_ANY {
+				anyEntries[name] = entry
+			} else {
+				prio, err := util.AtoiNoOct(entry.Value)
+				if err != nil {
+					return util.FmtNewtError(
+						"invalid priority value: setting=%s value=%s pkg=%s",
+						name, entry.Value, entry.History[0].Name())
+				}
+
+				if prio > max {
+					return util.FmtNewtError(
+						"invalid priority value: value too great (> %d); "+
+							"setting=%s value=%s pkg=%s",
+						max, entry.Name, entry.Value,
+						mostRecentPoint(entry).Name())
+				}
+
+				if !allowDups {
+					if oldEntry, ok := valEntries[prio]; ok {
+						return util.FmtNewtError(
+							"duplicate priority value: setting1=%s "+
+								"setting2=%s pkg1=%s pkg2=%s value=%s",
+							oldEntry.Name, entry.Name, entry.Value,
+							oldEntry.History[0].Name(),
+							entry.History[0].Name())
+					}
+				}
+
+				valEntries[prio] = entry
+			}
+		}
+	}
+
+	greatest := 0
+	for prio, _ := range valEntries {
+		if prio > greatest {
+			greatest = prio
+		}
+	}
+
+	anyNames := make([]string, 0, len(anyEntries))
+	for name, _ := range anyEntries {
+		anyNames = append(anyNames, name)
+	}
+	sort.Strings(anyNames)
+
+	for _, name := range anyNames {
+		entry := anyEntries[name]
+
+		greatest++
+		if greatest > max {
+			return util.FmtNewtError("could not assign 'any' priority: "+
+				"value too great (> %d); setting=%s value=%s pkg=%s",
+				max, name, greatest,
+				mostRecentPoint(entry).Name())
+		}
+
+		entry.Value = strconv.Itoa(greatest)
+		cfg[name] = entry
+	}
+
+	return nil
+}
+
+func writeCheckMacros(w io.Writer) {
+	s := `/**
+ * These macros exists to ensure code includes this header when needed.  If
+ * code checks the existence of a setting directly via ifdef without including
+ * this header, the setting macro will silently evaluate to 0.  In contrast, an
+ * attempt to use these macros without including this header will result in a
+ * compiler error.
+ */
+#define MYNEWT_VAL(x)                           MYNEWT_VAL_ ## x
+#define MYNEWT_PKG(x)                           MYNEWT_PKG_ ## x
+#define MYNEWT_API(x)                           MYNEWT_API_ ## x
+`
+	fmt.Fprintf(w, "%s\n", s)
+}
+
+func writeComment(entry CfgEntry, w io.Writer) {
+	if len(entry.History) > 1 {
+		fmt.Fprintf(w, "/* Overridden by %s (defined by %s) */\n",
+			mostRecentPoint(entry).Name(),
+			entry.History[0].Name())
+	}
+}
+
+func writeDefine(key string, value string, w io.Writer) {
+	fmt.Fprintf(w, "#ifndef %s\n", key)
+	fmt.Fprintf(w, "#define %s (%s)\n", key, value)
+	fmt.Fprintf(w, "#endif\n")
+}
+
+func specialValues(cfg Cfg) (apis, pkgs, settings []string) {
+	for _, entry := range cfg {
+		if isApiVal(entry.Value) {
+			apis = append(apis, entry.Value)
+		} else if isPkgVal(entry.Value) {
+			pkgs = append(pkgs, entry.Value)
+		} else if isSettingVal(entry.Value) {
+			settings = append(settings, entry.Value)
+		}
+	}
+
+	return
+}
+
+func buildCfgRoster(cfg Cfg, lpkgs []*pkg.LocalPackage,
+	apis []string) cfgRoster {
+
+	roster := cfgRoster{
+		settings:    make(map[string]string, len(cfg)),
+		pkgsPresent: make(map[string]bool, len(lpkgs)),
+		apisPresent: make(map[string]bool, len(apis)),
+	}
+
+	for k, v := range cfg {
+		roster.settings[settingName(k)] = v.Value
+	}
+
+	for _, v := range lpkgs {
+		roster.pkgsPresent[pkgPresentName(v.Name())] = true
+	}
+
+	for _, v := range apis {
+		roster.apisPresent[apiPresentName(v)] = true
+	}
+
+	apisNotPresent, pkgsNotPresent, _ := specialValues(cfg)
+
+	for _, v := range apisNotPresent {
+		_, ok := roster.apisPresent[v]
+		if !ok {
+			roster.apisPresent[v] = false
+		}
+	}
+
+	for _, v := range pkgsNotPresent {
+		_, ok := roster.pkgsPresent[v]
+		if !ok {
+			roster.pkgsPresent[v] = false
+		}
+	}
+
+	return roster
+}
+
+func settingValueToConstant(value string,
+	roster cfgRoster) (string, bool, error) {
+
+	seen := map[string]struct{}{}
+	curVal := value
+	for {
+		v, ok := roster.settings[curVal]
+		if ok {
+			if _, ok := seen[v]; ok {
+				return "", false, util.FmtNewtError("Syscfg cycle detected: "+
+					"%s <==> %s", value, v)
+			}
+			seen[v] = struct{}{}
+			curVal = v
+		} else {
+			break
+		}
+	}
+	if curVal != value {
+		return curVal, true, nil
+	}
+
+	v, ok := roster.apisPresent[value]
+	if ok {
+		if v {
+			return "1", true, nil
+		} else {
+			return "0", true, nil
+		}
+	}
+
+	v, ok = roster.pkgsPresent[value]
+	if ok {
+		if v {
+			return "1", true, nil
+		} else {
+			return "0", true, nil
+		}
+	}
+
+	return value, false, nil
+}
+
+func fixupSettings(cfg Cfg, roster cfgRoster) error {
+	for k, entry := range cfg {
+		value, changed, err := settingValueToConstant(entry.Value, roster)
+		if err != nil {
+			return err
+		}
+
+		if changed {
+			entry.Value = value
+			cfg[k] = entry
+		}
+	}
+
+	return nil
+}
+
+func UnfixedValue(entry CfgEntry) string {
+	point := mostRecentPoint(entry)
+	return point.Value
+}
+
+func EntriesByPkg(cfg Cfg) map[string][]CfgEntry {
+	pkgEntries := map[string][]CfgEntry{}
+	for _, v := range cfg {
+		name := v.History[0].Name()
+		pkgEntries[name] = append(pkgEntries[name], v)
+	}
+	return pkgEntries
+}
+
+func writeSettingsOnePkg(cfg Cfg, pkgName string, pkgEntries []CfgEntry,
+	w io.Writer) {
+
+	fmt.Fprintf(w, "/*** %s */\n", pkgName)
+
+	names := make([]string, len(pkgEntries), len(pkgEntries))
+	for i, entry := range pkgEntries {
+		names[i] = entry.Name
+	}
+	sort.Strings(names)
+
+	first := true
+	for _, n := range names {
+		entry := cfg[n]
+		if entry.Value != "" {
+			if first {
+				first = false
+			} else {
+				fmt.Fprintf(w, "\n")
+			}
+
+			writeComment(entry, w)
+			writeDefine(settingName(n), entry.Value, w)
+		}
+	}
+}
+
+func writeSettings(cfg Cfg, w io.Writer) {
+	// Group settings by package name so that the generated header file is
+	// easier to readOnce.
+	pkgEntries := EntriesByPkg(cfg)
+	for _, v := range cfg {
+		name := v.History[0].Name()
+		pkgEntries[name] = append(pkgEntries[name], v)
+	}
+
+	pkgNames := make([]string, 0, len(pkgEntries))
+	for name, _ := range pkgEntries {
+		pkgNames = append(pkgNames, name)
+	}
+	sort.Strings(pkgNames)
+
+	fmt.Fprintf(w, "/***** Settings */\n")
+
+	for _, name := range pkgNames {
+		fmt.Fprintf(w, "\n")
+		entries := pkgEntries[name]
+		writeSettingsOnePkg(cfg, name, entries, w)
+	}
+}
+
+func writePkgsPresent(roster cfgRoster, w io.Writer) {
+	present := make([]string, 0, len(roster.pkgsPresent))
+	notPresent := make([]string, 0, len(roster.pkgsPresent))
+	for k, v := range roster.pkgsPresent {
+		if v {
+			present = append(present, k)
+		} else {
+			notPresent = append(notPresent, k)
+		}
+	}
+
+	sort.Strings(present)
+	sort.Strings(notPresent)
+
+	fmt.Fprintf(w, "/*** Packages (present) */\n")
+	for _, symbol := range present {
+		fmt.Fprintf(w, "\n")
+		writeDefine(symbol, "1", w)
+	}
+
+	fmt.Fprintf(w, "\n")
+	fmt.Fprintf(w, "/*** Packages (not present)*/\n")
+	for _, symbol := range notPresent {
+		fmt.Fprintf(w, "\n")
+		writeDefine(symbol, "0", w)
+	}
+}
+
+func writeApisPresent(roster cfgRoster, w io.Writer) {
+	present := make([]string, 0, len(roster.apisPresent))
+	notPresent := make([]string, 0, len(roster.apisPresent))
+	for k, v := range roster.apisPresent {
+		if v {
+			present = append(present, k)
+		} else {
+			notPresent = append(notPresent, k)
+		}
+	}
+
+	sort.Strings(present)
+	sort.Strings(notPresent)
+
+	fmt.Fprintf(w, "/*** APIs (present) */\n")
+	for _, symbol := range present {
+		fmt.Fprintf(w, "\n")
+		writeDefine(symbol, "1", w)
+	}
+
+	fmt.Fprintf(w, "\n")
+	fmt.Fprintf(w, "/*** APIs (not present) */\n")
+	for _, symbol := range notPresent {
+		writeDefine(symbol, "0", w)
+		fmt.Fprintf(w, "\n")
+	}
+}
+
+func write(cfg Cfg, roster cfgRoster, w io.Writer) {
+	WritePreamble(w)
+
+	fmt.Fprintf(w, "#ifndef H_MYNEWT_SYSCFG_\n")
+	fmt.Fprintf(w, "#define H_MYNEWT_SYSCFG_\n\n")
+
+	writeCheckMacros(w)
+	fmt.Fprintf(w, "\n")
+
+	writeSettings(cfg, w)
+	fmt.Fprintf(w, "\n")
+
+	writePkgsPresent(roster, w)
+	fmt.Fprintf(w, "\n")
+
+	writeApisPresent(roster, w)
+	fmt.Fprintf(w, "\n")
+
+	fmt.Fprintf(w, "#endif\n")
+}
+
+func writeRequired(contents []byte, path string) (bool, error) {
+	oldHeader, err := ioutil.ReadFile(path)
+	if err != nil {
+		if os.IsNotExist(err) {
+			// File doesn't exist; write required.
+			return true, nil
+		}
+
+		return true, util.NewNewtError(err.Error())
+	}
+
+	rc := bytes.Compare(oldHeader, contents)
+	return rc != 0, nil
+}
+
+func headerPath(targetPath string) string {
+	return fmt.Sprintf("%s/%s/%s", targetPath, SYSCFG_INCLUDE_SUBDIR,
+		SYSCFG_HEADER_FILENAME)
+}
+
+func EnsureWritten(cfg Cfg, lpkgs []*pkg.LocalPackage,
+	apis []string, targetPath string) error {
+
+	if err := calcPriorities(cfg, CFG_SETTING_TYPE_TASK_PRIO,
+		SYSCFG_TASK_PRIO_MAX, false); err != nil {
+
+		return err
+	}
+
+	if err := calcPriorities(cfg, CFG_SETTING_TYPE_INTERRUPT_PRIO,
+		SYSCFG_INTERRUPT_PRIO_MAX, true); err != nil {
+
+		return err
+	}
+
+	roster := buildCfgRoster(cfg, lpkgs, apis)
+	if err := fixupSettings(cfg, roster); err != nil {
+		return err
+	}
+
+	buf := bytes.Buffer{}
+	write(cfg, roster, &buf)
+
+	path := headerPath(targetPath)
+
+	writeReqd, err := writeRequired(buf.Bytes(), path)
+	if err != nil {
+		return err
+	}
+	if !writeReqd {
+		log.Debugf("syscfg unchanged; not writing header file (%s).", path)
+		return nil
+	}
+
+	log.Debugf("syscfg changed; writing header file (%s).", path)
+
+	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
+		return util.NewNewtError(err.Error())
+	}
+
+	if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
+		return util.NewNewtError(err.Error())
+	}
+
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/sysinit/sysinit.go
----------------------------------------------------------------------
diff --git a/newt/sysinit/sysinit.go b/newt/sysinit/sysinit.go
new file mode 100644
index 0000000..8e8188b
--- /dev/null
+++ b/newt/sysinit/sysinit.go
@@ -0,0 +1,154 @@
+/**
+ * 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 sysinit
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+
+	log "github.com/Sirupsen/logrus"
+
+	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/util"
+)
+
+const FILENAME = "sysinit.c"
+const SYSINIT_FN_SIG = `void
+sysinit(void)
+{
+`
+
+func buildStageMap(pkgs []*pkg.LocalPackage) map[int][]*pkg.LocalPackage {
+	sm := map[int][]*pkg.LocalPackage{}
+
+	for _, p := range pkgs {
+		stage := p.InitStage()
+		sm[stage] = append(sm[stage], p)
+	}
+
+	return sm
+}
+
+func writePrototypes(pkgs []*pkg.LocalPackage, w io.Writer) {
+	sorted := pkg.SortLclPkgs(pkgs)
+	for _, p := range sorted {
+		fmt.Fprintf(w, "void %s(void);\n", p.InitFnName())
+	}
+}
+
+func writeStage(stage int, pkgs []*pkg.LocalPackage, w io.Writer) {
+	sorted := pkg.SortLclPkgs(pkgs)
+
+	fmt.Fprintf(w, "    /*** Stage %d */\n", stage)
+	for i, p := range sorted {
+		fmt.Fprintf(w, "    /* %d.%d: %s */\n", stage, i, p.Name())
+		fmt.Fprintf(w, "    %s();\n", p.InitFnName())
+	}
+}
+
+func onlyPkgsWithInit(pkgs []*pkg.LocalPackage) []*pkg.LocalPackage {
+	good := make([]*pkg.LocalPackage, 0, len(pkgs))
+	for _, p := range pkgs {
+		if p.InitFnName() != "" {
+			good = append(good, p)
+		}
+	}
+
+	return good
+}
+
+func write(pkgs []*pkg.LocalPackage, w io.Writer) {
+	goodPkgs := onlyPkgsWithInit(pkgs)
+	stageMap := buildStageMap(goodPkgs)
+
+	i := 0
+	stages := make([]int, len(stageMap))
+	for k, _ := range stageMap {
+		stages[i] = k
+		i++
+	}
+	sort.Ints(stages)
+
+	syscfg.WritePreamble(w)
+
+	writePrototypes(goodPkgs, w)
+	fmt.Fprintf(w, "\n")
+
+	fmt.Fprintf(w, "%s", SYSINIT_FN_SIG)
+	for i, s := range stages {
+		if i != 0 {
+			fmt.Fprintf(w, "\n")
+		}
+
+		writeStage(s, stageMap[s], w)
+	}
+
+	fmt.Fprintf(w, "}\n")
+}
+
+func writeRequired(contents []byte, path string) (bool, error) {
+	oldSrc, err := ioutil.ReadFile(path)
+	if err != nil {
+		if os.IsNotExist(err) {
+			// File doesn't exist; write required.
+			return true, nil
+		}
+
+		return true, util.NewNewtError(err.Error())
+	}
+
+	rc := bytes.Compare(oldSrc, contents)
+	return rc != 0, nil
+}
+
+func EnsureWritten(pkgs []*pkg.LocalPackage, targetPath string) error {
+	buf := bytes.Buffer{}
+	write(pkgs, &buf)
+
+	path := fmt.Sprintf("%s/src/%s", targetPath, FILENAME)
+
+	writeReqd, err := writeRequired(buf.Bytes(), path)
+	if err != nil {
+		return err
+	}
+
+	if !writeReqd {
+		log.Debugf("sysinit unchanged; not writing src file (%s).", path)
+		return nil
+	}
+
+	log.Debugf("sysinit changed; writing src file (%s).", path)
+
+	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
+		return util.NewNewtError(err.Error())
+	}
+
+	if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
+		return util.NewNewtError(err.Error())
+	}
+
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/toolchain/compiler.go
----------------------------------------------------------------------
diff --git a/newt/toolchain/compiler.go b/newt/toolchain/compiler.go
index b032d97..a961051 100644
--- a/newt/toolchain/compiler.go
+++ b/newt/toolchain/compiler.go
@@ -153,6 +153,10 @@ func addFlags(flagType string, orig []string, new []string) []string {
 	return combined
 }
 
+func (ci *CompilerInfo) AddCflags(cflags []string) {
+	ci.Cflags = addFlags("cflag", ci.Cflags, cflags)
+}
+
 func (ci *CompilerInfo) AddCompilerInfo(newCi *CompilerInfo) {
 	ci.Includes = append(ci.Includes, newCi.Includes...)
 	ci.Cflags = addFlags("cflag", ci.Cflags, newCi.Cflags)
@@ -168,7 +172,7 @@ func NewCompiler(compilerDir string, dstDir string,
 	c := &Compiler{
 		ObjPathList: map[string]bool{},
 		dstDir:      filepath.Clean(dstDir),
-		extraDeps:   []string{compilerDir + COMPILER_FILENAME},
+		extraDeps:   []string{},
 	}
 
 	c.depTracker = NewDepTracker(c)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/toolchain/deps.go
----------------------------------------------------------------------
diff --git a/newt/toolchain/deps.go b/newt/toolchain/deps.go
index a50e265..e54c255 100644
--- a/newt/toolchain/deps.go
+++ b/newt/toolchain/deps.go
@@ -165,6 +165,7 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
 	if err != nil {
 		return false, err
 	}
+
 	if commandHasChanged(objFile, cmd) {
 		util.StatusMessage(util.VERBOSITY_VERBOSE, "%s - rebuild required; "+
 			"different command\n", srcFile)
@@ -175,6 +176,13 @@ func (tracker *DepTracker) CompileRequired(srcFile string,
 		return true, nil
 	}
 
+	if util.NodeNotExist(depFile) {
+		err := tracker.compiler.GenDepsForFile(srcFile)
+		if err != nil {
+			return false, err
+		}
+	}
+
 	srcModTime, err := util.FileModificationTime(srcFile)
 	if err != nil {
 		return false, err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/vendor/mynewt.apache.org/newt/DISCLAIMER
----------------------------------------------------------------------
diff --git a/newt/vendor/mynewt.apache.org/newt/DISCLAIMER b/newt/vendor/mynewt.apache.org/newt/DISCLAIMER
deleted file mode 100644
index 1600825..0000000
--- a/newt/vendor/mynewt.apache.org/newt/DISCLAIMER
+++ /dev/null
@@ -1,8 +0,0 @@
-Apache Mynewt is an effort undergoing incubation at The Apache Software
-Foundation (ASF), sponsored by the Incubator PMC.  Incubation is
-required of all newly accepted projects until a further review indicates
-that the infrastructure, communications, and decision making process
-have stabilized in a manner consistent with other successful ASF
-projects. While incubation status is not necessarily a reflection of the
-completeness or stability of the code, it does indicate that the project
-has yet to be fully endorsed by the ASF.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/vendor/mynewt.apache.org/newt/LICENSE
----------------------------------------------------------------------
diff --git a/newt/vendor/mynewt.apache.org/newt/LICENSE b/newt/vendor/mynewt.apache.org/newt/LICENSE
deleted file mode 100644
index 88a6f68..0000000
--- a/newt/vendor/mynewt.apache.org/newt/LICENSE
+++ /dev/null
@@ -1,244 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright {yyyy} {name of copyright owner}
-
-   Licensed 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.
-
-This product bundles pretty, which is available under the MIT license.  For
-details, see newt/vendor/github.com/kr/pretty/License
-
-This product bundles kr/text, which is available under the MIT license.  For
-details, see newt/vendor/github.com/kr/text/License
-
-This product bundles mapstructure, which is available under the MIT license.
-For details, see newt/vendor/github.com/mitchellh/mapstructure/LICENSE
-
-This product bundles logrus, which is available under the MIT license.  For
-details, see newt/vendor/github.com/Sirupsen/logrus/LICENSE
-
-This product bundles Cast, which is available under the MIT license.  For
-details, see newt/vendor/github.com/spf13/cast/LICENSE
-
-This product bundles jWalterWeatherman, which is available under the MIT
-license.  For details, see
-newt/vendor/github.com/spf13/jwalterweatherman/LICENSE
-
-This product bundles pflag, which is available under the "3-clause BSD"
-license.  For details, see newt/vendor/github.com/spf13/pflag/LICENSE
-
-This product bundles the unix Go package, which is available under the
-"3-clause BSD" license.  For details, see newt/vendor/golang.org/x/sys/LICENSE
-
-This product bundles fsnotify.v1, which is available under the "3-clause BSD"
-license.  For details, see newt/vendor/gopkg.in/fsnotify.v1/LICENSE
-
-This product bundles yaml.v2's Go port of libyaml, which is available under the
-MIT license.  For details, see:
-    * yaml/apic.go
-    * yaml/emitterc.go
-    * yaml/parserc.go
-    * yaml/readerc.go
-    * yaml/scannerc.go
-    * yaml/writerc.go
-    * yaml/yamlh.go
-    * yaml/yamlprivateh.go
-
-This product bundles viper, which is available under the MIT license.  For
-details, see:
-    * viper/LICENSE

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/vendor/mynewt.apache.org/newt/NOTICE
----------------------------------------------------------------------
diff --git a/newt/vendor/mynewt.apache.org/newt/NOTICE b/newt/vendor/mynewt.apache.org/newt/NOTICE
deleted file mode 100644
index 94bea73..0000000
--- a/newt/vendor/mynewt.apache.org/newt/NOTICE
+++ /dev/null
@@ -1,8 +0,0 @@
-Apache Mynewt (incubating)
-Copyright 2015-2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-Portions of this software were developed at
-Runtime Inc, copyright 2015.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/0ae71ef1/newt/vendor/mynewt.apache.org/newt/util/util.go
----------------------------------------------------------------------
diff --git a/newt/vendor/mynewt.apache.org/newt/util/util.go b/newt/vendor/mynewt.apache.org/newt/util/util.go
index 27b407c..930c24e 100644
--- a/newt/vendor/mynewt.apache.org/newt/util/util.go
+++ b/newt/vendor/mynewt.apache.org/newt/util/util.go
@@ -32,6 +32,7 @@ import (
 	"path/filepath"
 	"runtime"
 	"sort"
+	"strconv"
 	"strings"
 	"syscall"
 	"time"
@@ -422,3 +423,23 @@ func SortFields(wsSepStrings ...string) []string {
 	sort.Strings(slice)
 	return slice
 }
+
+func AtoiNoOct(s string) (int, error) {
+	var runLen int
+	for runLen = 0; runLen < len(s)-1; runLen++ {
+		if s[runLen] != '0' || s[runLen+1] == 'x' {
+			break
+		}
+	}
+
+	if runLen > 0 {
+		s = s[runLen:]
+	}
+
+	i, err := strconv.ParseInt(s, 0, 0)
+	if err != nil {
+		return 0, NewNewtError(err.Error())
+	}
+
+	return int(i), nil
+}