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  }