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)
 			}
 		}