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 2018/11/01 18:40:01 UTC

[mynewt-newt] branch master updated (070430f -> 2f34faf)

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git.


    from 070430f  Allow branches with no default upstream
     new d7ee16d  syscfg: Extract setting reference functionality
     new d1384bc  logcfg: Allow logs to be defined in `syscfg.yml`
     new bec355f  logcfg: `target logcfg <show | brief>` commands
     new 9b06eff  val: Generic setting value structure
     new 1a4ef35  stage: Use ValSetting (generic setting value)
     new 55944f7  logcfg: use ValSetting (generic setting value)
     new 31417de  Higher level structures for sysinit/sysdown
     new 1e81d51  Add `newt target [sysinit | sysdown]` cmds
     new 2f34faf  CLI: Move some target commands to a new file

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 newt/builder/targetbuild.go |  74 ++--
 newt/cli/target_cfg_cmds.go | 856 ++++++++++++++++++++++++++++++++++++++++++++
 newt/cli/target_cmds.go     | 354 +-----------------
 newt/logcfg/logcfg.go       | 327 +++++++++++++++++
 newt/pkg/localpackage.go    |  45 +--
 newt/resolve/resolve.go     |  24 +-
 newt/stage/stage.go         |  55 ++-
 newt/syscfg/syscfg.go       |  62 ++--
 newt/sysdown/sysdown.go     | 162 +++++++--
 newt/sysinit/sysinit.go     | 137 +++++--
 newt/val/valsetting.go      |  65 ++++
 11 files changed, 1634 insertions(+), 527 deletions(-)
 create mode 100644 newt/cli/target_cfg_cmds.go
 create mode 100644 newt/logcfg/logcfg.go
 create mode 100644 newt/val/valsetting.go


[mynewt-newt] 01/09: syscfg: Extract setting reference functionality

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit d7ee16d29547007ce676555f1e4c618155e27080
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 15 18:22:52 2018 -0700

    syscfg: Extract setting reference functionality
    
    A setting can refer to another with the `MYNEWT_VAL(...)` notation.
    This commit extracts the code which detects such references and puts it
    into separate functions.
---
 newt/syscfg/syscfg.go | 62 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/newt/syscfg/syscfg.go b/newt/syscfg/syscfg.go
index 6e75a84..40f68b3 100644
--- a/newt/syscfg/syscfg.go
+++ b/newt/syscfg/syscfg.go
@@ -68,6 +68,8 @@ const SYSCFG_PRIO_ANY = "any"
 // Reserve last 16 priorities for the system (sanity, idle).
 const SYSCFG_TASK_PRIO_MAX = 0xef
 
