Go 1.8rc3 源代码学习:cmd go
前言命令行工具 go 相关的代码在 <go-src>/src/cmd/go,目录结构 <go-src>/src/cmd/go internal testdata alldocs.go go11.go go_test.go go_unix_test.go go_windows_test.go main.go mkalldocs.sh note_test.sh note_test.go vendor_test.go
internal 目录下基本上按照 go "子命令" 进行组织,可以看到常用的子命令比如 help,list,run .etc <go-src>/src/cmd/go internal base bug get help list run ... main.gomain.go 是 go 命令的入口,为了优雅的支持各种 "子命令",main.go 将各个子命令对象保存在数组里,通过遍历数组找到具体的子命令,然后调用各个子命令的 run 方法 for _,cmd := range base.Commands { if cmd.Name() == args[0] && cmd.Runnable() { cmd.Flag.Usage = func() { cmd.Usage() } if cmd.CustomFlags { args = args[1:] } else { cmd.Flag.Parse(args[1:]) args = cmd.Flag.Args() } cmd.Run(cmd,args) base.Exit() return } } Command structA command is an implementation of a go command type Command struct { // Run runs the command. // The args are the arguments after the command name. Run func(cmd *Command,args []string) // UsageLine is the one-line usage message. // The first word in the line is taken to be the command name. UsageLine string // Short is the short description shown in the 'go help' output. Short string // Long is the long message shown in the 'go help <this-command>' output. Long string // Flag is a set of flags specific to this command. Flag flag.FlagSet // CustomFlags indicates that the command will do its own // flag parsing. CustomFlags bool } go 支持的所有 Command 存放在 base package 的 Command 数组 Command,并在 main.go 的 init 函数中初始化 func init() { base.Commands = []*base.Command{ work.CmdBuild,clean.CmdClean,doc.CmdDoc,envcmd.CmdEnv,bug.CmdBug,fix.CmdFix,fmtcmd.CmdFmt,generate.CmdGenerate,get.CmdGet,work.CmdInstall,list.CmdList,run.CmdRun,test.CmdTest,tool.CmdTool,version.CmdVersion,vet.CmdVet,.etc } } go buildbuild command 的相关代码在 <go-src>/src/cmd/go/internal/work/build.go,在讨论具体的流程之前,我们先来看一些和 build 相关的数据结构 toolchain interfacetoolchain 接口定义了在编译过程中一些通用的方法 type toolchain interface { // gc runs the compiler in a specific directory on a set of files // and returns the name of the generated output file. gc(b *Builder,p *load.Package,archive,obj string,asmhdr bool,importArgs []string,gofiles []string) (ofile string,out []byte,err error) // cc runs the toolchain's C compiler in a directory on a C file // to produce an output file. cc(b *Builder,objdir,ofile,cfile string) error // asm runs the assembler in a specific directory on specific files // and returns a list of named output files. asm(b *Builder,sfiles []string) ([]string,error) // pkgpath builds an appropriate path for a temporary package file. Pkgpath(basedir string,p *load.Package) string // pack runs the archive packer in a specific directory to create // an archive from a set of object files. // typically it is run in the object directory. pack(b *Builder,objDir,afile string,ofiles []string) error // ld runs the linker to create an executable starting at mainpkg. ld(b *Builder,root *Action,out string,allactions []*Action,mainpkg string,ofiles []string) error // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions ldShared(b *Builder,toplevelactions []*Action,allactions []*Action) error compiler() string linker() string } noToolchaingoToolchaingccgoToolchainActionAn action represents a single action in the action graph type Action struct { ... Deps []*Action triggers []*Action ... } BuilderA Builder holds global state about a build. It does not hold per-package state,because we build packages in parallel,and the builder is shared. type Builder struct { ... ready actionQueue } 总结(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |