Delve代码分析笔记(4)——构建command tree

Delve使用cobra来构造command tree。先看root command,也就是dlv

func New() *cobra.Command {
    ......
    // Main dlv root command.
    RootCommand = &cobra.Command{
        Use:   "dlv",
        Short: "Delve is a debugger for the Go programming language.",
        Long:  dlvCommandLongDesc,
    }

    RootCommand.PersistentFlags().StringVarP(&Addr, "listen", "l", "localhost:0", "Debugging server listen address.")
    RootCommand.PersistentFlags().BoolVarP(&Log, "log", "", false, "Enable debugging server logging.")
    RootCommand.PersistentFlags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
    RootCommand.PersistentFlags().BoolVarP(&AcceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connections. Note that the server API is not reentrant and clients will have to coordinate")
    RootCommand.PersistentFlags().IntVar(&ApiVersion, "api-version", 1, "Selects API version when headless")
    RootCommand.PersistentFlags().StringVar(&InitFile, "init", "", "Init file, executed by the terminal client.")
    RootCommand.PersistentFlags().StringVar(&BuildFlags, "build-flags", buildFlagsDefault, "Build flags, to be passed to the compiler.")
    ......
}

因为dlv command没有实现run函数,所以单独运行dlv命令只会打印cobra帮忙生成的默认输出:

# dlv
Delve is a source level debugger for Go programs.

......

Usage:
  dlv [command]

Available Commands:
  version     Prints version.
  ......
Flags:
      --accept-multiclient[=false]: Allows a headless server to accept multiple client connections. Note that the server API is not reentrant and clients will have to coordinate
    ......

依次为Long descriptionUsageAvailable Commands等等。

再以trace subcommand为例,看如何把subcommand加到root command里:

......
// 'trace' subcommand.
traceCommand := &cobra.Command{
    Use:   "trace [package] regexp",
    Short: "Compile and begin tracing program.",
    Long:  "Trace program execution. Will set a tracepoint on every function matching the provided regular expression and output information when tracepoint is hit.",
    Run:   traceCmd,
}
traceCommand.Flags().IntVarP(&traceAttachPid, "pid", "p", 0, "Pid to attach to.")
traceCommand.Flags().IntVarP(&traceStackDepth, "stack", "s", 0, "Show stack trace with given depth.")
RootCommand.AddCommand(traceCommand)
......

Cobra提供两种flags
a)Persistent Flags:对当前命令及其子命令都有效;
b)Local Flags:只对当前命令有效。

 

Delve代码分析笔记(3)——config

Delve程序运行起来以后,首先就会加载和解析配置文件:

func New() *cobra.Command {
    // Config setup and load.
    conf = config.LoadConfig()
    ......
}

Delve的配置文件位于用户home目录下的.dlv文件夹下,文件名是config.yml。例如,如果是root用户,则配置文件的全路径是:/root/.dlv/config.yml。目前配置文件只支持为命令指定别名。

config包只包含一个config.go文件。代码也比较简单,归纳起来就是:如果用户没有创建配置文件,则替用户创建一个(里面没有实质内容),然后读取配置文件内容,并把Config结构体(定义如下)返回给调用者。

// Config defines all configuration options available to be set through the config file.
type Config struct {
    Aliases map[string][]string
}