+var cfgRefRe = regexp.MustCompile("MYNEWT_VAL\\((\\w+)\\)")
+
 var cfgSettingNameTypeMap = map[string]CfgSettingType{
 	"raw":           CFG_SETTING_TYPE_RAW,
 	"task_priority": CFG_SETTING_TYPE_TASK_PRIO,
@@ -180,34 +182,50 @@ func (cfg *Cfg) SettingValues() map[string]string {
 	return values
 }
 
-func (cfg *Cfg) ResolveValueRefs() {
-	re := regexp.MustCompile("MYNEWT_VAL\\((\\w+)\\)")
-	for k, entry := range cfg.Settings {
-		value := strings.TrimSpace(entry.Value)
-
-		m := re.FindStringSubmatch(value)
-		if len(m) == 0 || len(m[0]) != len(value) {
-			// either there is no reference or there's something else besides
-			// reference - skip it
-			// TODO we may want to emit warning in the latter case (?)
-			continue
-		}
+func ResolveValueRefName(val string) string {
+	// If the value has the `MYNEWT_VAL([...])` notation, then extract the
+	// parenthesized identifier.
+	m := cfgRefRe.FindStringSubmatch(val)
+	if m == nil {
+		return ""
+	} else {
+		// TODO we may try to resolve nested references...
+		return m[1]
+	}
+}
 
-		newName := m[1]
+func (cfg *Cfg) ExpandRef(val string) (string, string, error) {
+	refName := ResolveValueRefName(val)
+	if refName == "" {
+		// Not a reference.
+		return "", val, nil
+	}
 
-		// TODO we may try to resolve nested references...
+	entry, ok := cfg.Settings[refName]
+	if !ok {
+		return "", "", util.FmtNewtError(
+			"setting value \"%s\" references undefined setting", val)
+	}
 
-		newEntry, exists := cfg.Settings[newName]
-		entry.ValueRefName = newName
-		if exists {
-			entry.Value = newEntry.Value
-		} else {
-			// set unresolved setting value to 0, this way restrictions
-			// can be evaluated and won't create spurious warnings
+	return entry.Name, entry.Value, nil
+
+}
+
+func (cfg *Cfg) ResolveValueRefs() {
+	for k, entry := range cfg.Settings {
+		refName, val, err := cfg.ExpandRef(strings.TrimSpace(entry.Value))
+		if err != nil {
+			// Referenced setting doesn't exist.  Set unresolved setting value
+			// to 0, this way restrictions can be evaluated and won't create
+			// spurious warnings.
 			entry.Value = "0"
 			cfg.UnresolvedValueRefs[k] = struct{}{}
+			cfg.Settings[k] = entry
+		} else if refName != "" {
+			entry.ValueRefName = refName
+			entry.Value = val
+			cfg.Settings[k] = entry
 		}
-		cfg.Settings[k] = entry
 	}
 }
 


[mynewt-newt] 08/09: Add `newt target [sysinit | sysdown]` cmds

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 1e81d51fee4e651323bcbf13421ca72daf40f5c3
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:07:30 2018 -0700

    Add `newt target [sysinit | sysdown]` cmds
    
    This commit adds four newt commands:
    
        newt target sysinit show <target>
        newt target sysinit brief <target>
        newt target sysdown show <target>
        newt target sysdown brief <target>
    
    Both sysinit commands produce a report of all the sysinit entries configured
    for the target.  Example output:
    
    [SHOW]
        $ newt target sysinit show slinky-nrf52dk
    
        Log config for targets/slinky-nrf52dk:
        <snip>
        config_pkg_init:
            Package: @apache-mynewt-core/sys/config
            Stage:  50               [CONFIG_SYSINIT_1_STAGE]
    
        log_init:
            Package: @apache-mynewt-core/sys/log/full
            Stage:  100              [LOG_SYSINIT_STAGE]
    
        <snip>
    
    [BRIEF]
        $ newt target sysinit brief slinky-nrf52dk
    
        Brief sysinit config for targets/slinky-nrf52dk:
         FUNCTION                 | PACKAGE                                                 | STAGE
        <snip>
         config_pkg_init          | @apache-mynewt-core/sys/config                          | 50               [CONFIG_SYSINIT_1_STAGE]
         log_init                 | @apache-mynewt-core/sys/log/full                        | 100              [LOG_SYSINIT_STAGE]
        <snip>
    
    The sysdown commands are similar; they show sysdown entries rather than
    sysinit entries.
---
 newt/cli/target_cmds.go | 275 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 267 insertions(+), 8 deletions(-)

diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go
index 821865f..41cbb9b 100644
--- a/newt/cli/target_cmds.go
+++ b/newt/cli/target_cmds.go
@@ -35,8 +35,12 @@ import (
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/resolve"
+	"mynewt.apache.org/newt/newt/stage"
 	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/sysdown"
+	"mynewt.apache.org/newt/newt/sysinit"
 	"mynewt.apache.org/newt/newt/target"
+	"mynewt.apache.org/newt/newt/val"
 	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
 )
@@ -779,18 +783,18 @@ func targetConfigBriefCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
-func logModuleString(ls logcfg.LogSetting) string {
-	intVal, _ := ls.IntVal()
+func valSettingString(vs val.ValSetting) string {
+	intVal, _ := vs.IntVal()
 
 	s := fmt.Sprintf("%d", intVal)
-	if ls.RefName != "" {
-		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", ls.RefName)
+	if vs.RefName != "" {
+		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", vs.RefName)
 	}
 
 	return s
 }
 
-func logLevelString(ls logcfg.LogSetting) string {
+func logLevelString(ls val.ValSetting) string {
 	intVal, _ := ls.IntVal()
 
 	s := fmt.Sprintf("%d (%s)", intVal, logcfg.LogLevelString(intVal))
@@ -806,7 +810,7 @@ func printLogCfgOne(l logcfg.Log) {
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
 		l.Source.FullName())
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Module:  %s\n",
-		logModuleString(l.Module))
+		valSettingString(l.Module))
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Level:   %s\n",
 		logLevelString(l.Level))
 }
@@ -860,7 +864,8 @@ func printLogCfgBriefOne(l logcfg.Log, colWidth int) {
 	intMod, _ := l.Module.IntVal()
 	intLevel, _ := l.Level.IntVal()
 
-	levelStr := fmt.Sprintf("%d (%s)", intLevel, logcfg.LogLevelString(intLevel))
+	levelStr := fmt.Sprintf("%d (%s)", intLevel,
+		logcfg.LogLevelString(intLevel))
 
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "%*s | %-8d | %-12s\n",
 		colWidth, l.Name, intMod, levelStr)
@@ -874,7 +879,7 @@ func printLogCfgBrief(targetName string, lcfg logcfg.LCfg) {
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief log config for %s:\n",
 		targetName)
 
-	longest := 0
+	longest := 6
 	logNames := make([]string, 0, len(lcfg.Logs))
 	for name, _ := range lcfg.Logs {
 		logNames = append(logNames, name)
@@ -918,6 +923,186 @@ func targetLogBriefCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
+func printStage(sf stage.StageFunc) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", sf.Name)
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
+		sf.Pkg.FullName())
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Stage:  %s\n",
+		valSettingString(sf.Stage))
+}
+
+func printStageBriefOne(sf stage.StageFunc, fnWidth int, pkgWidth int) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, " %-*s | %-*s | %s\n",
+		fnWidth, sf.Name,
+		pkgWidth, sf.Pkg.FullName(),
+		valSettingString(sf.Stage))
+}
+
+func printStageBriefTable(sfs []stage.StageFunc) {
+	longestPkg := 6
+	longestFn := 6
+	for _, sf := range sfs {
+		if len(sf.Name) > longestFn {
+			longestFn = len(sf.Name)
+		}
+		if len(sf.Pkg.FullName()) > longestPkg {
+			longestPkg = len(sf.Pkg.FullName())
+		}
+	}
+
+	pkgWidth := longestPkg + 2
+	fnWidth := longestFn + 2
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		" %-*s | %-*s | STAGE\n",
+		fnWidth, "FUNCTION",
+		pkgWidth, "PACKAGE")
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"-%s-+-%s-+----------\n",
+		strings.Repeat("-", fnWidth), strings.Repeat("-", pkgWidth))
+	for _, sf := range sfs {
+		printStageBriefOne(sf, fnWidth, pkgWidth)
+	}
+}
+
+func printSysinitCfg(targetName string, scfg sysinit.SysinitCfg) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysinit config for %s:\n",
+		targetName)
+
+	for i, sf := range scfg.StageFuncs {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printStage(sf)
+	}
+}
+
+func printSysinitBrief(targetName string, scfg sysinit.SysinitCfg) {
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysinit config for %s:\n",
+		targetName)
+
+	printStageBriefTable(scfg.StageFuncs)
+}
+
+func targetSysinitShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysinitCfg(b.GetTarget().Name(), res.SysinitCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func targetSysinitBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysinitBrief(b.GetTarget().Name(), res.SysinitCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printSysdownCfg(targetName string, scfg sysdown.SysdownCfg) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysdown config for %s:\n",
+		targetName)
+
+	for i, sf := range scfg.StageFuncs {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printStage(sf)
+	}
+}
+
+func targetSysdownShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysdownCfg(b.GetTarget().Name(), res.SysdownCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printSysdownBrief(targetName string, scfg sysdown.SysdownCfg) {
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysdown config for %s:\n",
+		targetName)
+
+	printStageBriefTable(scfg.StageFuncs)
+}
+
+func targetSysdownBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysdownBrief(b.GetTarget().Name(), res.SysdownCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
 func targetConfigInitCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 1 {
 		NewtUsage(cmd,
@@ -1307,6 +1492,80 @@ func AddTargetCommands(cmd *cobra.Command) {
 		return append(targetList(), unittestList()...)
 	})
 
+	sysinitHelpText := "View a target's sysinit configuration"
+
+	sysinitCmd := &cobra.Command{
+		Use:   "sysinit",
+		Short: sysinitHelpText,
+		Long:  sysinitHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	targetCmd.AddCommand(sysinitCmd)
+
+	sysinitShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's sysinit configuration",
+		Long:  "View a target's sysinit configuration",
+		Run:   targetSysinitShowCmd,
+	}
+
+	sysinitCmd.AddCommand(sysinitShowCmd)
+	AddTabCompleteFn(sysinitShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysinitBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's sysinit configuration",
+		Long:  "View a summary of target's sysinit configuration",
+		Run:   targetSysinitBriefCmd,
+	}
+
+	sysinitCmd.AddCommand(sysinitBriefCmd)
+	AddTabCompleteFn(sysinitBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysdownHelpText := "View a target's sysdown configuration"
+
+	sysdownCmd := &cobra.Command{
+		Use:   "sysdown",
+		Short: sysdownHelpText,
+		Long:  sysdownHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	targetCmd.AddCommand(sysdownCmd)
+
+	sysdownShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's sysdown configuration",
+		Long:  "View a target's sysdown configuration",
+		Run:   targetSysdownShowCmd,
+	}
+
+	sysdownCmd.AddCommand(sysdownShowCmd)
+	AddTabCompleteFn(sysdownShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysdownBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's sysdown configuration",
+		Long:  "View a summary of target's sysdown configuration",
+		Run:   targetSysdownBriefCmd,
+	}
+
+	sysdownCmd.AddCommand(sysdownBriefCmd)
+	AddTabCompleteFn(sysdownBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
 	depHelpText := "View a target's dependency graph."
 
 	depCmd := &cobra.Command{


[mynewt-newt] 04/09: val: Generic setting value structure

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 9b06effbba704378fe174dda01d9c1c8cc79bfa3
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:00:59 2018 -0700

    val: Generic setting value structure
---
 newt/val/valsetting.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/newt/val/valsetting.go b/newt/val/valsetting.go
new file mode 100644
index 0000000..a57d1d1
--- /dev/null
+++ b/newt/val/valsetting.go
@@ -0,0 +1,65 @@
+/**
+ * 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 val
+
+import (
+	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/util"
+)
+
+// Value setting: represents a setting value as read from a YAML configuration
+// file.  The setting may reference a syscfg setting via the `MYNEWT_VAL(...)`
+// notation.
+type ValSetting struct {
+	// The exact text specified as the YAML map key.
+	Text string
+
+	// If this setting refers to a syscfg setting via the `MYNEWT_VAL(...)`
+	// notation, this contains the name of the setting.  Otherwise, "".
+	RefName string
+
+	// The setting value, after setting references are resolved.
+	Value string
+}
+
+// IntVal Extracts a setting's integer value.
+func (vs *ValSetting) IntVal() (int, error) {
+	iv, err := util.AtoiNoOct(vs.Value)
+	if err != nil {
+		return 0, util.ChildNewtError(err)
+	}
+
+	return iv, nil
+}
+
+// Constructs a setting from a YAML string.
+func ResolveValSetting(s string, cfg *syscfg.Cfg) (ValSetting, error) {
+	refName, val, err := cfg.ExpandRef(s)
+	if err != nil {
+		return ValSetting{},
+			util.FmtNewtError("value \"%s\" references undefined setting", s)
+	}
+
+	return ValSetting{
+		Text:    s,
+		RefName: refName,
+		Value:   val,
+	}, nil
+}


[mynewt-newt] 06/09: logcfg: use ValSetting (generic setting value)

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 55944f752e33547b2f4eac65af47662084815095
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:06:34 2018 -0700

    logcfg: use ValSetting (generic setting value)
---
 newt/logcfg/logcfg.go | 46 +++++-----------------------------------------
 1 file changed, 5 insertions(+), 41 deletions(-)

diff --git a/newt/logcfg/logcfg.go b/newt/logcfg/logcfg.go
index 1cd5b27..6b2d66b 100644
--- a/newt/logcfg/logcfg.go
+++ b/newt/logcfg/logcfg.go
@@ -35,23 +35,12 @@ import (
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/val"
 	"mynewt.apache.org/newt/util"
 )
 
 const HEADER_PATH = "logcfg/logcfg.h"
 
-type LogSetting struct {
-	// The exact text specified as the YAML map key.
-	Text string
-
-	// If this setting refers to a syscfg setting via the `MYNEWT_VAL(...)`
-	// notation, this contains the name of the setting.  Otherwise, "".
-	RefName string
-
-	// The setting value, after setting references are resolved.
-	Value string
-}
-
 type Log struct {
 	// Log name; equal to the name of the YAML map that defines the log.
 	Name string
@@ -60,10 +49,10 @@ type Log struct {
 	Source *pkg.LocalPackage
 
 	// The log's numeric module ID.
-	Module LogSetting
+	Module val.ValSetting
 
 	// The level assigned to this log.
-	Level LogSetting
+	Level val.ValSetting
 }
 
 // Map of: [log-name] => log
@@ -107,31 +96,6 @@ func NewLCfg() LCfg {
 	}
 }
 
-// IntVal Extracts a log setting's integer value.
-func (ls *LogSetting) IntVal() (int, error) {
-	iv, err := util.AtoiNoOct(ls.Value)
-	if err != nil {
-		return 0, util.ChildNewtError(err)
-	}
-
-	return iv, nil
-}
-
-// Constructs a log setting from a YAML string.
-func resolveLogVal(s string, cfg *syscfg.Cfg) (LogSetting, error) {
-	refName, val, err := cfg.ExpandRef(s)
-	if err != nil {
-		return LogSetting{},
-			util.FmtNewtError("value \"%s\" references undefined setting", s)
-	}
-
-	return LogSetting{
-		Text:    s,
-		RefName: refName,
-		Value:   val,
-	}, nil
-}
-
 // Parses a single log definition from a YAML map.  The `logMapItf` parameter
 // should be a map with the following elements:
 //     "module": <module-string>
@@ -155,7 +119,7 @@ func parseOneLog(name string, lpkg *pkg.LocalPackage, logMapItf interface{},
 		return cl, util.FmtNewtError(
 			"\"%s\" missing required field \"module\"", name)
 	}
-	mod, err := resolveLogVal(modStr, cfg)
+	mod, err := val.ResolveValSetting(modStr, cfg)
 	if err != nil {
 		return cl, util.FmtNewtError(
 			"\"%s\" contains invalid \"module\": %s",
@@ -171,7 +135,7 @@ func parseOneLog(name string, lpkg *pkg.LocalPackage, logMapItf interface{},
 		return cl, util.FmtNewtError(
 			"\"%s\" missing required field \"level\"", name)
 	}
-	level, err := resolveLogVal(levelStr, cfg)
+	level, err := val.ResolveValSetting(levelStr, cfg)
 	if err != nil {
 		return cl, util.FmtNewtError(
 			"\"%s\" contains invalid \"level\": %s",


[mynewt-newt] 07/09: Higher level structures for sysinit/sysdown

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 31417de60e9b39d5f2a7ba5130b150b5317b088f
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:03:58 2018 -0700

    Higher level structures for sysinit/sysdown
    
    Prior to this commit, the sysinit and sysdown function lists were
    created on demand, when the corresponding C code is generated.
    
    This commit causes the sysinit and sysdown configurations to be
    generated at resolution time.  This allows:
        * Better error reporting
        * CLI commands to access the sysinit / sysdown configuration
---
 newt/builder/targetbuild.go |  77 ++++++++-------------
 newt/pkg/localpackage.go    |  45 ++----------
 newt/resolve/resolve.go     |  14 +++-
 newt/sysdown/sysdown.go     | 162 ++++++++++++++++++++++++++++++++++----------
 newt/sysinit/sysinit.go     | 137 ++++++++++++++++++++++++++++++-------
 5 files changed, 285 insertions(+), 150 deletions(-)

diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 519632c..9ee7317 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -45,8 +45,6 @@ import (
 	"mynewt.apache.org/newt/newt/resolve"
 	"mynewt.apache.org/newt/newt/symbol"
 	"mynewt.apache.org/newt/newt/syscfg"
-	"mynewt.apache.org/newt/newt/sysdown"
-	"mynewt.apache.org/newt/newt/sysinit"
 	"mynewt.apache.org/newt/newt/target"
 	"mynewt.apache.org/newt/newt/toolchain"
 	"mynewt.apache.org/newt/util"
@@ -216,72 +214,59 @@ func (t *TargetBuilder) validateAndWriteCfg() error {
 		log.Warn(line)
 	}
 
-	if err := syscfg.EnsureWritten(t.res.Cfg,
-		GeneratedIncludeDir(t.target.Name())); err != nil {
-
-		return err
-	}
-
-	if err := t.res.LCfg.EnsureWritten(
-		GeneratedIncludeDir(t.target.Name())); err != nil {
+	incDir := GeneratedIncludeDir(t.target.Name())
+	srcDir := GeneratedSrcDir(t.target.Name())
 
+	if err := syscfg.EnsureWritten(t.res.Cfg, incDir); err != nil {
 		return err
 	}
 
-	return nil
-}
-
-func (t *TargetBuilder) generateSysinit() error {
-	if err := t.ensureResolved(); err != nil {
+	if err := t.res.LCfg.EnsureWritten(incDir); err != nil {
 		return err
 	}
 
-	srcDir := GeneratedSrcDir(t.target.Name())
-
+	// Generate loader sysinit.
 	if t.res.LoaderSet != nil {
 		lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.LoaderSet.Rpkgs)
-		sysinit.EnsureWritten(lpkgs, srcDir,
-			pkg.ShortName(t.target.Package()), true)
+		if err := t.res.SysinitCfg.EnsureWritten(lpkgs, srcDir,
+			pkg.ShortName(t.target.Package()), true); err != nil {
+
+			return err
+		}
 	}
 
+	// Generate app sysinit.
 	lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.AppSet.Rpkgs)
-	sysinit.EnsureWritten(lpkgs, srcDir,
-		pkg.ShortName(t.target.Package()), false)
-
-	return nil
-}
+	if err := t.res.SysinitCfg.EnsureWritten(lpkgs, srcDir,
+		pkg.ShortName(t.target.Package()), false); err != nil {
 
-func (t *TargetBuilder) generateSysdown() error {
-	if err := t.ensureResolved(); err != nil {
 		return err
 	}
 
-	srcDir := GeneratedSrcDir(t.target.Name())
+	// Generate loader sysinit.
+	if t.res.LoaderSet != nil {
+		lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.LoaderSet.Rpkgs)
+		if err := t.res.SysdownCfg.EnsureWritten(lpkgs, srcDir,
+			pkg.ShortName(t.target.Package()), true); err != nil {
 
-	lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.AppSet.Rpkgs)
-	sysdown.EnsureWritten(lpkgs, t.res.Cfg, srcDir,
-		pkg.ShortName(t.target.Package()))
+			return err
+		}
+	}
 
-	return nil
-}
+	// XXX: Generate loader sysdown.
 
-func (t *TargetBuilder) generateFlashMap() error {
-	return t.bspPkg.FlashMap.EnsureWritten(
-		GeneratedSrcDir(t.target.Name()),
-		GeneratedIncludeDir(t.target.Name()),
-		pkg.ShortName(t.target.Package()))
-}
+	// Generate app sysdown.
+	lpkgs = resolve.RpkgSliceToLpkgSlice(t.res.AppSet.Rpkgs)
+	if err := t.res.SysdownCfg.EnsureWritten(lpkgs, srcDir,
+		pkg.ShortName(t.target.Package()), false); err != nil {
 
-func (t *TargetBuilder) generateCode() error {
-	if err := t.generateSysinit(); err != nil {
 		return err
 	}
 
-	if err := t.generateSysdown(); err != nil {
-		return err
-	}
+	// Generate flash map.
+	if err := t.bspPkg.FlashMap.EnsureWritten(srcDir, incDir,
+		pkg.ShortName(t.target.Package())); err != nil {
 
-	if err := t.generateFlashMap(); err != nil {
 		return err
 	}
 
@@ -339,10 +324,6 @@ func (t *TargetBuilder) PrepBuild() error {
 
 	logDepInfo(t.res)
 
-	if err := t.generateCode(); err != nil {
-		return err
-	}
-
 	return nil
 }
 
diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go
index d5cc9a8..0b23036 100644
--- a/newt/pkg/localpackage.go
+++ b/newt/pkg/localpackage.go
@@ -26,7 +26,6 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"strconv"
 	"strings"
 
 	log "github.com/Sirupsen/logrus"
@@ -61,10 +60,6 @@ type LocalPackage struct {
 	// General information about the package
 	desc *PackageDesc
 
-	// Package init function name and stage.  These are used to generate the
-	// sysinit C file.
-	init map[string]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
@@ -86,7 +81,6 @@ func NewLocalPackage(r *repo.Repo, pkgDir string) *LocalPackage {
 		SyscfgY:          ycfg.YCfg{},
 		repo:             r,
 		basePath:         filepath.ToSlash(filepath.Clean(pkgDir)),
-		init:             map[string]int{},
 		injectedSettings: map[string]string{},
 	}
 	return pkg
@@ -352,23 +346,6 @@ func (pkg *LocalPackage) Load() error {
 		return nil
 	}
 
-	init := pkg.PkgY.GetValStringMapString("pkg.init", nil)
-	for name, stageStr := range init {
-		stage, err := strconv.ParseInt(stageStr, 10, 64)
-		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Parsing pkg %s config: %s",
-				pkg.FullName(), err.Error()))
-		}
-		pkg.init[name] = int(stage)
-	}
-
-	// Backwards compatibility: allow old sysinit notation.
-	initFnName := pkg.PkgY.GetValString("pkg.init_function", nil)
-	initStage := pkg.PkgY.GetValInt("pkg.init_stage", nil)
-	if initFnName != "" {
-		pkg.init[initFnName] = initStage
-	}
-
 	// Read the package description from the file
 	pkg.desc, err = pkg.readDesc(pkg.PkgY)
 	if err != nil {
@@ -388,28 +365,18 @@ func (pkg *LocalPackage) Load() error {
 	return nil
 }
 
-func (pkg *LocalPackage) Init() map[string]int {
-	return pkg.init
+func (pkg *LocalPackage) InitFuncs(
+	settings map[string]string) map[string]string {
+
+	return pkg.PkgY.GetValStringMapString("pkg.init", settings)
 }
 
 // DownFuncs retrieves the package's shutdown functions.  The returned map has:
 // key=C-function-name, value=numeric-stage.
 func (pkg *LocalPackage) DownFuncs(
-	settings map[string]string) (map[string]int, error) {
-
-	downFuncs := map[string]int{}
-
-	down := pkg.PkgY.GetValStringMapString("pkg.down", settings)
-	for name, stageStr := range down {
-		stage, err := strconv.ParseInt(stageStr, 10, 64)
-		if err != nil {
-			return nil, util.FmtNewtError("Parsing pkg %s config: %s",
-				pkg.FullName(), err.Error())
-		}
-		downFuncs[name] = int(stage)
-	}
+	settings map[string]string) map[string]string {
 
-	return downFuncs, nil
+	return pkg.PkgY.GetValStringMapString("pkg.down", settings)
 }
 
 func (pkg *LocalPackage) InjectedSettings() map[string]string {
diff --git a/newt/resolve/resolve.go b/newt/resolve/resolve.go
index b5fa87a..29dcee5 100644
--- a/newt/resolve/resolve.go
+++ b/newt/resolve/resolve.go
@@ -31,6 +31,8 @@ import (
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/sysdown"
+	"mynewt.apache.org/newt/newt/sysinit"
 	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
 )
@@ -60,6 +62,8 @@ type Resolver struct {
 	flashMap         flash.FlashMap
 	cfg              syscfg.Cfg
 	lcfg             logcfg.LCfg
+	sysinitCfg       sysinit.SysinitCfg
+	sysdownCfg       sysdown.SysdownCfg
 
 	// [api-name][api-supplier]
 	apiConflicts map[string]map[*ResolvePackage]struct{}
@@ -94,7 +98,7 @@ type ResolveSet struct {
 	// Parent resoluion.  Contains this ResolveSet.
 	Res *Resolution
 
-	// All seed pacakges and their dependencies.
+	// All seed packages and their dependencies.
 	Rpkgs []*ResolvePackage
 }
 
@@ -107,6 +111,8 @@ type ApiConflict struct {
 type Resolution struct {
 	Cfg             syscfg.Cfg
 	LCfg            logcfg.LCfg
+	SysinitCfg      sysinit.SysinitCfg
+	SysdownCfg      sysdown.SysdownCfg
 	ApiMap          map[string]*ResolvePackage
 	UnsatisfiedApis map[string][]*ResolvePackage
 	ApiConflicts    []ApiConflict
@@ -545,6 +551,8 @@ func (r *Resolver) resolveDepsAndCfg() error {
 
 	lpkgs := RpkgSliceToLpkgSlice(r.rpkgSlice())
 	r.lcfg = logcfg.Read(lpkgs, &r.cfg)
+	r.sysinitCfg = sysinit.Read(lpkgs, &r.cfg)
+	r.sysdownCfg = sysdown.Read(lpkgs, &r.cfg)
 
 	// Log the final syscfg.
 	r.cfg.Log()
@@ -639,6 +647,8 @@ func ResolveFull(
 	res := newResolution()
 	res.Cfg = r.cfg
 	res.LCfg = r.lcfg
+	res.SysinitCfg = r.sysinitCfg
+	res.SysdownCfg = r.sysdownCfg
 
 	// Determine which package satisfies each API and which APIs are
 	// unsatisfied.
@@ -756,6 +766,8 @@ func (res *Resolution) ErrorText() string {
 
 	str += res.Cfg.ErrorText()
 	str += res.LCfg.ErrorText()
+	str += res.SysinitCfg.ErrorText()
+	str += res.SysdownCfg.ErrorText()
 
 	str = strings.TrimSpace(str)
 	if str != "" {
diff --git a/newt/sysdown/sysdown.go b/newt/sysdown/sysdown.go
index 060130e..b240edf 100644
--- a/newt/sysdown/sysdown.go
+++ b/newt/sysdown/sysdown.go
@@ -30,68 +30,156 @@ import (
 	"mynewt.apache.org/newt/newt/syscfg"
 )
 
-// downFuncs collects the sysdown functions corresponding to the provided
-// packages.
-func downFuncs(pkgs []*pkg.LocalPackage,
-	cfg syscfg.Cfg) ([]stage.StageFunc, error) {
-
-	fns := make([]stage.StageFunc, 0, len(pkgs))
-	for _, p := range pkgs {
-		downMap, err := p.DownFuncs(cfg.AllSettingsForLpkg(p))
+type SysdownCfg struct {
+	// Sorted in call order (stage-num,function-name).
+	StageFuncs []stage.StageFunc
+
+	// Strings describing errors encountered while parsing the sysdown config.
+	InvalidSettings []string
+
+	// Contains sets of entries with conflicting function names.
+	//     [function-name] => <slice-of-stages-with-function-name>
+	Conflicts map[string][]stage.StageFunc
+}
+
+func (scfg *SysdownCfg) readOnePkg(lpkg *pkg.LocalPackage, cfg *syscfg.Cfg) {
+	settings := cfg.AllSettingsForLpkg(lpkg)
+	initMap := lpkg.DownFuncs(settings)
+	for name, stageStr := range initMap {
+		sf, err := stage.NewStageFunc(name, stageStr, lpkg, cfg)
 		if err != nil {
-			return nil, err
+			scfg.InvalidSettings = append(scfg.InvalidSettings, err.Error())
 		}
+		sf.ReturnType = "int"
+		sf.ArgList = "int reason"
 
-		for name, stageNum := range downMap {
-			fn := stage.StageFunc{
-				Name:       name,
-				Stage:      stageNum,
-				ReturnType: "int",
-				ArgList:    "int reason",
-				Pkg:        p,
-			}
-			fns = append(fns, fn)
+		scfg.StageFuncs = append(scfg.StageFuncs, sf)
+	}
+}
+
+// Searches the sysdown configuration for entries with identical function
+// names.  The sysdown configuration object is populated with the results.
+func (scfg *SysdownCfg) detectConflicts() {
+	m := map[string][]stage.StageFunc{}
+
+	for _, sf := range scfg.StageFuncs {
+		m[sf.Name] = append(m[sf.Name], sf)
+	}
+
+	for name, sfs := range m {
+		if len(sfs) > 1 {
+			scfg.Conflicts[name] = sfs
 		}
 	}
+}
+
+func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) SysdownCfg {
+	scfg := SysdownCfg{}
+
+	for _, lpkg := range lpkgs {
+		scfg.readOnePkg(lpkg, cfg)
+	}
+
+	scfg.detectConflicts()
+	stage.SortStageFuncs(scfg.StageFuncs, "sysdown")
 
-	return fns, nil
+	return scfg
 }
 
-func sortedDownFuncs(pkgs []*pkg.LocalPackage,
-	cfg syscfg.Cfg) ([]stage.StageFunc, error) {
+func (scfg *SysdownCfg) filter(lpkgs []*pkg.LocalPackage) []stage.StageFunc {
+	m := make(map[*pkg.LocalPackage]struct{}, len(lpkgs))
 
-	fns, err := downFuncs(pkgs, cfg)
-	if err != nil {
-		return nil, err
+	for _, lpkg := range lpkgs {
+		m[lpkg] = struct{}{}
 	}
 
-	stage.SortStageFuncs(fns, "sysdown")
-	return fns, nil
+	filtered := []stage.StageFunc{}
+	for _, sf := range scfg.StageFuncs {
+		if _, ok := m[sf.Pkg]; ok {
+			filtered = append(filtered, sf)
+		}
+	}
+
+	return filtered
 }
 
-func write(pkgs []*pkg.LocalPackage, cfg syscfg.Cfg, w io.Writer) error {
+// If any errors were encountered while parsing sysdown definitions, this
+// function returns a string indicating the errors.  If no errors were
+// encountered, "" is returned.
+func (scfg *SysdownCfg) ErrorText() string {
+	str := ""
+
+	if len(scfg.InvalidSettings) > 0 {
+		str += "Invalid sysdown definitions detected:"
+		for _, e := range scfg.InvalidSettings {
+			str += "\n    " + e
+		}
+	}
+
+	if len(scfg.Conflicts) > 0 {
+		str += "Sysdown function name conflicts detected:\n"
+		for name, sfs := range scfg.Conflicts {
+			for _, sf := range sfs {
+				str += fmt.Sprintf("    Function=%s Package=%s\n",
+					name, sf.Pkg.FullName())
+			}
+		}
+
+		str += "\nResolve the problem by assigning unique function names " +
+			"to each entry."
+	}
+
+	return str
+}
+
+func (scfg *SysdownCfg) write(lpkgs []*pkg.LocalPackage, isLoader bool,
+	w io.Writer) error {
+
+	var sfs []stage.StageFunc
+	if lpkgs == nil {
+		sfs = scfg.StageFuncs
+	} else {
+		sfs = scfg.filter(lpkgs)
+	}
+
 	fmt.Fprintf(w, newtutil.GeneratedPreamble())
 
-	fns, err := sortedDownFuncs(pkgs, cfg)
-	if err != nil {
-		return err
+	if isLoader {
+		fmt.Fprintf(w, "#if SPLIT_LOADER\n\n")
+	} else {
+		fmt.Fprintf(w, "#if !SPLIT_LOADER\n\n")
 	}
 
-	stage.WritePrototypes(fns, w)
+	stage.WritePrototypes(sfs, w)
+
+	var arrName string
+
+	// XXX: Assign a different array name depending on isLoader.
+	arrName = "sysdown_cbs"
 
-	fmt.Fprintf(w, "\nint (* const sysdown_cbs[])(int reason) = {\n")
-	stage.WriteArr(fns, w)
+	fmt.Fprintf(w, "\nint (* const %s[])(int reason) = {\n", arrName)
+	stage.WriteArr(sfs, w)
 	fmt.Fprintf(w, "};\n")
 
+	fmt.Fprintf(w, "#endif\n")
+
 	return nil
 }
 
-func EnsureWritten(pkgs []*pkg.LocalPackage, cfg syscfg.Cfg, srcDir string,
-	targetName string) error {
+func (scfg *SysdownCfg) EnsureWritten(lpkgs []*pkg.LocalPackage, srcDir string,
+	targetName string, isLoader bool) error {
 
 	buf := bytes.Buffer{}
-	write(pkgs, cfg, &buf)
+	if err := scfg.write(lpkgs, isLoader, &buf); err != nil {
+		return err
+	}
+
+	var path string
+	if isLoader {
+		path = fmt.Sprintf("%s/%s-sysdown-loader.c", srcDir, targetName)
+	} else {
+		path = fmt.Sprintf("%s/%s-sysdown-app.c", srcDir, targetName)
+	}
 
-	path := fmt.Sprintf("%s/%s-sysdown.c", srcDir, targetName)
 	return stage.EnsureWritten(path, buf.Bytes())
 }
diff --git a/newt/sysinit/sysinit.go b/newt/sysinit/sysinit.go
index 98e7fc6..7d012d0 100644
--- a/newt/sysinit/sysinit.go
+++ b/newt/sysinit/sysinit.go
@@ -27,33 +27,118 @@ import (
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/stage"
+	"mynewt.apache.org/newt/newt/syscfg"
 )
 
-func initFuncs(pkgs []*pkg.LocalPackage) []stage.StageFunc {
-	fns := make([]stage.StageFunc, 0, len(pkgs))
-	for _, p := range pkgs {
-		initMap := p.Init()
-		for name, stageNum := range initMap {
-			fn := stage.StageFunc{
-				Name:  name,
-				Stage: stageNum,
-				Pkg:   p,
-			}
-			fns = append(fns, fn)
+type SysinitCfg struct {
+	// Sorted in call order (stage-num,function-name).
+	StageFuncs []stage.StageFunc
+
+	// Strings describing errors encountered while parsing the sysinit config.
+	InvalidSettings []string
+
+	// Contains sets of entries with conflicting function names.
+	//     [function-name] => <slice-of-stages-with-function-name>
+	Conflicts map[string][]stage.StageFunc
+}
+
+func (scfg *SysinitCfg) readOnePkg(lpkg *pkg.LocalPackage, cfg *syscfg.Cfg) {
+	settings := cfg.AllSettingsForLpkg(lpkg)
+	initMap := lpkg.InitFuncs(settings)
+	for name, stageStr := range initMap {
+		sf, err := stage.NewStageFunc(name, stageStr, lpkg, cfg)
+		if err != nil {
+			scfg.InvalidSettings = append(scfg.InvalidSettings, err.Error())
 		}
+
+		scfg.StageFuncs = append(scfg.StageFuncs, sf)
 	}
+}
+
+// Searches the sysinit configuration for entries with identical function
+// names.  The sysinit configuration object is populated with the results.
+func (scfg *SysinitCfg) detectConflicts() {
+	m := map[string][]stage.StageFunc{}
 
-	return fns
+	for _, sf := range scfg.StageFuncs {
+		m[sf.Name] = append(m[sf.Name], sf)
+	}
+
+	for name, sfs := range m {
+		if len(sfs) > 1 {
+			scfg.Conflicts[name] = sfs
+		}
+	}
 }
 
-func sortedInitFuncs(pkgs []*pkg.LocalPackage) []stage.StageFunc {
-	fns := initFuncs(pkgs)
-	stage.SortStageFuncs(fns, "sysinit")
-	return fns
+func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) SysinitCfg {
+	scfg := SysinitCfg{}
+
+	for _, lpkg := range lpkgs {
+		scfg.readOnePkg(lpkg, cfg)
+	}
+
+	scfg.detectConflicts()
+	stage.SortStageFuncs(scfg.StageFuncs, "sysinit")
+
+	return scfg
 }
 
-func write(pkgs []*pkg.LocalPackage, isLoader bool,
-	w io.Writer) {
+func (scfg *SysinitCfg) filter(lpkgs []*pkg.LocalPackage) []stage.StageFunc {
+	m := make(map[*pkg.LocalPackage]struct{}, len(lpkgs))
+
+	for _, lpkg := range lpkgs {
+		m[lpkg] = struct{}{}
+	}
+
+	filtered := []stage.StageFunc{}
+	for _, sf := range scfg.StageFuncs {
+		if _, ok := m[sf.Pkg]; ok {
+			filtered = append(filtered, sf)
+		}
+	}
+
+	return filtered
+}
+
+// If any errors were encountered while parsing sysinit definitions, this
+// function returns a string indicating the errors.  If no errors were
+// encountered, "" is returned.
+func (scfg *SysinitCfg) ErrorText() string {
+	str := ""
+
+	if len(scfg.InvalidSettings) > 0 {
+		str += "Invalid sysinit definitions detected:"
+		for _, e := range scfg.InvalidSettings {
+			str += "\n    " + e
+		}
+	}
+
+	if len(scfg.Conflicts) > 0 {
+		str += "Sysinit function name conflicts detected:\n"
+		for name, sfs := range scfg.Conflicts {
+			for _, sf := range sfs {
+				str += fmt.Sprintf("    Function=%s Package=%s\n",
+					name, sf.Pkg.FullName())
+			}
+		}
+
+		str += "\nResolve the problem by assigning unique function names " +
+			"to each entry."
+	}
+
+	return str
+}
+
+func (scfg *SysinitCfg) write(lpkgs []*pkg.LocalPackage, isLoader bool,
+	w io.Writer) error {
+
+	var sfs []stage.StageFunc
+	if lpkgs == nil {
+		sfs = scfg.StageFuncs
+	} else {
+		sfs = scfg.filter(lpkgs)
+	}
 
 	fmt.Fprintf(w, newtutil.GeneratedPreamble())
 
@@ -63,9 +148,7 @@ func write(pkgs []*pkg.LocalPackage, isLoader bool,
 		fmt.Fprintf(w, "#if !SPLIT_LOADER\n\n")
 	}
 
-	fns := sortedInitFuncs(pkgs)
-
-	stage.WritePrototypes(fns, w)
+	stage.WritePrototypes(sfs, w)
 
 	var fnName string
 	if isLoader {
@@ -77,17 +160,21 @@ func write(pkgs []*pkg.LocalPackage, isLoader bool,
 	fmt.Fprintf(w, "\n")
 	fmt.Fprintf(w, "void\n%s(void)\n{\n", fnName)
 
-	stage.WriteCalls(fns, "", w)
+	stage.WriteCalls(sfs, "", w)
 
 	fmt.Fprintf(w, "}\n\n")
 	fmt.Fprintf(w, "#endif\n")
+
+	return nil
 }
 
-func EnsureWritten(pkgs []*pkg.LocalPackage, srcDir string, targetName string,
-	isLoader bool) error {
+func (scfg *SysinitCfg) EnsureWritten(lpkgs []*pkg.LocalPackage, srcDir string,
+	targetName string, isLoader bool) error {
 
 	buf := bytes.Buffer{}
-	write(pkgs, isLoader, &buf)
+	if err := scfg.write(lpkgs, isLoader, &buf); err != nil {
+		return err
+	}
 
 	var path string
 	if isLoader {


[mynewt-newt] 02/09: logcfg: Allow logs to be defined in `syscfg.yml`

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit d1384bc57d0ab759519f629fdb42c60f33d2f8ef
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 15 18:49:36 2018 -0700

    logcfg: Allow logs to be defined in `syscfg.yml`
    
    A package can define logs in its `syscfg.yml` file under the heading of
    `syscfg.logs`.  During the build process, newt generates a C header file
    called `logcfg/logcfg.h` containing macros for using each generated log.
    
    Each entry in the `syscfg.logs` map has the following structure:
    
            <log-name>:
                module: <module>
                level: <level>
                guest: <true/false> (optional)
    
    For example:
    
        syscfg.logs:
            MY_LOG:
                module: MYNEWT_VAL(MY_LOG_MODULE)
                level: MYNEWT_VAL(MY_LOG_LEVEL)
    
    It is recommended, though not required, that the module and level fields
    refer to syscfg settings, as above.  This allows the target to
    reconfigure a package's log without modifying the package itself.
    
    The above log definition generates the following code in
    `logcfg/logcfg.h` (assuming `MY_LOG_MODULE is set to LOG_LEVEL_ERROR (3)):
    
        #define MY_LOG_DEBUG(logcfg_lvl_, ...) IGNORE(__VA_ARGS__)
        #define MY_LOG_INFO(logcfg_lvl_, ...) IGNORE(__VA_ARGS__)
        #define MY_LOG_WARN(logcfg_lvl_, ...) IGNORE(__VA_ARGS__)
        #define MY_LOG_ERROR(logcfg_lvl_, ...) MODLOG_ ## logcfg_lvl_(MYNEWT_VAL(MY_LOG_MODULE), __VA_ARGS__)
        #define MY_LOG_CRITICAL(logcfg_lvl_, ...) MODLOG_ ## logcfg_lvl_(MYNEWT_VAL(MY_LOG_MODULE), __VA_ARGS__)
    
    If two or more logs have module values that resolve to the same number,
    newt aborts the build with an error:
    
        Error: Log module conflicts detected:
            Module=100 Log=MY_LOG Package=sys/coredump
            Module=100 Log=YOUR_LOG Package=sys/coredump
    
        Resolve the problem by assigning unique module IDs to each log,
        or by setting the "guest" flag of all but one.
    
    The "guest" flag, when set, allows a log to use the same module as
    another without generating an error.
---
 newt/builder/targetbuild.go |   9 ++
 newt/logcfg/logcfg.go       | 363 ++++++++++++++++++++++++++++++++++++++++++++
 newt/resolve/resolve.go     |  10 +-
 3 files changed, 381 insertions(+), 1 deletion(-)

diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index e4ccc21..519632c 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -101,6 +101,9 @@ func NewTargetTester(target *target.Target,
 		injectedSettings: map[string]string{},
 	}
 
+	// Indicate that this version of newt supports the generated logcfg header.
+	t.InjectSetting("NEWT_FEATURE_LOGCFG", "1")
+
 	return t, nil
 }
 
@@ -219,6 +222,12 @@ func (t *TargetBuilder) validateAndWriteCfg() error {
 		return err
 	}
 
+	if err := t.res.LCfg.EnsureWritten(
+		GeneratedIncludeDir(t.target.Name())); err != nil {
+
+		return err
+	}
+
 	return nil
 }
 
diff --git a/newt/logcfg/logcfg.go b/newt/logcfg/logcfg.go
new file mode 100644
index 0000000..1cd5b27
--- /dev/null
+++ b/newt/logcfg/logcfg.go
@@ -0,0 +1,363 @@
+/**
+ * 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 logcfg
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"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/newt/syscfg"
+	"mynewt.apache.org/newt/util"
+)
+
+const HEADER_PATH = "logcfg/logcfg.h"
+
+type LogSetting struct {
+	// The exact text specified as the YAML map key.
+	Text string
+
+	// If this setting refers to a syscfg setting via the `MYNEWT_VAL(...)`
+	// notation, this contains the name of the setting.  Otherwise, "".
+	RefName string
+
+	// The setting value, after setting references are resolved.
+	Value string
+}
+
+type Log struct {
+	// Log name; equal to the name of the YAML map that defines the log.
+	Name string
+
+	// The package that defines the log.
+	Source *pkg.LocalPackage
+
+	// The log's numeric module ID.
+	Module LogSetting
+
+	// The level assigned to this log.
+	Level LogSetting
+}
+
+// Map of: [log-name] => log
+type LogMap map[string]Log
+
+// The log configuration of the target.
+type LCfg struct {
+	// [log-name] => log
+	Logs LogMap
+
+	// Strings describing errors encountered while parsing the log config.
+	InvalidSettings []string
+
+	// Contains sets of logs with conflicting module IDs.
+	//     [module-ID] => <slice-of-logs-with-module-id>
+	ModuleConflicts map[int][]Log
+}
+
+// Maps numeric log levels to their string representations.  Used when
+// generating the C log macros.
+var logLevelNames = []string{
+	0: "DEBUG",
+	1: "INFO",
+	2: "WARN",
+	3: "ERROR",
+	4: "CRITICAL",
+}
+
+func LogLevelString(level int) string {
+	if level < 0 || level >= len(logLevelNames) {
+		return "???"
+	}
+
+	return logLevelNames[level]
+}
+
+func NewLCfg() LCfg {
+	return LCfg{
+		Logs:            map[string]Log{},
+		ModuleConflicts: map[int][]Log{},
+	}
+}
+
+// IntVal Extracts a log setting's integer value.
+func (ls *LogSetting) IntVal() (int, error) {
+	iv, err := util.AtoiNoOct(ls.Value)
+	if err != nil {
+		return 0, util.ChildNewtError(err)
+	}
+
+	return iv, nil
+}
+
+// Constructs a log setting from a YAML string.
+func resolveLogVal(s string, cfg *syscfg.Cfg) (LogSetting, error) {
+	refName, val, err := cfg.ExpandRef(s)
+	if err != nil {
+		return LogSetting{},
+			util.FmtNewtError("value \"%s\" references undefined setting", s)
+	}
+
+	return LogSetting{
+		Text:    s,
+		RefName: refName,
+		Value:   val,
+	}, nil
+}
+
+// Parses a single log definition from a YAML map.  The `logMapItf` parameter
+// should be a map with the following elements:
+//     "module": <module-string>
+//     "level": <level-string>
+func parseOneLog(name string, lpkg *pkg.LocalPackage, logMapItf interface{},
+	cfg *syscfg.Cfg) (Log, error) {
+
+	cl := Log{
+		Name:   name,
+		Source: lpkg,
+	}
+
+	logMap := cast.ToStringMapString(logMapItf)
+	if logMap == nil {
+		return cl, util.FmtNewtError(
+			"\"%s\" missing required field \"module\"", name)
+	}
+
+	modStr := logMap["module"]
+	if modStr == "" {
+		return cl, util.FmtNewtError(
+			"\"%s\" missing required field \"module\"", name)
+	}
+	mod, err := resolveLogVal(modStr, cfg)
+	if err != nil {
+		return cl, util.FmtNewtError(
+			"\"%s\" contains invalid \"module\": %s",
+			name, err.Error())
+	}
+	if _, err := mod.IntVal(); err != nil {
+		return cl, util.FmtNewtError(
+			"\"%s\" contains invalid \"module\": %s", name, err.Error())
+	}
+
+	levelStr := logMap["level"]
+	if levelStr == "" {
+		return cl, util.FmtNewtError(
+			"\"%s\" missing required field \"level\"", name)
+	}
+	level, err := resolveLogVal(levelStr, cfg)
+	if err != nil {
+		return cl, util.FmtNewtError(
+			"\"%s\" contains invalid \"level\": %s",
+			name, err.Error())
+	}
+	if _, err := level.IntVal(); err != nil {
+		return cl, util.FmtNewtError(
+			"\"%s\" contains invalid \"level\": %s", name, err.Error())
+	}
+
+	cl.Module = mod
+	cl.Level = level
+
+	return cl, nil
+}
+
+// Reads all the logs defined by the specified package.  The log definitions
+// are read from the `syscfg.logs` map in the package's `syscfg.yml` file.
+func (lcfg *LCfg) readOnePkg(lpkg *pkg.LocalPackage, cfg *syscfg.Cfg) {
+	lsettings := cfg.AllSettingsForLpkg(lpkg)
+	logMaps := lpkg.SyscfgY.GetValStringMap("syscfg.logs", lsettings)
+	for name, logMapItf := range logMaps {
+		cl, err := parseOneLog(name, lpkg, logMapItf, cfg)
+		if err != nil {
+			lcfg.InvalidSettings =
+				append(lcfg.InvalidSettings, strings.TrimSpace(err.Error()))
+		} else {
+			lcfg.Logs[cl.Name] = cl
+		}
+	}
+}
+
+// Searches the log configuration for logs with identical module IDs.  The log
+// configuration object is populated with the results.
+func (lcfg *LCfg) detectModuleConflicts() {
+	m := map[int][]Log{}
+
+	for _, l := range lcfg.Logs {
+		intMod, _ := l.Module.IntVal()
+		m[intMod] = append(m[intMod], l)
+	}
+
+	for mod, logs := range m {
+		if len(logs) > 1 {
+			for _, l := range logs {
+				lcfg.ModuleConflicts[mod] =
+					append(lcfg.ModuleConflicts[mod], l)
+			}
+		}
+	}
+}
+
+// Reads all log definitions for each of the specified packages.  The
+// returned LCfg object is populated with the result of this operation.
+func Read(lpkgs []*pkg.LocalPackage, cfg *syscfg.Cfg) LCfg {
+	lcfg := NewLCfg()
+
+	for _, lpkg := range lpkgs {
+		lcfg.readOnePkg(lpkg, cfg)
+	}
+
+	lcfg.detectModuleConflicts()
+
+	return lcfg
+}
+
+// If any errors were encountered while parsing log definitions, this function
+// returns a string indicating the errors.  If no errors were encountered, ""
+// is returned.
+func (lcfg *LCfg) ErrorText() string {
+	str := ""
+
+	if len(lcfg.InvalidSettings) > 0 {
+		str += "Invalid log definitions detected:"
+		for _, e := range lcfg.InvalidSettings {
+			str += "\n    " + e
+		}
+	}
+
+	if len(lcfg.ModuleConflicts) > 0 {
+		str += "Log module conflicts detected:\n"
+		for mod, logs := range lcfg.ModuleConflicts {
+			for _, l := range logs {
+				str += fmt.Sprintf("    Module=%d Log=%s Package=%s\n",
+					mod, l.Name, l.Source.FullName())
+			}
+		}
+
+		str +=
+			"\nResolve the problem by assigning unique module IDs to each log."
+	}
+
+	return str
+}
+
+// Retrieves a sorted slice of logs from the receiving log configuration.
+func (lcfg *LCfg) sortedLogs() []Log {
+	names := make([]string, 0, len(lcfg.Logs))
+
+	for n, _ := range lcfg.Logs {
+		names = append(names, n)
+	}
+	sort.Strings(names)
+
+	logs := make([]Log, 0, len(names))
+	for _, n := range names {
+		logs = append(logs, lcfg.Logs[n])
+	}
+
+	return logs
+}
+
+// Writes a no-op stub log C macro definition.
+func writeLogStub(logName string, levelStr string, w io.Writer) {
+	fmt.Fprintf(w, "#define %s_%s(...) IGNORE(__VA_ARGS__)\n",
+		logName, levelStr)
+}
+
+// Writes a log C macro definition.
+func writeLogMacro(logName string, module int, levelStr string, w io.Writer) {
+	fmt.Fprintf(w,
+		"#define %s_%s(...) MODLOG_%s(%d, __VA_ARGS__)\n",
+		logName, levelStr, levelStr, module)
+}
+
+// Write log C macro definitions for each log in the log configuration.
+func (lcfg *LCfg) writeLogMacros(w io.Writer) {
+	logs := lcfg.sortedLogs()
+	for _, l := range logs {
+		fmt.Fprintf(w, "\n")
+
+		levelInt, _ := util.AtoiNoOct(l.Level.Value)
+		for i, levelStr := range logLevelNames {
+			if i < levelInt {
+				writeLogStub(l.Name, levelStr, w)
+			} else {
+				modInt, _ := l.Module.IntVal()
+				writeLogMacro(l.Name, modInt, levelStr, w)
+			}
+		}
+	}
+}
+
+// Writes a logcfg header file to the specified writer.
+func (lcfg *LCfg) write(w io.Writer) {
+	fmt.Fprintf(w, newtutil.GeneratedPreamble())
+
+	fmt.Fprintf(w, "#ifndef H_MYNEWT_LOGCFG_\n")
+	fmt.Fprintf(w, "#define H_MYNEWT_LOGCFG_\n\n")
+
+	if len(lcfg.Logs) > 0 {
+		fmt.Fprintf(w, "#include \"modlog/modlog.h\"\n")
+		fmt.Fprintf(w, "#include \"log_common/log_common.h\"\n")
+
+		lcfg.writeLogMacros(w)
+		fmt.Fprintf(w, "\n")
+	}
+
+	fmt.Fprintf(w, "#endif\n")
+}
+
+// Ensures an up-to-date logcfg header is written for the target.
+func (lcfg *LCfg) EnsureWritten(includeDir string) error {
+	buf := bytes.Buffer{}
+	lcfg.write(&buf)
+
+	path := includeDir + "/" + HEADER_PATH
+
+	writeReqd, err := util.FileContentsChanged(path, buf.Bytes())
+	if err != nil {
+		return err
+	}
+	if !writeReqd {
+		log.Debugf("logcfg unchanged; not writing header file (%s).", path)
+		return nil
+	}
+
+	log.Debugf("logcfg 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
+}
diff --git a/newt/resolve/resolve.go b/newt/resolve/resolve.go
index dcdb0a3..b5fa87a 100644
--- a/newt/resolve/resolve.go
+++ b/newt/resolve/resolve.go
@@ -27,11 +27,12 @@ import (
 	log "github.com/Sirupsen/logrus"
 
 	"mynewt.apache.org/newt/newt/flash"
+	"mynewt.apache.org/newt/newt/logcfg"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/syscfg"
-	"mynewt.apache.org/newt/util"
 	"mynewt.apache.org/newt/newt/ycfg"
+	"mynewt.apache.org/newt/util"
 )
 
 // Represents a supplied API.
@@ -58,6 +59,7 @@ type Resolver struct {
 	injectedSettings map[string]string
 	flashMap         flash.FlashMap
 	cfg              syscfg.Cfg
+	lcfg             logcfg.LCfg
 
 	// [api-name][api-supplier]
 	apiConflicts map[string]map[*ResolvePackage]struct{}
@@ -104,6 +106,7 @@ type ApiConflict struct {
 // The result of resolving a target's configuration, APIs, and dependencies.
 type Resolution struct {
 	Cfg             syscfg.Cfg
+	LCfg            logcfg.LCfg
 	ApiMap          map[string]*ResolvePackage
 	UnsatisfiedApis map[string][]*ResolvePackage
 	ApiConflicts    []ApiConflict
@@ -540,6 +543,9 @@ func (r *Resolver) resolveDepsAndCfg() error {
 		return err
 	}
 
+	lpkgs := RpkgSliceToLpkgSlice(r.rpkgSlice())
+	r.lcfg = logcfg.Read(lpkgs, &r.cfg)
+
 	// Log the final syscfg.
 	r.cfg.Log()
 
@@ -632,6 +638,7 @@ func ResolveFull(
 
 	res := newResolution()
 	res.Cfg = r.cfg
+	res.LCfg = r.lcfg
 
 	// Determine which package satisfies each API and which APIs are
 	// unsatisfied.
@@ -748,6 +755,7 @@ func (res *Resolution) ErrorText() string {
 	}
 
 	str += res.Cfg.ErrorText()
+	str += res.LCfg.ErrorText()
 
 	str = strings.TrimSpace(str)
 	if str != "" {


[mynewt-newt] 09/09: CLI: Move some target commands to a new file

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 2f34faf8d3a282cc29bae44d60a50e02a067579c
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:33:14 2018 -0700

    CLI: Move some target commands to a new file
    
    Clean up `target_cmds.go` by moving the following commands to a new file:
        * target config
        * target logcfg
        * target sysinit
        * target sysdown
---
 newt/cli/target_cfg_cmds.go | 856 ++++++++++++++++++++++++++++++++++++++++++++
 newt/cli/target_cmds.go     | 790 +---------------------------------------
 2 files changed, 861 insertions(+), 785 deletions(-)

diff --git a/newt/cli/target_cfg_cmds.go b/newt/cli/target_cfg_cmds.go
new file mode 100644
index 0000000..6966519
--- /dev/null
+++ b/newt/cli/target_cfg_cmds.go
@@ -0,0 +1,856 @@
+/**
+ * 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.
+ */
+
+// Implements commands that show or modify a target's configuration.
+
+package cli
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"sort"
+	"strings"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/spf13/cobra"
+
+	"mynewt.apache.org/newt/newt/builder"
+	"mynewt.apache.org/newt/newt/logcfg"
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/newt/resolve"
+	"mynewt.apache.org/newt/newt/stage"
+	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/sysdown"
+	"mynewt.apache.org/newt/newt/sysinit"
+	"mynewt.apache.org/newt/newt/val"
+	"mynewt.apache.org/newt/util"
+)
+
+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)
+
+	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.FullName())
+		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"default=%s\n", entry.History[0].Value)
+	}
+	if len(entry.ValueRefName) > 0 {
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"    * Copied from: %s\n",
+			entry.ValueRefName)
+	}
+}
+
+func printBriefSetting(entry syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "  %s: %s",
+		entry.Name, entry.Value)
+
+	var extras []string
+
+	if len(entry.History) > 1 {
+		s := fmt.Sprintf("overridden by %s",
+			entry.History[len(entry.History)-1].Source.FullName())
+		extras = append(extras, s)
+	}
+	if len(entry.ValueRefName) > 0 {
+		s := fmt.Sprintf("copied from %s", entry.ValueRefName)
+		extras = append(extras, s)
+	}
+
+	if len(extras) > 0 {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, " (%s)",
+			strings.Join(extras, ", "))
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+}
+
+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.Settings[name])
+	}
+}
+
+func printCfg(targetName string, cfg syscfg.Cfg) {
+	if errText := cfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Syscfg for %s:\n", targetName)
+	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 printPkgBriefCfg(pkgName string, cfg syscfg.Cfg, entries []syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "[%s]\n", pkgName)
+
+	settingNames := make([]string, len(entries))
+	for i, entry := range entries {
+		settingNames[i] = entry.Name
+	}
+	sort.Strings(settingNames)
+
+	for _, name := range settingNames {
+		printBriefSetting(cfg.Settings[name])
+	}
+}
+
+func printBriefCfg(targetName string, cfg syscfg.Cfg) {
+	if errText := cfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief syscfg for %s:\n", targetName)
+	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")
+		}
+		printPkgBriefCfg(pkgName, cfg, pkgNameEntryMap[pkgName])
+	}
+}
+
+func yamlPkgCfg(w io.Writer, pkgName string, cfg syscfg.Cfg,
+	entries []syscfg.CfgEntry) {
+
+	settingNames := make([]string, len(entries))
+	for i, entry := range entries {
+		settingNames[i] = entry.Name
+	}
+	sort.Strings(settingNames)
+
+	fmt.Fprintf(w, "    ### %s\n", pkgName)
+	for _, name := range settingNames {
+		fmt.Fprintf(w, "    %s: '%s'\n", name, cfg.Settings[name].Value)
+	}
+}
+
+func yamlCfg(cfg syscfg.Cfg) string {
+	if errText := cfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	pkgNameEntryMap := syscfg.EntriesByPkg(cfg)
+
+	pkgNames := make([]string, 0, len(pkgNameEntryMap))
+	for pkgName, _ := range pkgNameEntryMap {
+		pkgNames = append(pkgNames, pkgName)
+	}
+	sort.Strings(pkgNames)
+
+	buf := bytes.Buffer{}
+
+	fmt.Fprintf(&buf, "syscfg.vals:\n")
+	for i, pkgName := range pkgNames {
+		if i > 0 {
+			fmt.Fprintf(&buf, "\n")
+		}
+		yamlPkgCfg(&buf, pkgName, cfg, pkgNameEntryMap[pkgName])
+	}
+
+	return string(buf.Bytes())
+}
+
+func targetBuilderConfigResolve(b *builder.TargetBuilder) *resolve.Resolution {
+	res, err := b.Resolve()
+	if err != nil {
+		NewtUsage(nil, err)
+	}
+
+	warningText := strings.TrimSpace(res.WarningText())
+	if warningText != "" {
+		log.Warn(warningText + "\n")
+	}
+
+	return res
+}
+
+func targetConfigShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printCfg(b.GetTarget().Name(), res.Cfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func targetConfigBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printBriefCfg(b.GetTarget().Name(), res.Cfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func valSettingString(vs val.ValSetting) string {
+	intVal, _ := vs.IntVal()
+
+	s := fmt.Sprintf("%d", intVal)
+	if vs.RefName != "" {
+		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", vs.RefName)
+	}
+
+	return s
+}
+
+func logLevelString(ls val.ValSetting) string {
+	intVal, _ := ls.IntVal()
+
+	s := fmt.Sprintf("%d (%s)", intVal, logcfg.LogLevelString(intVal))
+	if ls.RefName != "" {
+		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", ls.RefName)
+	}
+
+	return s
+}
+
+func printLogCfgOne(l logcfg.Log) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", l.Name)
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
+		l.Source.FullName())
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Module:  %s\n",
+		valSettingString(l.Module))
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Level:   %s\n",
+		logLevelString(l.Level))
+}
+
+func printLogCfg(targetName string, lcfg logcfg.LCfg) {
+	if errText := lcfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Log config for %s:\n",
+		targetName)
+
+	logNames := make([]string, 0, len(lcfg.Logs))
+	for name, _ := range lcfg.Logs {
+		logNames = append(logNames, name)
+	}
+	sort.Strings(logNames)
+
+	for i, logName := range logNames {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printLogCfgOne(lcfg.Logs[logName])
+	}
+}
+
+func targetLogShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printLogCfg(b.GetTarget().Name(), res.LCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printLogCfgBriefOne(l logcfg.Log, colWidth int) {
+	intMod, _ := l.Module.IntVal()
+	intLevel, _ := l.Level.IntVal()
+
+	levelStr := fmt.Sprintf("%d (%s)", intLevel,
+		logcfg.LogLevelString(intLevel))
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%*s | %-8d | %-12s\n",
+		colWidth, l.Name, intMod, levelStr)
+}
+
+func printLogCfgBrief(targetName string, lcfg logcfg.LCfg) {
+	if errText := lcfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief log config for %s:\n",
+		targetName)
+
+	longest := 6
+	logNames := make([]string, 0, len(lcfg.Logs))
+	for name, _ := range lcfg.Logs {
+		logNames = append(logNames, name)
+		if len(name) > longest {
+			longest = len(name)
+		}
+	}
+	sort.Strings(logNames)
+
+	colWidth := longest + 4
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"%*s | MODULE   | LEVEL\n", colWidth, "LOG")
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"%s-+----------+--------------\n",
+		strings.Repeat("-", colWidth))
+	for _, logName := range logNames {
+		printLogCfgBriefOne(lcfg.Logs[logName], colWidth)
+	}
+}
+
+func targetLogBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printLogCfgBrief(b.GetTarget().Name(), res.LCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printStage(sf stage.StageFunc) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", sf.Name)
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
+		sf.Pkg.FullName())
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Stage:  %s\n",
+		valSettingString(sf.Stage))
+}
+
+func printStageBriefOne(sf stage.StageFunc,
+	stageWidth int, pkgWidth int, fnWidth int, settingWidth int) {
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, " %-*s | %-*s | %-*s | %-*s\n",
+		stageWidth, sf.Stage.Value,
+		pkgWidth, sf.Pkg.FullName(),
+		fnWidth, sf.Name,
+		settingWidth, sf.Stage.RefName)
+}
+
+func printStageBriefTable(sfs []stage.StageFunc) {
+	longestStage := 5
+	longestPkg := 7
+	longestFn := 8
+	longestSetting := 7
+	for _, sf := range sfs {
+		if len(sf.Stage.Value) > longestStage {
+			longestStage = len(sf.Stage.Value)
+		}
+		if len(sf.Pkg.FullName()) > longestPkg {
+			longestPkg = len(sf.Pkg.FullName())
+		}
+		if len(sf.Name) > longestFn {
+			longestFn = len(sf.Name)
+		}
+		if len(sf.Stage.RefName) > longestSetting {
+			longestSetting = len(sf.Stage.RefName)
+		}
+	}
+
+	stageWidth := longestStage + 2
+	pkgWidth := longestPkg + 2
+	fnWidth := longestFn + 2
+	settingWidth := longestSetting + 2
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		" %-*s | %-*s | %-*s | %-*s\n",
+		stageWidth, "STAGE",
+		pkgWidth, "PACKAGE",
+		fnWidth, "FUNCTION",
+		settingWidth, "SETTING")
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"-%s-+-%s-+-%s-+-%s-\n",
+		strings.Repeat("-", stageWidth),
+		strings.Repeat("-", pkgWidth),
+		strings.Repeat("-", fnWidth),
+		strings.Repeat("-", settingWidth))
+	for _, sf := range sfs {
+		printStageBriefOne(sf, stageWidth, pkgWidth, fnWidth, settingWidth)
+	}
+}
+
+func printSysinitCfg(targetName string, scfg sysinit.SysinitCfg) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysinit config for %s:\n",
+		targetName)
+
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	for i, sf := range scfg.StageFuncs {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printStage(sf)
+	}
+}
+
+func printSysinitBrief(targetName string, scfg sysinit.SysinitCfg) {
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysinit config for %s:\n",
+		targetName)
+
+	printStageBriefTable(scfg.StageFuncs)
+}
+
+func targetSysinitShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysinitCfg(b.GetTarget().Name(), res.SysinitCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func targetSysinitBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysinitBrief(b.GetTarget().Name(), res.SysinitCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printSysdownCfg(targetName string, scfg sysdown.SysdownCfg) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysdown config for %s:\n",
+		targetName)
+
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	for i, sf := range scfg.StageFuncs {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printStage(sf)
+	}
+}
+
+func targetSysdownShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysdownCfg(b.GetTarget().Name(), res.SysdownCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printSysdownBrief(targetName string, scfg sysdown.SysdownCfg) {
+	if errText := scfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysdown config for %s:\n",
+		targetName)
+
+	printStageBriefTable(scfg.StageFuncs)
+}
+
+func targetSysdownBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printSysdownBrief(b.GetTarget().Name(), res.SysdownCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func targetConfigInitCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	type entry struct {
+		lpkg   *pkg.LocalPackage
+		path   string
+		b      *builder.TargetBuilder
+		exists bool
+	}
+
+	TryGetProject()
+
+	anyExist := false
+	entries := make([]entry, len(args))
+	for i, pkgName := range args {
+		e := &entries[i]
+
+		b, err := TargetBuilderForTargetOrUnittest(pkgName)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+		e.b = b
+
+		e.lpkg = b.GetTestPkg()
+		if e.lpkg == nil {
+			e.lpkg = b.GetTarget().Package()
+		}
+
+		e.path = builder.PkgSyscfgPath(e.lpkg.BasePath())
+
+		if util.NodeExist(e.path) {
+			e.exists = true
+			anyExist = true
+		}
+	}
+
+	if anyExist && !newtutil.NewtForce {
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"Configuration files already exist:\n")
+		for _, e := range entries {
+			if e.exists {
+				util.StatusMessage(util.VERBOSITY_DEFAULT, "    * %s\n",
+					e.path)
+			}
+		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+
+		fmt.Printf("Overwrite them? (y/N): ")
+		rsp := PromptYesNo(false)
+		if !rsp {
+			return
+		}
+	}
+
+	for _, e := range entries {
+		res := targetBuilderConfigResolve(e.b)
+		yaml := yamlCfg(res.Cfg)
+
+		if err := ioutil.WriteFile(e.path, []byte(yaml), 0644); err != nil {
+			NewtUsage(nil, util.FmtNewtError("Error writing file \"%s\"; %s",
+				e.path, err.Error()))
+		}
+	}
+}
+
+func targetCfgCmdAll() []*cobra.Command {
+	cmds := []*cobra.Command{}
+
+	configHelpText := "View or populate a target's system configuration"
+
+	configCmd := &cobra.Command{
+		Use:   "config",
+		Short: configHelpText,
+		Long:  configHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	cmds = append(cmds, configCmd)
+
+	configShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's system configuration",
+		Long:  "View a target's system configuration",
+		Run:   targetConfigShowCmd,
+	}
+
+	configCmd.AddCommand(configShowCmd)
+	AddTabCompleteFn(configShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	configBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's system configuration",
+		Long:  "View a summary of target's system configuration",
+		Run:   targetConfigBriefCmd,
+	}
+
+	configCmd.AddCommand(configBriefCmd)
+	AddTabCompleteFn(configBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	configInitCmd := &cobra.Command{
+		Use:   "init",
+		Short: "Populate a target's system configuration file",
+		Long: "Populate a target's system configuration file (syscfg). " +
+			"Unspecified settings are given default values.",
+		Run: targetConfigInitCmd,
+	}
+	configInitCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
+		"force", "f", false,
+		"Force overwrite of target configuration")
+
+	configCmd.AddCommand(configInitCmd)
+	AddTabCompleteFn(configInitCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	logHelpText := "View a target's log configuration"
+
+	logCmd := &cobra.Command{
+		Use:   "logcfg",
+		Short: logHelpText,
+		Long:  logHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	cmds = append(cmds, logCmd)
+
+	logShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's log configuration",
+		Long:  "View a target's log configuration",
+		Run:   targetLogShowCmd,
+	}
+
+	logCmd.AddCommand(logShowCmd)
+	AddTabCompleteFn(logShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	logBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's log configuration",
+		Long:  "View a summary of target's log configuration",
+		Run:   targetLogBriefCmd,
+	}
+
+	logCmd.AddCommand(logBriefCmd)
+	AddTabCompleteFn(logBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysinitHelpText := "View a target's sysinit configuration"
+
+	sysinitCmd := &cobra.Command{
+		Use:   "sysinit",
+		Short: sysinitHelpText,
+		Long:  sysinitHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	cmds = append(cmds, sysinitCmd)
+
+	sysinitShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's sysinit configuration",
+		Long:  "View a target's sysinit configuration",
+		Run:   targetSysinitShowCmd,
+	}
+
+	sysinitCmd.AddCommand(sysinitShowCmd)
+	AddTabCompleteFn(sysinitShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysinitBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's sysinit configuration",
+		Long:  "View a summary of target's sysinit configuration",
+		Run:   targetSysinitBriefCmd,
+	}
+
+	sysinitCmd.AddCommand(sysinitBriefCmd)
+	AddTabCompleteFn(sysinitBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysdownHelpText := "View a target's sysdown configuration"
+
+	sysdownCmd := &cobra.Command{
+		Use:   "sysdown",
+		Short: sysdownHelpText,
+		Long:  sysdownHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	cmds = append(cmds, sysdownCmd)
+
+	sysdownShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's sysdown configuration",
+		Long:  "View a target's sysdown configuration",
+		Run:   targetSysdownShowCmd,
+	}
+
+	sysdownCmd.AddCommand(sysdownShowCmd)
+	AddTabCompleteFn(sysdownShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	sysdownBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's sysdown configuration",
+		Long:  "View a summary of target's sysdown configuration",
+		Run:   targetSysdownBriefCmd,
+	}
+
+	sysdownCmd.AddCommand(sysdownBriefCmd)
+	AddTabCompleteFn(sysdownBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	return cmds
+}
diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go
index 41cbb9b..04c3260 100644
--- a/newt/cli/target_cmds.go
+++ b/newt/cli/target_cmds.go
@@ -22,25 +22,19 @@ package cli
 import (
 	"bytes"
 	"fmt"
-	"io"
 	"io/ioutil"
 	"os"
 	"sort"
 	"strings"
 
-	log "github.com/Sirupsen/logrus"
 	"github.com/spf13/cobra"
+
 	"mynewt.apache.org/newt/newt/builder"
-	"mynewt.apache.org/newt/newt/logcfg"
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/resolve"
-	"mynewt.apache.org/newt/newt/stage"
 	"mynewt.apache.org/newt/newt/syscfg"
-	"mynewt.apache.org/newt/newt/sysdown"
-	"mynewt.apache.org/newt/newt/sysinit"
 	"mynewt.apache.org/newt/newt/target"
-	"mynewt.apache.org/newt/newt/val"
 	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
 )
@@ -557,620 +551,6 @@ func targetCopyCmd(cmd *cobra.Command, args []string) {
 		srcTarget.FullName(), dstTarget.FullName())
 }
 
-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)
-
-	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.FullName())
-		}
-		util.StatusMessage(util.VERBOSITY_DEFAULT,
-			"default=%s\n", entry.History[0].Value)
-	}
-	if len(entry.ValueRefName) > 0 {
-		util.StatusMessage(util.VERBOSITY_DEFAULT,
-			"    * Copied from: %s\n",
-			entry.ValueRefName)
-	}
-}
-
-func printBriefSetting(entry syscfg.CfgEntry) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "  %s: %s",
-		entry.Name, entry.Value)
-
-	var extras []string
-
-	if len(entry.History) > 1 {
-		s := fmt.Sprintf("overridden by %s",
-			entry.History[len(entry.History)-1].Source.FullName())
-		extras = append(extras, s)
-	}
-	if len(entry.ValueRefName) > 0 {
-		s := fmt.Sprintf("copied from %s", entry.ValueRefName)
-		extras = append(extras, s)
-	}
-
-	if len(extras) > 0 {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, " (%s)",
-			strings.Join(extras, ", "))
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-}
-
-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.Settings[name])
-	}
-}
-
-func printCfg(targetName string, cfg syscfg.Cfg) {
-	if errText := cfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Syscfg for %s:\n", targetName)
-	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 printPkgBriefCfg(pkgName string, cfg syscfg.Cfg, entries []syscfg.CfgEntry) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "[%s]\n", pkgName)
-
-	settingNames := make([]string, len(entries))
-	for i, entry := range entries {
-		settingNames[i] = entry.Name
-	}
-	sort.Strings(settingNames)
-
-	for _, name := range settingNames {
-		printBriefSetting(cfg.Settings[name])
-	}
-}
-
-func printBriefCfg(targetName string, cfg syscfg.Cfg) {
-	if errText := cfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief syscfg for %s:\n", targetName)
-	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")
-		}
-		printPkgBriefCfg(pkgName, cfg, pkgNameEntryMap[pkgName])
-	}
-}
-
-func yamlPkgCfg(w io.Writer, pkgName string, cfg syscfg.Cfg,
-	entries []syscfg.CfgEntry) {
-
-	settingNames := make([]string, len(entries))
-	for i, entry := range entries {
-		settingNames[i] = entry.Name
-	}
-	sort.Strings(settingNames)
-
-	fmt.Fprintf(w, "    ### %s\n", pkgName)
-	for _, name := range settingNames {
-		fmt.Fprintf(w, "    %s: '%s'\n", name, cfg.Settings[name].Value)
-	}
-}
-
-func yamlCfg(cfg syscfg.Cfg) string {
-	if errText := cfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	pkgNameEntryMap := syscfg.EntriesByPkg(cfg)
-
-	pkgNames := make([]string, 0, len(pkgNameEntryMap))
-	for pkgName, _ := range pkgNameEntryMap {
-		pkgNames = append(pkgNames, pkgName)
-	}
-	sort.Strings(pkgNames)
-
-	buf := bytes.Buffer{}
-
-	fmt.Fprintf(&buf, "syscfg.vals:\n")
-	for i, pkgName := range pkgNames {
-		if i > 0 {
-			fmt.Fprintf(&buf, "\n")
-		}
-		yamlPkgCfg(&buf, pkgName, cfg, pkgNameEntryMap[pkgName])
-	}
-
-	return string(buf.Bytes())
-}
-
-func targetBuilderConfigResolve(b *builder.TargetBuilder) *resolve.Resolution {
-	res, err := b.Resolve()
-	if err != nil {
-		NewtUsage(nil, err)
-	}
-
-	warningText := strings.TrimSpace(res.WarningText())
-	if warningText != "" {
-		log.Warn(warningText + "\n")
-	}
-
-	return res
-}
-
-func targetConfigShowCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printCfg(b.GetTarget().Name(), res.Cfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func targetConfigBriefCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printBriefCfg(b.GetTarget().Name(), res.Cfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func valSettingString(vs val.ValSetting) string {
-	intVal, _ := vs.IntVal()
-
-	s := fmt.Sprintf("%d", intVal)
-	if vs.RefName != "" {
-		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", vs.RefName)
-	}
-
-	return s
-}
-
-func logLevelString(ls val.ValSetting) string {
-	intVal, _ := ls.IntVal()
-
-	s := fmt.Sprintf("%d (%s)", intVal, logcfg.LogLevelString(intVal))
-	if ls.RefName != "" {
-		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", ls.RefName)
-	}
-
-	return s
-}
-
-func printLogCfgOne(l logcfg.Log) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", l.Name)
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
-		l.Source.FullName())
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Module:  %s\n",
-		valSettingString(l.Module))
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Level:   %s\n",
-		logLevelString(l.Level))
-}
-
-func printLogCfg(targetName string, lcfg logcfg.LCfg) {
-	if errText := lcfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Log config for %s:\n",
-		targetName)
-
-	logNames := make([]string, 0, len(lcfg.Logs))
-	for name, _ := range lcfg.Logs {
-		logNames = append(logNames, name)
-	}
-	sort.Strings(logNames)
-
-	for i, logName := range logNames {
-		if i > 0 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-		printLogCfgOne(lcfg.Logs[logName])
-	}
-}
-
-func targetLogShowCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printLogCfg(b.GetTarget().Name(), res.LCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func printLogCfgBriefOne(l logcfg.Log, colWidth int) {
-	intMod, _ := l.Module.IntVal()
-	intLevel, _ := l.Level.IntVal()
-
-	levelStr := fmt.Sprintf("%d (%s)", intLevel,
-		logcfg.LogLevelString(intLevel))
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "%*s | %-8d | %-12s\n",
-		colWidth, l.Name, intMod, levelStr)
-}
-
-func printLogCfgBrief(targetName string, lcfg logcfg.LCfg) {
-	if errText := lcfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief log config for %s:\n",
-		targetName)
-
-	longest := 6
-	logNames := make([]string, 0, len(lcfg.Logs))
-	for name, _ := range lcfg.Logs {
-		logNames = append(logNames, name)
-		if len(name) > longest {
-			longest = len(name)
-		}
-	}
-	sort.Strings(logNames)
-
-	colWidth := longest + 4
-	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		"%*s | MODULE   | LEVEL\n", colWidth, "LOG")
-	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		"%s-+----------+--------------\n",
-		strings.Repeat("-", colWidth))
-	for _, logName := range logNames {
-		printLogCfgBriefOne(lcfg.Logs[logName], colWidth)
-	}
-}
-
-func targetLogBriefCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printLogCfgBrief(b.GetTarget().Name(), res.LCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func printStage(sf stage.StageFunc) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", sf.Name)
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
-		sf.Pkg.FullName())
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Stage:  %s\n",
-		valSettingString(sf.Stage))
-}
-
-func printStageBriefOne(sf stage.StageFunc, fnWidth int, pkgWidth int) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, " %-*s | %-*s | %s\n",
-		fnWidth, sf.Name,
-		pkgWidth, sf.Pkg.FullName(),
-		valSettingString(sf.Stage))
-}
-
-func printStageBriefTable(sfs []stage.StageFunc) {
-	longestPkg := 6
-	longestFn := 6
-	for _, sf := range sfs {
-		if len(sf.Name) > longestFn {
-			longestFn = len(sf.Name)
-		}
-		if len(sf.Pkg.FullName()) > longestPkg {
-			longestPkg = len(sf.Pkg.FullName())
-		}
-	}
-
-	pkgWidth := longestPkg + 2
-	fnWidth := longestFn + 2
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		" %-*s | %-*s | STAGE\n",
-		fnWidth, "FUNCTION",
-		pkgWidth, "PACKAGE")
-	util.StatusMessage(util.VERBOSITY_DEFAULT,
-		"-%s-+-%s-+----------\n",
-		strings.Repeat("-", fnWidth), strings.Repeat("-", pkgWidth))
-	for _, sf := range sfs {
-		printStageBriefOne(sf, fnWidth, pkgWidth)
-	}
-}
-
-func printSysinitCfg(targetName string, scfg sysinit.SysinitCfg) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysinit config for %s:\n",
-		targetName)
-
-	for i, sf := range scfg.StageFuncs {
-		if i > 0 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-		printStage(sf)
-	}
-}
-
-func printSysinitBrief(targetName string, scfg sysinit.SysinitCfg) {
-	if errText := scfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysinit config for %s:\n",
-		targetName)
-
-	printStageBriefTable(scfg.StageFuncs)
-}
-
-func targetSysinitShowCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printSysinitCfg(b.GetTarget().Name(), res.SysinitCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func targetSysinitBriefCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printSysinitBrief(b.GetTarget().Name(), res.SysinitCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func printSysdownCfg(targetName string, scfg sysdown.SysdownCfg) {
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Sysdown config for %s:\n",
-		targetName)
-
-	for i, sf := range scfg.StageFuncs {
-		if i > 0 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-		printStage(sf)
-	}
-}
-
-func targetSysdownShowCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printSysdownCfg(b.GetTarget().Name(), res.SysdownCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func printSysdownBrief(targetName string, scfg sysdown.SysdownCfg) {
-	if errText := scfg.ErrorText(); errText != "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
-	}
-
-	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief sysdown config for %s:\n",
-		targetName)
-
-	printStageBriefTable(scfg.StageFuncs)
-}
-
-func targetSysdownBriefCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	TryGetProject()
-
-	for i, arg := range args {
-		b, err := TargetBuilderForTargetOrUnittest(arg)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-
-		res := targetBuilderConfigResolve(b)
-		printSysdownBrief(b.GetTarget().Name(), res.SysdownCfg)
-
-		if i < len(args)-1 {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		}
-	}
-}
-
-func targetConfigInitCmd(cmd *cobra.Command, args []string) {
-	if len(args) < 1 {
-		NewtUsage(cmd,
-			util.NewNewtError("Must specify target or unittest name"))
-	}
-
-	type entry struct {
-		lpkg   *pkg.LocalPackage
-		path   string
-		b      *builder.TargetBuilder
-		exists bool
-	}
-
-	TryGetProject()
-
-	anyExist := false
-	entries := make([]entry, len(args))
-	for i, pkgName := range args {
-		e := &entries[i]
-
-		b, err := TargetBuilderForTargetOrUnittest(pkgName)
-		if err != nil {
-			NewtUsage(cmd, err)
-		}
-		e.b = b
-
-		e.lpkg = b.GetTestPkg()
-		if e.lpkg == nil {
-			e.lpkg = b.GetTarget().Package()
-		}
-
-		e.path = builder.PkgSyscfgPath(e.lpkg.BasePath())
-
-		if util.NodeExist(e.path) {
-			e.exists = true
-			anyExist = true
-		}
-	}
-
-	if anyExist && !newtutil.NewtForce {
-		util.StatusMessage(util.VERBOSITY_DEFAULT,
-			"Configuration files already exist:\n")
-		for _, e := range entries {
-			if e.exists {
-				util.StatusMessage(util.VERBOSITY_DEFAULT, "    * %s\n",
-					e.path)
-			}
-		}
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-
-		fmt.Printf("Overwrite them? (y/N): ")
-		rsp := PromptYesNo(false)
-		if !rsp {
-			return
-		}
-	}
-
-	for _, e := range entries {
-		res := targetBuilderConfigResolve(e.b)
-		yaml := yamlCfg(res.Cfg)
-
-		if err := ioutil.WriteFile(e.path, []byte(yaml), 0644); err != nil {
-			NewtUsage(nil, util.FmtNewtError("Error writing file \"%s\"; %s",
-				e.path, err.Error()))
-		}
-	}
-}
-
 func targetDepCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 1 {
 		NewtUsage(cmd,
@@ -1402,170 +782,6 @@ func AddTargetCommands(cmd *cobra.Command) {
 	targetCmd.AddCommand(copyCmd)
 	AddTabCompleteFn(copyCmd, targetList)
 
-	configHelpText := "View or populate a target's system configuration"
-
-	configCmd := &cobra.Command{
-		Use:   "config",
-		Short: configHelpText,
-		Long:  configHelpText,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmd.Usage()
-		},
-	}
-
-	targetCmd.AddCommand(configCmd)
-
-	configShowCmd := &cobra.Command{
-		Use:   "show <target> [target...]",
-		Short: "View a target's system configuration",
-		Long:  "View a target's system configuration",
-		Run:   targetConfigShowCmd,
-	}
-
-	configCmd.AddCommand(configShowCmd)
-	AddTabCompleteFn(configShowCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	configBriefCmd := &cobra.Command{
-		Use:   "brief <target> [target...]",
-		Short: "View a summary of target's system configuration",
-		Long:  "View a summary of target's system configuration",
-		Run:   targetConfigBriefCmd,
-	}
-
-	configCmd.AddCommand(configBriefCmd)
-	AddTabCompleteFn(configBriefCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	configInitCmd := &cobra.Command{
-		Use:   "init",
-		Short: "Populate a target's system configuration file",
-		Long: "Populate a target's system configuration file (syscfg). " +
-			"Unspecified settings are given default values.",
-		Run: targetConfigInitCmd,
-	}
-	configInitCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
-		"force", "f", false,
-		"Force overwrite of target configuration")
-
-	configCmd.AddCommand(configInitCmd)
-	AddTabCompleteFn(configInitCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	logHelpText := "View a target's log configuration"
-
-	logCmd := &cobra.Command{
-		Use:   "logcfg",
-		Short: logHelpText,
-		Long:  logHelpText,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmd.Usage()
-		},
-	}
-
-	targetCmd.AddCommand(logCmd)
-
-	logShowCmd := &cobra.Command{
-		Use:   "show <target> [target...]",
-		Short: "View a target's log configuration",
-		Long:  "View a target's log configuration",
-		Run:   targetLogShowCmd,
-	}
-
-	logCmd.AddCommand(logShowCmd)
-	AddTabCompleteFn(logShowCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	logBriefCmd := &cobra.Command{
-		Use:   "brief <target> [target...]",
-		Short: "View a summary of target's log configuration",
-		Long:  "View a summary of target's log configuration",
-		Run:   targetLogBriefCmd,
-	}
-
-	logCmd.AddCommand(logBriefCmd)
-	AddTabCompleteFn(logBriefCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	sysinitHelpText := "View a target's sysinit configuration"
-
-	sysinitCmd := &cobra.Command{
-		Use:   "sysinit",
-		Short: sysinitHelpText,
-		Long:  sysinitHelpText,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmd.Usage()
-		},
-	}
-
-	targetCmd.AddCommand(sysinitCmd)
-
-	sysinitShowCmd := &cobra.Command{
-		Use:   "show <target> [target...]",
-		Short: "View a target's sysinit configuration",
-		Long:  "View a target's sysinit configuration",
-		Run:   targetSysinitShowCmd,
-	}
-
-	sysinitCmd.AddCommand(sysinitShowCmd)
-	AddTabCompleteFn(sysinitShowCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	sysinitBriefCmd := &cobra.Command{
-		Use:   "brief <target> [target...]",
-		Short: "View a summary of target's sysinit configuration",
-		Long:  "View a summary of target's sysinit configuration",
-		Run:   targetSysinitBriefCmd,
-	}
-
-	sysinitCmd.AddCommand(sysinitBriefCmd)
-	AddTabCompleteFn(sysinitBriefCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	sysdownHelpText := "View a target's sysdown configuration"
-
-	sysdownCmd := &cobra.Command{
-		Use:   "sysdown",
-		Short: sysdownHelpText,
-		Long:  sysdownHelpText,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmd.Usage()
-		},
-	}
-
-	targetCmd.AddCommand(sysdownCmd)
-
-	sysdownShowCmd := &cobra.Command{
-		Use:   "show <target> [target...]",
-		Short: "View a target's sysdown configuration",
-		Long:  "View a target's sysdown configuration",
-		Run:   targetSysdownShowCmd,
-	}
-
-	sysdownCmd.AddCommand(sysdownShowCmd)
-	AddTabCompleteFn(sysdownShowCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
-	sysdownBriefCmd := &cobra.Command{
-		Use:   "brief <target> [target...]",
-		Short: "View a summary of target's sysdown configuration",
-		Long:  "View a summary of target's sysdown configuration",
-		Run:   targetSysdownBriefCmd,
-	}
-
-	sysdownCmd.AddCommand(sysdownBriefCmd)
-	AddTabCompleteFn(sysdownBriefCmd, func() []string {
-		return append(targetList(), unittestList()...)
-	})
-
 	depHelpText := "View a target's dependency graph."
 
 	depCmd := &cobra.Command{
@@ -1593,4 +809,8 @@ func AddTargetCommands(cmd *cobra.Command) {
 	AddTabCompleteFn(revdepCmd, func() []string {
 		return append(targetList(), unittestList()...)
 	})
+
+	for _, cmd := range targetCfgCmdAll() {
+		targetCmd.AddCommand(cmd)
+	}
 }


[mynewt-newt] 03/09: logcfg: `target logcfg ` commands

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit bec355f5ea0cf3c6b875c22b9ea9dc1e34daebb9
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Mon Oct 15 18:50:05 2018 -0700

    logcfg: `target logcfg <show | brief>` commands
    
    Add two new newt commands:
    
        newt target logcfg show <target>
        newt target logcfg brief <target>
    
    Both commands produce a report of all the logs configured for the
    target.  Example output:
    
    [SHOW]
        $ newt target logcfg show slinky-nrf52dk
    
        Log config for targets/slinky-nrf52dk:
        COREDUMP_LOG:
            Package: sys/coredump
            Module:  100              [COREDUMP_LOG_MODULE]
            Level:   3 (ERROR)        [COREDUMP_LOG_LEVEL]
            Flags:
    
        SENSORS_LOG:
            Package: sys/coredump
            Module:  99
            Level:   1 (INFO)         [COREDUMP_LOG_LEVEL]
            Flags:
    
    [BRIEF]
        $ newt target logcfg brief slinky-nrf52dk
    
        Brief log config for targets/slinky-nrf52dk:
                     LOG | MODULE   | LEVEL        | FLAGS
        -----------------+----------+--------------|----------
            COREDUMP_LOG | 100      | 3 (ERROR)    |
             SENSORS_LOG | 99       | 1 (INFO)     |
---
 newt/cli/target_cmds.go | 177 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go
index bf7d6dd..821865f 100644
--- a/newt/cli/target_cmds.go
+++ b/newt/cli/target_cmds.go
@@ -31,6 +31,7 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"mynewt.apache.org/newt/newt/builder"
+	"mynewt.apache.org/newt/newt/logcfg"
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/resolve"
@@ -778,6 +779,145 @@ func targetConfigBriefCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
+func logModuleString(ls logcfg.LogSetting) string {
+	intVal, _ := ls.IntVal()
+
+	s := fmt.Sprintf("%d", intVal)
+	if ls.RefName != "" {
+		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", ls.RefName)
+	}
+
+	return s
+}
+
+func logLevelString(ls logcfg.LogSetting) string {
+	intVal, _ := ls.IntVal()
+
+	s := fmt.Sprintf("%d (%s)", intVal, logcfg.LogLevelString(intVal))
+	if ls.RefName != "" {
+		s += fmt.Sprintf("%*s [%s]", 16-len(s), "", ls.RefName)
+	}
+
+	return s
+}
+
+func printLogCfgOne(l logcfg.Log) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%s:\n", l.Name)
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Package: %s\n",
+		l.Source.FullName())
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Module:  %s\n",
+		logModuleString(l.Module))
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "    Level:   %s\n",
+		logLevelString(l.Level))
+}
+
+func printLogCfg(targetName string, lcfg logcfg.LCfg) {
+	if errText := lcfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Log config for %s:\n",
+		targetName)
+
+	logNames := make([]string, 0, len(lcfg.Logs))
+	for name, _ := range lcfg.Logs {
+		logNames = append(logNames, name)
+	}
+	sort.Strings(logNames)
+
+	for i, logName := range logNames {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printLogCfgOne(lcfg.Logs[logName])
+	}
+}
+
+func targetLogShowCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printLogCfg(b.GetTarget().Name(), res.LCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func printLogCfgBriefOne(l logcfg.Log, colWidth int) {
+	intMod, _ := l.Module.IntVal()
+	intLevel, _ := l.Level.IntVal()
+
+	levelStr := fmt.Sprintf("%d (%s)", intLevel, logcfg.LogLevelString(intLevel))
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "%*s | %-8d | %-12s\n",
+		colWidth, l.Name, intMod, levelStr)
+}
+
+func printLogCfgBrief(targetName string, lcfg logcfg.LCfg) {
+	if errText := lcfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief log config for %s:\n",
+		targetName)
+
+	longest := 0
+	logNames := make([]string, 0, len(lcfg.Logs))
+	for name, _ := range lcfg.Logs {
+		logNames = append(logNames, name)
+		if len(name) > longest {
+			longest = len(name)
+		}
+	}
+	sort.Strings(logNames)
+
+	colWidth := longest + 4
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"%*s | MODULE   | LEVEL\n", colWidth, "LOG")
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"%s-+----------+--------------\n",
+		strings.Repeat("-", colWidth))
+	for _, logName := range logNames {
+		printLogCfgBriefOne(lcfg.Logs[logName], colWidth)
+	}
+}
+
+func targetLogBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printLogCfgBrief(b.GetTarget().Name(), res.LCfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
 func targetConfigInitCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 1 {
 		NewtUsage(cmd,
@@ -1130,6 +1270,43 @@ func AddTargetCommands(cmd *cobra.Command) {
 		return append(targetList(), unittestList()...)
 	})
 
+	logHelpText := "View a target's log configuration"
+
+	logCmd := &cobra.Command{
+		Use:   "logcfg",
+		Short: logHelpText,
+		Long:  logHelpText,
+		Run: func(cmd *cobra.Command, args []string) {
+			cmd.Usage()
+		},
+	}
+
+	targetCmd.AddCommand(logCmd)
+
+	logShowCmd := &cobra.Command{
+		Use:   "show <target> [target...]",
+		Short: "View a target's log configuration",
+		Long:  "View a target's log configuration",
+		Run:   targetLogShowCmd,
+	}
+
+	logCmd.AddCommand(logShowCmd)
+	AddTabCompleteFn(logShowCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
+	logBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's log configuration",
+		Long:  "View a summary of target's log configuration",
+		Run:   targetLogBriefCmd,
+	}
+
+	logCmd.AddCommand(logBriefCmd)
+	AddTabCompleteFn(logBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
 	depHelpText := "View a target's dependency graph."
 
 	depCmd := &cobra.Command{


[mynewt-newt] 05/09: stage: Use ValSetting (generic setting value)

Posted by cc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit 1a4ef35daa7e1775b0092e731b03ac9e2c34b504
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 24 17:02:43 2018 -0700

    stage: Use ValSetting (generic setting value)
---
 newt/stage/stage.go | 55 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/newt/stage/stage.go b/newt/stage/stage.go
index ee2dead..e701250 100644
--- a/newt/stage/stage.go
+++ b/newt/stage/stage.go
@@ -36,17 +36,43 @@ import (
 	log "github.com/Sirupsen/logrus"
 
 	"mynewt.apache.org/newt/newt/pkg"
+	"mynewt.apache.org/newt/newt/syscfg"
+	"mynewt.apache.org/newt/newt/val"
 	"mynewt.apache.org/newt/util"
 )
 
 type StageFunc struct {
-	Stage      int
+	Stage      val.ValSetting
 	Name       string
 	ReturnType string
 	ArgList    string
 	Pkg        *pkg.LocalPackage
 }
 
+func NewStageFunc(name string, textVal string,
+	p *pkg.LocalPackage, cfg *syscfg.Cfg) (StageFunc, error) {
+
+	vs, err := val.ResolveValSetting(textVal, cfg)
+	if err != nil {
+		return StageFunc{}, err
+	}
+
+	// Ensure setting resolves to an integer.
+	if _, err := vs.IntVal(); err != nil {
+		return StageFunc{}, util.FmtNewtError("Invalid stage setting: %s=%s; "+
+			"value does not resolve to an integer",
+			name, textVal)
+	}
+
+	sf := StageFunc{
+		Name:  name,
+		Stage: vs,
+		Pkg:   p,
+	}
+
+	return sf, nil
+}
+
 type stageFuncSorter struct {
 	// Used in logging; either "sysinit" or "sysdown".
 	funcType string
@@ -66,10 +92,13 @@ func (s stageFuncSorter) Less(i, j int) bool {
 	a := s.fns[i]
 	b := s.fns[j]
 
+	inta, _ := a.Stage.IntVal()
+	intb, _ := b.Stage.IntVal()
+
 	// 1: Sort by stage number.
-	if a.Stage < b.Stage {
+	if inta < intb {
 		return true
-	} else if b.Stage < a.Stage {
+	} else if intb < inta {
 		return false
 	}
 
@@ -130,20 +159,22 @@ func WriteCalls(sortedFuncs []StageFunc, argList string, w io.Writer) {
 	dupCount := 0
 
 	for i, f := range sortedFuncs {
-		if f.Stage != prevStage {
-			prevStage = f.Stage
+		intStage, _ := f.Stage.IntVal()
+
+		if intStage != prevStage {
+			prevStage = intStage
 			dupCount = 0
 
 			if i != 0 {
 				fmt.Fprintf(w, "\n")
 			}
-			fmt.Fprintf(w, "    /*** Stage %d */\n", f.Stage)
+			fmt.Fprintf(w, "    /*** Stage %d */\n", intStage)
 		} else {
 			dupCount += 1
 		}
 
 		fmt.Fprintf(w, "    /* %d.%d: %s (%s) */\n",
-			f.Stage, dupCount, f.Name, f.Pkg.Name())
+			intStage, dupCount, f.Name, f.Pkg.Name())
 		fmt.Fprintf(w, "    %s(%s);\n", f.Name, argList)
 	}
 }
@@ -156,20 +187,22 @@ func WriteArr(sortedFuncs []StageFunc, w io.Writer) {
 	dupCount := 0
 
 	for i, f := range sortedFuncs {
-		if f.Stage != prevStage {
-			prevStage = f.Stage
+		intStage, _ := f.Stage.IntVal()
+
+		if intStage != prevStage {
+			prevStage = intStage
 			dupCount = 0
 
 			if i != 0 {
 				fmt.Fprintf(w, "\n")
 			}
-			fmt.Fprintf(w, "    /*** Stage %d */\n", f.Stage)
+			fmt.Fprintf(w, "    /*** Stage %d */\n", intStage)
 		} else {
 			dupCount += 1
 		}
 
 		fmt.Fprintf(w, "    /* %d.%d: %s (%s) */\n",
-			f.Stage, dupCount, f.Name, f.Pkg.Name())
+			intStage, dupCount, f.Name, f.Pkg.Name())
 		fmt.Fprintf(w, "    %s,\n", f.Name)
 	}
 	fmt.Fprintf(w, "\n")