Skip to content

Commit 1d00f75

Browse files
lysujackysp
authored andcommitted
cmd: add plugin package tool (#9007)
1 parent 4b71d19 commit 1d00f75

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

cmd/pluginpkg/pluginpkg.go

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright 2018 PingCAP, 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"
25+
"path/filepath"
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/pingcap/tidb/plugin"
42+
"github.com/pingcap/tidb/sessionctx/variable"
43+
)
44+
45+
func PluginManifest() *plugin.Manifest {
46+
return plugin.ExportManifest(&plugin.{{.kind}}Manifest{
47+
Manifest: plugin.Manifest{
48+
Kind: plugin.{{.kind}},
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+
Validate: {{.validate}},
65+
OnInit: {{.onInit}},
66+
OnShutdown: {{.onShutdown}},
67+
},
68+
{{range .export}}
69+
{{.extPoint}}: {{.impl}},
70+
{{end}}
71+
})
72+
}
73+
`
74+
75+
func init() {
76+
flag.StringVar(&pkgDir, "pkg-dir", "", "plugin package folder path")
77+
flag.StringVar(&outDir, "out-dir", "", "plugin packaged folder path")
78+
flag.Usage = usage
79+
}
80+
81+
func usage() {
82+
log.Printf("Usage: %s --pkg-dir [plugin source pkg folder] --outDir-dir [outDir-dir]\n", path.Base(os.Args[0]))
83+
flag.PrintDefaults()
84+
os.Exit(1)
85+
}
86+
87+
func main() {
88+
flag.Parse()
89+
if pkgDir == "" || outDir == "" {
90+
flag.Usage()
91+
}
92+
var manifest map[string]interface{}
93+
_, err := toml.DecodeFile(filepath.Join(pkgDir, "manifest.toml"), &manifest)
94+
if err != nil {
95+
log.Printf("read pkg %s's manifest failure, %+v\n", pkgDir, err)
96+
os.Exit(1)
97+
}
98+
manifest["buildTime"] = time.Now().String()
99+
100+
pluginName := manifest["name"].(string)
101+
if pluginName != filepath.Base(pkgDir) {
102+
log.Printf("plugin package must be same with plugin name in manifest file\n")
103+
os.Exit(1)
104+
}
105+
106+
version := manifest["version"].(string)
107+
tmpl, err := template.New("gen-plugin").Parse(codeTemplate)
108+
if err != nil {
109+
log.Printf("generate code failure during parse template, %+v\n", err)
110+
os.Exit(1)
111+
}
112+
113+
genFileName := filepath.Join(pkgDir, filepath.Base(pkgDir)+".gen.go")
114+
genFile, err := os.OpenFile(genFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
115+
if err != nil {
116+
log.Printf("generate code failure during prepare output file, %+v\n", err)
117+
os.Exit(1)
118+
}
119+
defer func() {
120+
err1 := os.Remove(genFileName)
121+
if err1 != nil {
122+
log.Printf("remove tmp file %s failure, please clean up manually at %v", genFileName, err1)
123+
}
124+
}()
125+
126+
err = tmpl.Execute(genFile, manifest)
127+
if err != nil {
128+
log.Printf("generate code failure during generating code, %+v\n", err)
129+
os.Exit(1)
130+
}
131+
132+
outputFile := filepath.Join(outDir, pluginName+"-"+version+".so")
133+
pluginPath := `-pluginpath=` + pluginName + "-" + version
134+
ctx := context.Background()
135+
buildCmd := exec.CommandContext(ctx, "go", "build",
136+
"-ldflags", pluginPath,
137+
"-buildmode=plugin",
138+
"-o", outputFile, pkgDir)
139+
buildCmd.Stderr = os.Stderr
140+
buildCmd.Stdout = os.Stdout
141+
buildCmd.Env = append(os.Environ(), "GO111MODULE=on")
142+
err = buildCmd.Run()
143+
if err != nil {
144+
log.Printf("compile plugin source code failure, %+v\n", err)
145+
os.Exit(1)
146+
}
147+
fmt.Printf(`Package "%s" as plugin "%s" success.`+"\nManifest:\n", pkgDir, outputFile)
148+
encoder := json.NewEncoder(os.Stdout)
149+
encoder.SetIndent(" ", "\t")
150+
err = encoder.Encode(manifest)
151+
if err != nil {
152+
log.Printf("print manifest detail failure, err: %v", err)
153+
}
154+
}

0 commit comments

Comments
 (0)