2021-01-21 04:06:03 +00:00
|
|
|
package bbgo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"text/template"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
2022-01-23 06:57:45 +00:00
|
|
|
var wrapperTemplate = template.Must(template.New("main").Parse(`// Code generated by bbgo; DO NOT EDIT.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
2021-01-21 04:06:03 +00:00
|
|
|
import (
|
2021-01-21 04:27:21 +00:00
|
|
|
"github.com/c9s/bbgo/pkg/bbgo"
|
2021-01-21 04:06:03 +00:00
|
|
|
"github.com/c9s/bbgo/pkg/cmd"
|
|
|
|
|
|
|
|
{{- range .Imports }}
|
|
|
|
_ "{{ . }}"
|
|
|
|
{{- end }}
|
|
|
|
)
|
|
|
|
|
2021-01-21 04:27:21 +00:00
|
|
|
func init() {
|
|
|
|
bbgo.SetWrapperBinary()
|
|
|
|
}
|
|
|
|
|
2021-01-21 04:06:03 +00:00
|
|
|
func main() {
|
|
|
|
cmd.Execute()
|
|
|
|
}
|
|
|
|
|
|
|
|
`))
|
|
|
|
|
|
|
|
func generateRunFile(filepath string, config *Config, imports []string) error {
|
|
|
|
var buf = bytes.NewBuffer(nil)
|
|
|
|
if err := wrapperTemplate.Execute(buf, struct {
|
|
|
|
Config *Config
|
|
|
|
Imports []string
|
|
|
|
}{
|
|
|
|
Config: config,
|
|
|
|
Imports: imports,
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return ioutil.WriteFile(filepath, buf.Bytes(), 0644)
|
|
|
|
}
|
|
|
|
|
|
|
|
func compilePackage(packageDir string, userConfig *Config, imports []string) error {
|
|
|
|
if _, err := os.Stat(packageDir); os.IsNotExist(err) {
|
|
|
|
if err := os.MkdirAll(packageDir, 0777); err != nil {
|
|
|
|
return errors.Wrapf(err, "can not create wrapper package directory: %s", packageDir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mainFile := filepath.Join(packageDir, "main.go")
|
|
|
|
if err := generateRunFile(mainFile, userConfig, imports); err != nil {
|
|
|
|
return errors.Wrap(err, "compile error")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Build(ctx context.Context, userConfig *Config, targetConfig BuildTargetConfig) (string, error) {
|
|
|
|
// combine global imports and target imports
|
|
|
|
imports := append(userConfig.Build.Imports, targetConfig.Imports...)
|
|
|
|
|
|
|
|
buildDir := userConfig.Build.BuildDir
|
|
|
|
if len(buildDir) == 0 {
|
|
|
|
buildDir = "build"
|
|
|
|
}
|
|
|
|
|
|
|
|
packageDir, err := ioutil.TempDir(buildDir, "bbgow-") // with prefix bbgow
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := compilePackage(packageDir, userConfig, imports); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
var buildEnvs []string
|
|
|
|
|
|
|
|
if targetConfig.OS != runtime.GOOS {
|
|
|
|
buildEnvs = append(buildEnvs, "GOOS="+targetConfig.OS)
|
|
|
|
}
|
|
|
|
|
|
|
|
if targetConfig.Arch != runtime.GOARCH {
|
|
|
|
buildEnvs = append(buildEnvs, "GOARCH="+targetConfig.Arch)
|
|
|
|
}
|
|
|
|
|
|
|
|
buildTarget := filepath.Join(cwd, packageDir)
|
|
|
|
|
|
|
|
binary := targetConfig.Name
|
|
|
|
if len(binary) == 0 {
|
|
|
|
binary = fmt.Sprintf("bbgow-%s-%s", targetConfig.OS, targetConfig.Arch)
|
|
|
|
}
|
|
|
|
|
|
|
|
output := filepath.Join(buildDir, binary)
|
|
|
|
|
2022-01-23 06:44:17 +00:00
|
|
|
args := []string{"build", "-tags", "wrapper", "-o", output, buildTarget}
|
|
|
|
logrus.Debugf("building binary %s from %s: go %v", output, buildTarget, args)
|
|
|
|
buildCmd := exec.CommandContext(ctx, "go", args...)
|
2021-01-21 04:06:03 +00:00
|
|
|
buildCmd.Env = append(os.Environ(), buildEnvs...)
|
|
|
|
buildCmd.Stdout = os.Stdout
|
|
|
|
buildCmd.Stderr = os.Stderr
|
|
|
|
if err := buildCmd.Run(); err != nil {
|
2021-01-21 04:27:21 +00:00
|
|
|
return output, err
|
2021-01-21 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
2022-01-23 06:44:17 +00:00
|
|
|
return output, os.RemoveAll(packageDir)
|
2021-01-21 04:06:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func BuildTarget(ctx context.Context, userConfig *Config, target BuildTargetConfig) (string, error) {
|
|
|
|
buildDir := userConfig.Build.BuildDir
|
|
|
|
if len(buildDir) == 0 {
|
|
|
|
buildDir = "build"
|
|
|
|
}
|
|
|
|
|
|
|
|
buildDir = filepath.Join(userConfig.Build.BuildDir, target.Name)
|
|
|
|
return Build(ctx, userConfig, target)
|
|
|
|
}
|