func (command *GoCrossCompile) Execute(context *console.Context) (err error) { if len(context.Args) <= 2 { return fmt.Errorf("need gofile parameter") } targetFile := context.FlagSet().Arg(0) kmgc, err := kmgConfig.LoadEnvFromWd() if err != nil { return } targetName := kmgFile.GetFileBaseWithoutExt(targetFile) if command.outputPath == "" { command.outputPath = filepath.Join(kmgc.ProjectPath, "bin") } for _, target := range kmgc.CrossCompileTarget { fileName := targetName + "_" + target.GetGOOS() + "_" + target.GetGOARCH() if target.GetGOOS() == "windows" { fileName = fileName + ".exe" } outputFilePath := filepath.Join(command.outputPath, fileName) cmd := kmgCmd.NewStdioCmd(context, "go", "build", "-o", outputFilePath, targetFile) kmgCmd.SetCmdEnv(cmd, "GOOS", target.GetGOOS()) kmgCmd.SetCmdEnv(cmd, "GOARCH", target.GetGOARCH()) kmgCmd.SetCmdEnv(cmd, "GOPATH", kmgc.GOPATHToString()) err = cmd.Run() if err != nil { return err } } return }
func init() { var err error Env, err = kmgConfig.LoadEnvFromWd() if err != nil { panic(fmt.Errorf("can not getEnv,do you forget create a .kmg.yml at project root? err: %s", err)) } }
func (command *GoCrossCompileInit) Execute(context *console.Context) (err error) { kmgc, err := kmgConfig.LoadEnvFromWd() if err != nil { return } GOROOT := kmgc.GOROOT if GOROOT == "" { return fmt.Errorf("you must set $GOROOT in environment to use GoCrossComplieInit") } var makeShellArgs []string var makeShellName string runCmdPath := filepath.Join(GOROOT, "src") if runtime.GOOS == "windows" { makeShellName = "cmd" makeShellArgs = []string{"/C", filepath.Join(GOROOT, "src", "make.bat"), "--no-clean"} } else { makeShellName = filepath.Join(GOROOT, "src", "make.bash") makeShellArgs = []string{"--no-clean"} } for _, target := range kmgc.CrossCompileTarget { cmd := kmgCmd.NewStdioCmd(context, makeShellName, makeShellArgs...) kmgCmd.SetCmdEnv(cmd, "GOOS", target.GetGOOS()) kmgCmd.SetCmdEnv(cmd, "GOARCH", target.GetGOARCH()) cmd.Dir = runCmdPath err = cmd.Run() if err != nil { return err } } return }
func runGoCrossCompileInit() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) GOROOT := kmgc.GOROOT if GOROOT == "" { //guess GOROOT out, err := exec.Command("go", "env", "GOROOT").CombinedOutput() kmgConsole.ExitOnErr(err) GOROOT = strings.TrimSpace(string(out)) if GOROOT == "" { kmgConsole.ExitOnErr(fmt.Errorf("you must set $GOROOT in environment to use GoCrossComplieInit")) } } var makeShellArgs []string var makeShellName string runCmdPath := filepath.Join(GOROOT, "src") if runtime.GOOS == "windows" { makeShellName = "cmd" makeShellArgs = []string{"/C", filepath.Join(GOROOT, "src", "make.bat"), "--no-clean"} } else { makeShellName = filepath.Join(GOROOT, "src", "make.bash") makeShellArgs = []string{"--no-clean"} } for _, target := range kmgc.CrossCompileTarget { err = kmgCmd.CmdSlice(append([]string{makeShellName}, makeShellArgs...)). MustSetEnv("GOOS", target.GetGOOS()). MustSetEnv("GOARCH", target.GetGOARCH()). SetDir(runCmdPath). Run() kmgConsole.ExitOnErr(err) } return }
// run go command in current project // 1.go build -i github.com/xxx/xxx use to get fastest speed of build. // 2.try remove pkg directory if you found you change is ignore. func GoCommand() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) err = kmgCmd.CmdSlice(append([]string{"go"}, os.Args[1:]...)). MustSetEnv("GOPATH", kmgc.GOPATHToString()).StdioRun() kmgConsole.ExitOnErr(err) }
func (command *Go) Execute(context *console.Context) (err error) { cmd := kmgCmd.NewStdioCmd(context, "go", context.Args[2:]...) kmgc, err := kmgConfig.LoadEnvFromWd() if err != nil { return } err = kmgCmd.SetCmdEnv(cmd, "GOPATH", kmgc.GOPATHToString()) if err != nil { return err } return cmd.Run() }
// go install bug func GoRunCmd() { runtime.GOMAXPROCS(runtime.NumCPU()) kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) goPath := kmgc.GOPATHToString() //假设第一个是文件或者package名称,后面是传给命令行的参数 if len(os.Args) < 2 { kmgConsole.ExitOnErr(fmt.Errorf("you need pass in running filename")) return } pathOrPkg := os.Args[1] _, err = os.Stat(pathOrPkg) switch { case os.IsNotExist(err): //package名称 goRunPackageName(goPath, pathOrPkg) return case err != nil: //其他错误 kmgConsole.ExitOnErr(err) return default: //文件或目录 wd, err := os.Getwd() kmgConsole.ExitOnErr(err) if wd == filepath.Join(goPath, "src") { //用户在src下 goRunPackageName(goPath, pathOrPkg) return } // 找出指向的这个文件的所有import的包,全部install一遍,再go run //靠谱实现这个东西的复杂度太高,目前已有的方案不能达到目标,暂时先使用go run // 如果有需要使用请把这个文件放到package里面,或者运行前删除pkg目录. // TODO 速度比较慢. //已经证实不行的方案: // 1.在临时目录建一个package,并且使用GOPATH指向那个临时目录,缓存会出现问题,并且效果和 go build -i 没有区别 // 2.使用go build -i 效果和直接go run没有区别(缓存还是会出现问题) //找出这个文件所有的 import然后install 一遍 importPathList, err := kmgGoSource.GetImportPathListFromFile(pathOrPkg) kmgConsole.ExitOnErr(err) for _, pkgPath := range importPathList { runCmdSliceWithGoPath(goPath, []string{"go", "install", pkgPath}) } runCmdSliceWithGoPath(goPath, append([]string{"go", "run"}, os.Args[1:]...)) return } kmgConsole.ExitOnErr(fmt.Errorf("unexpected run path")) }
func (command *GoFmt) Execute(context *console.Context) (err error) { var fmtDir string kmgc, err := kmgConfig.LoadEnvFromWd() if err == nil { fmtDir = kmgc.ProjectPath } else { fmtDir, err = os.Getwd() if err != nil { return } } cmd := kmgCmd.NewStdioCmd(context, "gofmt", "-w=true", ".") cmd.Dir = fmtDir return cmd.Run() }
/* 递归目录的go test 支持.kmg.yml目录结构提示文件(该文件必须存在) -v 更详细的描述 -m 一个模块名,从这个模块名开始递归目录测试 -d 一个目录名,从这个目录开始递归目录测试 -bench benchmarks参数,直接传递到go test -onePackage 不递归目录测试,仅测试一个package */ func runGoTest() { command := GoTest{} flag.BoolVar(&command.v, "v", false, "show output of test") flag.StringVar(&command.dir, "d", "", "dir path to test") flag.StringVar(&command.moduleName, "m", "", "module name to test") flag.StringVar(&command.bench, "bench", "", "bench parameter pass to go test") flag.BoolVar(&command.onePackage, "onePackage", false, "only test one package") flag.StringVar(&command.runArg, "run", "", "Run only those tests and examples matching the regular expression.") flag.BoolVar(&command.onlyBuild, "onlyBuild", false, "only build all package(not test)") flag.Parse() kmgc, err := kmgConfig.LoadEnvFromWd() if err == nil { command.gopath = kmgc.GOPATH[0] } else { if kmgConfig.IsNotFound(err) { command.gopath = os.Getenv("GOPATH") } else { kmgConsole.ExitOnErr(err) } } //find root path root, err := command.findRootPath() kmgConsole.ExitOnErr(err) command.buildContext = &build.Context{ GOPATH: command.gopath, Compiler: build.Default.Compiler, } if command.onePackage { err = command.handlePath(root) kmgConsole.ExitOnErr(err) } err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { return nil } if kmgFile.IsDotFile(path) { return filepath.SkipDir } return command.handlePath(path) }) kmgConsole.ExitOnErr(err) }
/* GoCrossComplie [gofile] the output file will put into $project_root/bin/name_GOOS_GOARCH[.exe] */ func runGoCrossCompile() { command := GoCrossCompile{} flag.StringVar(&command.outputPath, "o", "", "output file dir(file name come from source file name),default to $project_root/bin") flag.StringVar(&command.version, "v", "", "version string in output file name") flag.StringVar(&command.platform, "platform", "", "platform(default use .kmg.yml config)") flag.Parse() if len(os.Args) <= 1 { kmgConsole.ExitOnErr(fmt.Errorf("need gofile parameter")) return } targetFile := flag.Arg(0) kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) targetName := kmgFile.GetFileBaseWithoutExt(targetFile) if command.outputPath == "" { command.outputPath = filepath.Join(kmgc.ProjectPath, "bin") } targetList := []kmgConfig.CompileTarget{} if command.platform == "" { targetList = kmgc.CrossCompileTarget } else { targetList = []kmgConfig.CompileTarget{kmgConfig.CompileTarget(command.platform)} } for _, target := range targetList { fileName := "" if command.version == "" { fileName = targetName + "_" + target.GetGOOS() + "_" + target.GetGOARCH() } else { fileName = targetName + "_" + command.version + "_" + target.GetGOOS() + "_" + target.GetGOARCH() } if target.GetGOOS() == "windows" { fileName = fileName + ".exe" } outputFilePath := filepath.Join(command.outputPath, fileName) err := kmgCmd.CmdSlice([]string{"go", "build", "-i", "-o", outputFilePath, targetFile}). MustSetEnv("GOOS", target.GetGOOS()). MustSetEnv("GOARCH", target.GetGOARCH()). MustSetEnv("GOPATH", kmgc.GOPATHToString()). Run() kmgConsole.ExitOnErr(err) } return }
func makeCmd() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) if kmgc.Make == "" { kmgConsole.ExitOnStderr(errors.New("Please defined a Make command in .kmg.yml file to use kmg make")) return } if len(os.Args) >= 2 && kmgc.MakeSubCommandMap != nil { for cmdName, cmdString := range kmgc.MakeSubCommandMap { if strings.EqualFold(cmdName, os.Args[1]) { args := strings.Split(cmdString, " ") os.Args = os.Args[1:] runCommand(kmgc, args) return } } } args := strings.Split(kmgc.Make, " ") runCommand(kmgc, args) }
func (command *GoWatch) Execute(context *console.Context) (err error) { command.isDebug = false command.context = context if len(context.Args) != 3 { return fmt.Errorf("usage: %s watch [packages]", context.ExecutionName) } command.mainFilePath = context.Args[2] kmgc, err := kmgConfig.LoadEnvFromWd() if err != nil { return } command.GOPATH = kmgc.GOPATHToString() command.wd = kmgc.ProjectPath runner, err := fsnotify.NewRunner(10000) if err != nil { return err } runner.Watcher.ErrorHandler = func(err error) { fmt.Println("watcher.Error error: ", err) } runner.Watcher.IsIgnorePath = func(path string) bool { if fsnotify.DefaultIsIgnorePath(path) { return true } if path == command.targetFilePath { return true } return false } runner.Watcher.WatchRecursion(command.wd) // wait forever runner.Run(func() { err := command.restart() if err != nil { fmt.Println("command.restart() error: ", err) } }) return nil }
func (command *GoTest) Execute(context *console.Context) (err error) { command.context = context kmgc, err := kmgConfig.LoadEnvFromWd() if err == nil { command.gopath = kmgc.GOPATH[0] } else { if kmgConfig.IsNotFound(err) { command.gopath = os.Getenv("GOPATH") } else { return } } //find root path root, err := command.findRootPath(context) if err != nil { return } command.buildContext = &build.Context{ GOPATH: command.gopath, Compiler: build.Default.Compiler, } if command.onePackage { return command.handlePath(root) } return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { return nil } if kmgFile.IsDotFile(path) { return filepath.SkipDir } return command.handlePath(path) }) }
// use `kmg goenv` to setup current work project GOPATH func GoEnvCmd() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) fmt.Println("export", "GOPATH="+kmgc.GOPATHToString()) //TODO 解决转义问题? }
func (command *GoAllImport) Execute(context *console.Context) (err error) { kmgc, err := kmgConfig.LoadEnvFromWd() if err != nil { return } command.gopath = kmgc.GOPATH[0] root := command.dir exist, err := kmgFile.FileExist(root) if err != nil { return } if !exist { return fmt.Errorf("[GoAllImport] dir path[%s] not exist", root) } c := &build.Context{ GOPATH: kmgc.GOPATHToString(), Compiler: build.Default.Compiler, } root, err = kmgFile.Realpath(root) if err != nil { return } moduleList := []string{} err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { return nil } if kmgFile.IsDotFile(path) { return filepath.SkipDir } pkg, err := c.ImportDir(path, build.ImportMode(0)) if err != nil { //忽略异常文件夹,(不是golang的目录之类的) return nil } if pkg.IsCommand() { return nil } pkgFullName, err := filepath.Rel(command.gopath, path) if err != nil { return err } moduleList = append(moduleList, strings.TrimPrefix(filepath.ToSlash(pkgFullName), "src/")) return nil }) if err != nil { return } tpl := template.Must(template.New("").Parse(`package {{.PackageName}} import( {{range .ModuleList}} _ "{{.}}" {{end}} ) `)) buf := &bytes.Buffer{} tpl.Execute(buf, struct { PackageName string ModuleList []string }{ PackageName: command.packageName, ModuleList: moduleList, }) fmt.Println(string(buf.Bytes())) return }