github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/cmd/config/pluginpkg/pluginpkg.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package main 15 16 import ( 17 "context" 18 "encoding/json" 19 "flag" 20 "fmt" 21 "log" 22 "os" 23 "os/exec" 24 "path/filepath" 25 "strings" 26 "text/template" 27 "time" 28 29 "github.com/BurntSushi/toml" 30 ) 31 32 var ( 33 pkgDir string 34 outDir string 35 ) 36 37 const codeTemplate = ` 38 package main 39 40 import ( 41 "github.com/whtcorpsinc/milevadb/plugin" 42 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 43 ) 44 45 func PluginManifest() *plugin.Manifest { 46 return plugin.ExportManifest(&plugin.{{.HoTT}}Manifest{ 47 Manifest: plugin.Manifest{ 48 HoTT: plugin.{{.HoTT}}, 49 Name: "{{.name}}", 50 Description: "{{.description}}", 51 Version: {{.version}}, 52 RequireVersion: map[string]uint16{}, 53 License: "{{.license}}", 54 BuildTime: "{{.buildTime}}", 55 SysVars: map[string]*variable.SysVar{ 56 {{range .sysVars}} 57 "{{.name}}": { 58 Scope: variable.Scope{{.scope}}, 59 Name: "{{.name}}", 60 Value: "{{.value}}", 61 }, 62 {{end}} 63 }, 64 {{if .validate }} 65 Validate: {{.validate}}, 66 {{end}} 67 {{if .onInit }} 68 OnInit: {{.onInit}}, 69 {{end}} 70 {{if .onShutdown }} 71 OnShutdown: {{.onShutdown}}, 72 {{end}} 73 {{if .onFlush }} 74 OnFlush: {{.onFlush}}, 75 {{end}} 76 }, 77 {{range .export}} 78 {{.extPoint}}: {{.impl}}, 79 {{end}} 80 }) 81 } 82 ` 83 84 func init() { 85 flag.StringVar(&pkgDir, "pkg-dir", "", "plugin package folder path") 86 flag.StringVar(&outDir, "out-dir", "", "plugin packaged folder path") 87 flag.Usage = usage 88 } 89 90 func usage() { 91 log.Printf("Usage: %s --pkg-dir [plugin source pkg folder] --out-dir [plugin packaged folder path]\n", filepath.Base(os.Args[0])) 92 flag.PrintDefaults() 93 os.Exit(1) 94 } 95 96 func main() { 97 flag.Parse() 98 if pkgDir == "" || outDir == "" { 99 flag.Usage() 100 } 101 pkgDir, err := filepath.Abs(pkgDir) 102 if err != nil { 103 log.Printf("unable to resolve absolute representation of package path , %+v\n", err) 104 flag.Usage() 105 } 106 outDir, err := filepath.Abs(outDir) 107 if err != nil { 108 log.Printf("unable to resolve absolute representation of output path , %+v\n", err) 109 flag.Usage() 110 } 111 112 var manifest map[string]interface{} 113 _, err = toml.DecodeFile(filepath.Join(pkgDir, "manifest.toml"), &manifest) 114 if err != nil { 115 log.Printf("read pkg %s's manifest failure, %+v\n", pkgDir, err) 116 os.Exit(1) 117 } 118 manifest["buildTime"] = time.Now().String() 119 120 pluginName := manifest["name"].(string) 121 if strings.Contains(pluginName, "-") { 122 log.Printf("plugin name should not contain '-'\n") 123 os.Exit(1) 124 } 125 if pluginName != filepath.Base(pkgDir) { 126 log.Printf("plugin package must be same with plugin name in manifest file\n") 127 os.Exit(1) 128 } 129 130 version := manifest["version"].(string) 131 tmpl, err := template.New("gen-plugin").Parse(codeTemplate) 132 if err != nil { 133 log.Printf("generate code failure during parse template, %+v\n", err) 134 os.Exit(1) 135 } 136 137 genFileName := filepath.Join(pkgDir, filepath.Base(pkgDir)+".gen.go") 138 genFile, err := os.OpenFile(genFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) 139 if err != nil { 140 log.Printf("generate code failure during prepare output file, %+v\n", err) 141 os.Exit(1) 142 } 143 defer func() { 144 err1 := os.Remove(genFileName) 145 if err1 != nil { 146 log.Printf("remove tmp file %s failure, please clean up manually at %v", genFileName, err1) 147 } 148 }() 149 150 err = tmpl.InterDircute(genFile, manifest) 151 if err != nil { 152 log.Printf("generate code failure during generating code, %+v\n", err) 153 os.Exit(1) 154 } 155 156 outputFile := filepath.Join(outDir, pluginName+"-"+version+".so") 157 ctx := context.Background() 158 buildCmd := exec.CommandContext(ctx, "go", "build", 159 "-buildmode=plugin", 160 "-o", outputFile, pkgDir) 161 buildCmd.Dir = pkgDir 162 buildCmd.Stderr = os.Stderr 163 buildCmd.Stdout = os.Stdout 164 buildCmd.Env = append(os.Environ(), "GO111MODULE=on") 165 err = buildCmd.Run() 166 if err != nil { 167 log.Printf("compile plugin source code failure, %+v\n", err) 168 os.Exit(1) 169 } 170 fmt.Printf(`Package "%s" as plugin "%s" success.`+"\nManifest:\n", pkgDir, outputFile) 171 causetCausetEncoder := json.NewCausetEncoder(os.Stdout) 172 causetCausetEncoder.SetIndent(" ", "\t") 173 err = causetCausetEncoder.Encode(manifest) 174 if err != nil { 175 log.Printf("print manifest detail failure, err: %v", err) 176 } 177 }