You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/03/14 18:02:37 UTC
[mynewt-newt] 03/03: Add sysinit graph output in DOT format
This is an automated email from the ASF dual-hosted git repository.
andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git
commit f793ccec2d849b916d83c9e94263e3e51ed8d24b
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Mar 7 11:03:42 2022 +0100
Add sysinit graph output in DOT format
This adds "newt target sysinit graphviz" subcommand that outputs sysinit
structure in DOT format which allows to render a graph of dependencies.
The simplest way to create a graph is by using Graphviz and ImageMagick:
$ newt target sysinit graphviz targetname | dot -Tsvg | display
---
newt/cli/target_cfg_cmds.go | 59 +++++++++++++++++++++++++++++++++++++++++++++
newt/stage/stage.go | 1 +
newt/sysinit/sysinit.go | 3 +++
3 files changed, 63 insertions(+)
diff --git a/newt/cli/target_cfg_cmds.go b/newt/cli/target_cfg_cmds.go
index f7a0dc9..98352dd 100644
--- a/newt/cli/target_cfg_cmds.go
+++ b/newt/cli/target_cfg_cmds.go
@@ -575,6 +575,30 @@ func printSysinitBrief(targetName string, scfg sysinit.SysinitCfg) {
printStageBriefTable(scfg.StageFuncs)
}
+func printSysinitGraphviz(targetName string, scfg sysinit.SysinitCfg) {
+ if errText := scfg.ErrorText(); errText != "" {
+ util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+ }
+
+ fmt.Printf("digraph sysinit {\n")
+ for _, sf := range scfg.StageFuncs {
+ if len(sf.Stage.Afters) == 0 && len(sf.Stage.Befores) == 0 {
+ stage, _ := sf.Stage.IntVal()
+ fmt.Printf(" %s [label=\"%s (%d)\"];\n", sf.Name, sf.Name, stage)
+ }
+ for _, depSf := range sf.DepsI {
+ fmt.Printf(" %s -> %s;\n", sf.Name, depSf.Name)
+ }
+ for _, depStr := range sf.Stage.Afters {
+ fmt.Printf(" %s -> %s [label=\"$after:%s\"];\n", depStr, sf.Name, depStr)
+ }
+ for _, depStr := range sf.Stage.Befores {
+ fmt.Printf(" %s -> %s [label=\"$before:%s\"];\n", sf.Name, depStr, depStr)
+ }
+ }
+ fmt.Printf("}\n")
+}
+
func targetSysinitShowCmd(cmd *cobra.Command, args []string) {
if len(args) < 1 {
NewtUsage(cmd,
@@ -621,6 +645,29 @@ func targetSysinitBriefCmd(cmd *cobra.Command, args []string) {
}
}
+func targetSysinitGraphvizCmd(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)
+ printSysinitGraphviz(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)
@@ -939,6 +986,18 @@ func targetCfgCmdAll() []*cobra.Command {
return append(targetList(), unittestList()...)
})
+ sysinitGraphvizCmd := &cobra.Command{
+ Use: "graphviz <target> [target...]",
+ Short: "Print a graph representation of target's sysinit configuration (DOT format)",
+ Long: "Print a graph representation of target's sysinit configuration (DOT format)",
+ Run: targetSysinitGraphvizCmd,
+ }
+
+ sysinitCmd.AddCommand(sysinitGraphvizCmd)
+ AddTabCompleteFn(sysinitGraphvizCmd, func() []string {
+ return append(targetList(), unittestList()...)
+ })
+
sysdownHelpText := "View a target's sysdown configuration"
sysdownCmd := &cobra.Command{
diff --git a/newt/stage/stage.go b/newt/stage/stage.go
index b028e44..4e39ca2 100644
--- a/newt/stage/stage.go
+++ b/newt/stage/stage.go
@@ -48,6 +48,7 @@ type StageFunc struct {
ArgList string
Pkg *pkg.LocalPackage
Deps []*StageFunc
+ DepsI []*StageFunc
Resolved bool
Resolving bool
}
diff --git a/newt/sysinit/sysinit.go b/newt/sysinit/sysinit.go
index 73c822d..efa226a 100644
--- a/newt/sysinit/sysinit.go
+++ b/newt/sysinit/sysinit.go
@@ -164,6 +164,9 @@ func ResolveStageFuncsOrder(sfs []stage.StageFunc) ([]stage.StageFunc, error) {
for _, sfsP := range sfsPrev {
for _, sfsC := range sfsCurr {
sfsP.Deps = append(sfsP.Deps, sfsC)
+ // Keep separate list of implicit dependencies
+ // This is only used for Graphviz output
+ sfsP.DepsI = append(sfsP.DepsI, sfsC)
}
}