goc build init version

This commit is contained in:
lyyyuna 2021-06-20 21:14:21 +08:00
parent 4c9163ce64
commit 8df7498c33
7 changed files with 117 additions and 25 deletions

View File

@ -1,6 +1,10 @@
package build package build
import ( import (
"os"
"os/exec"
"github.com/qiniu/goc/v2/pkg/config"
"github.com/qiniu/goc/v2/pkg/cover" "github.com/qiniu/goc/v2/pkg/cover"
"github.com/qiniu/goc/v2/pkg/flag" "github.com/qiniu/goc/v2/pkg/flag"
"github.com/qiniu/goc/v2/pkg/log" "github.com/qiniu/goc/v2/pkg/log"
@ -17,9 +21,13 @@ type Build struct {
// consumes args, get package dirs, read project meta info. // consumes args, get package dirs, read project meta info.
func NewBuild(cmd *cobra.Command, args []string) *Build { func NewBuild(cmd *cobra.Command, args []string) *Build {
b := &Build{} b := &Build{}
// 1. 解析 goc 命令行和 go 命令行
remainedArgs := flag.BuildCmdArgsParse(cmd, args) remainedArgs := flag.BuildCmdArgsParse(cmd, args)
// 2. 解析 go 包位置
flag.GetPackagesDir(remainedArgs) flag.GetPackagesDir(remainedArgs)
// 3. 读取工程元信息go.mod, pkgs list ...
b.readProjectMetaInfo() b.readProjectMetaInfo()
// 4. 展示元信息
b.displayProjectMetaInfo() b.displayProjectMetaInfo()
return b return b
@ -31,12 +39,54 @@ func NewBuild(cmd *cobra.Command, args []string) *Build {
// 2. inject cover variables and functions into the project, // 2. inject cover variables and functions into the project,
// 3. build the project in temp. // 3. build the project in temp.
func (b *Build) Build() { func (b *Build) Build() {
// 1. 拷贝至临时目录
b.copyProjectToTmp() b.copyProjectToTmp()
// defer b.clean() // defer b.clean()
log.Donef("project copied to temporary directory") log.Donef("project copied to temporary directory")
// 2. inject cover vars
// inject cover vars
cover.Inject() cover.Inject()
// 3. build in the temp project
// build in the temp project b.doBuildInTemp()
}
func (b *Build) doBuildInTemp() {
goflags := config.GocConfig.Goflags
// 检查用户是否自定义了 -o
oSet := false
for _, flag := range goflags {
if flag == "-o" {
oSet = true
}
}
// 如果没被设置就加一个至原命令执行的目录
if !oSet {
goflags = append(goflags, "-o", config.GocConfig.CurWd)
}
pacakges := config.GocConfig.TmpPkgDir
if config.GocConfig.ContainSpecialPattern {
pacakges = pacakges + "/..."
}
goflags = append(goflags, pacakges)
args := []string{"build"}
args = append(args, goflags...)
// go 命令行由 go build [-o output] [build flags] [packages] 组成
cmd := exec.Command("go", args...)
cmd.Dir = config.GocConfig.TmpModProjectDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Infof("go build cmd is: %v", cmd.Args)
if err := cmd.Start(); err != nil {
log.Fatalf("fail to execute go build: %v", err)
}
if err := cmd.Wait(); err != nil {
log.Fatalf("fail to execute go build: %v", err)
}
// done
log.Donef("go build done")
} }

View File

@ -19,11 +19,10 @@ func (b *Build) readProjectMetaInfo() {
// get gopath & gobin // get gopath & gobin
config.GocConfig.GOPATH = b.readGOPATH() config.GocConfig.GOPATH = b.readGOPATH()
config.GocConfig.GOBIN = b.readGOBIN() config.GocConfig.GOBIN = b.readGOBIN()
// 获取当前目录及其依赖的 package list // 获取 [packages] 及其依赖的 package list
config.GocConfig.Pkgs = b.listPackages(config.GocConfig.CurPkgDir) pkgs := b.listPackages(config.GocConfig.CurPkgDir)
// get mod info // get mod info
pkgs := config.GocConfig.Pkgs
for _, pkg := range pkgs { for _, pkg := range pkgs {
// check if go modules is enabled // check if go modules is enabled
if pkg.Module == nil { if pkg.Module == nil {
@ -36,6 +35,13 @@ func (b *Build) readProjectMetaInfo() {
break break
} }
// 如果包目录不是工程根目录,那再次 go list 一次,获取整个工程的包信息
if config.GocConfig.CurPkgDir != config.GocConfig.CurModProjectDir {
config.GocConfig.Pkgs = b.listPackages(config.GocConfig.CurModProjectDir)
} else {
config.GocConfig.Pkgs = pkgs
}
// get tmp folder name // get tmp folder name
config.GocConfig.TmpModProjectDir = filepath.Join(os.TempDir(), tmpFolderName(config.GocConfig.CurModProjectDir)) config.GocConfig.TmpModProjectDir = filepath.Join(os.TempDir(), tmpFolderName(config.GocConfig.CurModProjectDir))
// get cur pkg dir in the corresponding tmp dir // get cur pkg dir in the corresponding tmp dir
@ -47,7 +53,6 @@ func (b *Build) readProjectMetaInfo() {
// displayProjectMetaInfo prints basic infomation of this project to stdout // displayProjectMetaInfo prints basic infomation of this project to stdout
func (b *Build) displayProjectMetaInfo() { func (b *Build) displayProjectMetaInfo() {
log.Infof("Project Infomation")
log.Infof("GOPATH: %v", config.GocConfig.GOPATH) log.Infof("GOPATH: %v", config.GocConfig.GOPATH)
log.Infof("GOBIN: %v", config.GocConfig.GOBIN) log.Infof("GOBIN: %v", config.GocConfig.GOBIN)
log.Infof("Project Directory: %v", config.GocConfig.CurModProjectDir) log.Infof("Project Directory: %v", config.GocConfig.CurModProjectDir)

View File

@ -3,17 +3,19 @@ package config
import "time" import "time"
type gocConfig struct { type gocConfig struct {
Debug bool Debug bool
ImportPath string // import path of the project CurWd string
CurPkgDir string Goflags []string
CurModProjectDir string ImportPath string // import path of the project
TmpModProjectDir string CurPkgDir string
TmpPkgDir string CurModProjectDir string
BinaryName string TmpModProjectDir string
Pkgs map[string]*Package TmpPkgDir string
GOPATH string ContainSpecialPattern bool // 参数中包含 ...
GOBIN string Pkgs map[string]*Package
IsMod bool // deprecated GOPATH string
GOBIN string
IsMod bool // deprecated
GlobalCoverVarImportPath string GlobalCoverVarImportPath string
GlobalCoverVarImportPathDir string GlobalCoverVarImportPathDir string

View File

@ -56,6 +56,7 @@ func init() {
time.Sleep(waitDelay) time.Sleep(waitDelay)
continue continue
} }
log.Printf("[goc][Info] connected to goc server")
rwc := &ReadWriteCloser{ws: ws} rwc := &ReadWriteCloser{ws: ws}
s := rpc.NewServer() s := rpc.NewServer()
@ -65,6 +66,7 @@ func init() {
// exit rpc server, close ws connection // exit rpc server, close ws connection
ws.Close() ws.Close()
time.Sleep(waitDelay) time.Sleep(waitDelay)
log.Printf("[goc][Error] connection to goc server broken", )
} }
} }
@ -84,7 +86,7 @@ func (ga *GocAgent) GetProfile(req *ProfileReq, res *ProfileRes) error {
} }
w := new(strings.Builder) w := new(strings.Builder)
fmt.Fprint(w, "south north") fmt.Fprint(w, "mode: {{.Mode}}\n")
counters, blocks := loadValues() counters, blocks := loadValues()
var active, total int64 var active, total int64

View File

@ -158,11 +158,13 @@ func injectGocAgent(where string, covers []*config.PackageCover) {
GlobalCoverVarImportPath string GlobalCoverVarImportPath string
Package string Package string
Host string Host string
Mode string
}{ }{
Covers: covers, Covers: covers,
GlobalCoverVarImportPath: config.GocConfig.GlobalCoverVarImportPath, GlobalCoverVarImportPath: config.GocConfig.GlobalCoverVarImportPath,
Package: injectPkgName, Package: injectPkgName,
Host: config.GocConfig.Host, Host: config.GocConfig.Host,
Mode: config.GocConfig.Mode,
} }
if err := coverMainTmpl.Execute(f, tmplData); err != nil { if err := coverMainTmpl.Execute(f, tmplData); err != nil {

View File

@ -2,7 +2,10 @@ package flag
import ( import (
"flag" "flag"
"os"
"path/filepath"
"github.com/qiniu/goc/v2/pkg/config"
"github.com/qiniu/goc/v2/pkg/log" "github.com/qiniu/goc/v2/pkg/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -15,7 +18,8 @@ The [goc flags] can be placed in anywhere in the command line.
However, other flags' order are same with the go official command. However, other flags' order are same with the go official command.
` `
// BuildCmdArgsParse parse both go flags and goc flags, it returns all non-flag arguments. // BuildCmdArgsParse parse both go flags and goc flags, it rewrite go flags if
// necessary, and returns all non-flag arguments.
// //
// 吞下 [packages] 之前所有的 flags. // 吞下 [packages] 之前所有的 flags.
func BuildCmdArgsParse(cmd *cobra.Command, args []string) []string { func BuildCmdArgsParse(cmd *cobra.Command, args []string) []string {
@ -52,6 +56,29 @@ func BuildCmdArgsParse(cmd *cobra.Command, args []string) []string {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} }
// 找出设置的 go flag
curWd, err := os.Getwd()
if err != nil {
log.Fatalf("fail to get current working directory: %v", err)
}
config.GocConfig.CurWd = curWd
flags := make([]string, 0)
goFlagSets.Visit(func(f *flag.Flag) {
// 将用户指定 -o 改成绝对目录
if f.Name == "o" {
outputDir := f.Value.String()
outputDir, err := filepath.Abs(outputDir)
if err != nil {
log.Fatalf("output flag is not valid: %v", err)
}
flags = append(flags, "-o", outputDir)
} else {
flags = append(flags, "-"+f.Name, f.Value.String())
}
})
config.GocConfig.Goflags = flags
return goFlagSets.Args() return goFlagSets.Args()
} }

View File

@ -38,7 +38,7 @@ func GetPackagesDir(patterns []string) {
// 获取当前 [packages] 所在的目录位置,供后续插桩使用。 // 获取当前 [packages] 所在的目录位置,供后续插桩使用。
config.GocConfig.CurPkgDir = filepath.Dir(absp) config.GocConfig.CurPkgDir = filepath.Dir(absp)
// 获取二进制名字 // 获取二进制名字
config.GocConfig.BinaryName = filepath.Base(absp) // config.GocConfig.BinaryName = filepath.Base(absp)
return return
} }
} }
@ -51,8 +51,11 @@ func GetPackagesDir(patterns []string) {
} }
config.GocConfig.CurPkgDir = coverWd config.GocConfig.CurPkgDir = coverWd
config.GocConfig.BinaryName = ""
return // 是否包含 ...
if strings.Contains(patterns[0], "...") {
config.GocConfig.ContainSpecialPattern = true
}
} }
// goFilesPackage 对一组 go 文件解析,判断是否合法 // goFilesPackage 对一组 go 文件解析,判断是否合法
@ -97,7 +100,7 @@ func goFilesPackage(gofiles []string) error {
return nil return nil
} }
// getDirFromImportPaths return the import path's real directory // getDirFromImportPaths return the import path's real abs directory
// //
// 该函数接收到的只有 dir 或 import pathfile 在上一步已被排除 // 该函数接收到的只有 dir 或 import pathfile 在上一步已被排除
// 只考虑 go modules 的情况 // 只考虑 go modules 的情况
@ -134,6 +137,7 @@ func getDirFromImportPaths(patterns []string) (string, error) {
case strings.Contains(pattern, "..."): case strings.Contains(pattern, "..."):
i := strings.Index(pattern, "...") i := strings.Index(pattern, "...")
dir, _ := filepath.Split(pattern[:i]) dir, _ := filepath.Split(pattern[:i])
dir, _ = filepath.Abs(dir)
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
return "", fmt.Errorf("error (%w) get directory from the import path: %v", err, pattern) return "", fmt.Errorf("error (%w) get directory from the import path: %v", err, pattern)
} }