mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			316 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package build
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"flag"
 | |
| 	"fmt"
 | |
| 	"go/build"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	GoOSWindows = "windows"
 | |
| 	GoOSLinux   = "linux"
 | |
| 
 | |
| 	BackendBinary = "grafana"
 | |
| 	ServerBinary  = "grafana-server"
 | |
| 	CLIBinary     = "grafana-cli"
 | |
| )
 | |
| 
 | |
| var binaries = []string{BackendBinary, ServerBinary, CLIBinary}
 | |
| 
 | |
| func logError(message string, err error) int {
 | |
| 	log.Println(message, err)
 | |
| 
 | |
| 	return 1
 | |
| }
 | |
| 
 | |
| // RunCmd runs the build command and returns the exit code
 | |
| func RunCmd() int {
 | |
| 	opts := BuildOptsFromFlags()
 | |
| 
 | |
| 	wd, err := os.Getwd()
 | |
| 	if err != nil {
 | |
| 		return logError("Error getting working directory", err)
 | |
| 	}
 | |
| 
 | |
| 	packageJSON, err := OpenPackageJSON(wd)
 | |
| 	if err != nil {
 | |
| 		return logError("Error opening package json", err)
 | |
| 	}
 | |
| 
 | |
| 	opts.version = packageJSON.Version
 | |
| 
 | |
| 	version, iteration := LinuxPackageVersion(packageJSON.Version, opts.buildID)
 | |
| 
 | |
| 	if opts.printGenVersion {
 | |
| 		fmt.Print(genPackageVersion(version, iteration))
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	log.Printf("Version: %s, Linux Version: %s, Package Iteration: %s\n", version, version, iteration)
 | |
| 
 | |
| 	if flag.NArg() == 0 {
 | |
| 		log.Println("Usage: go run build.go build")
 | |
| 		return 1
 | |
| 	}
 | |
| 
 | |
| 	for _, cmd := range flag.Args() {
 | |
| 		switch cmd {
 | |
| 		case "setup":
 | |
| 			setup(opts.goos)
 | |
| 
 | |
| 		case "build-backend":
 | |
| 			if !opts.isDev {
 | |
| 				clean(opts)
 | |
| 			}
 | |
| 
 | |
| 			if err := doBuild("grafana", "./pkg/cmd/grafana", opts); err != nil {
 | |
| 				log.Println(err)
 | |
| 				return 1
 | |
| 			}
 | |
| 
 | |
| 		case "build-srv", "build-server":
 | |
| 			if !opts.isDev {
 | |
| 				clean(opts)
 | |
| 			}
 | |
| 
 | |
| 			if err := doBuild("grafana-server", "./pkg/cmd/grafana-server", opts); err != nil {
 | |
| 				log.Println(err)
 | |
| 				return 1
 | |
| 			}
 | |
| 
 | |
| 		case "build-cli":
 | |
| 			clean(opts)
 | |
| 			if err := doBuild("grafana-cli", "./pkg/cmd/grafana-cli", opts); err != nil {
 | |
| 				log.Println(err)
 | |
| 				return 1
 | |
| 			}
 | |
| 
 | |
| 		case "build":
 | |
| 			//clean()
 | |
| 			for _, binary := range binaries {
 | |
| 				log.Println("building binaries", cmd)
 | |
| 				// Can't use filepath.Join here because filepath.Join calls filepath.Clean, which removes the `./` from this path, which upsets `go build`
 | |
| 				if err := doBuild(binary, fmt.Sprintf("./pkg/cmd/%s", binary), opts); err != nil {
 | |
| 					log.Println(err)
 | |
| 					return 1
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 		case "build-frontend":
 | |
| 			yarn("build")
 | |
| 
 | |
| 		case "sha-dist":
 | |
| 			if err := shaDir("dist"); err != nil {
 | |
| 				return logError("error packaging dist directory", err)
 | |
| 			}
 | |
| 
 | |
| 		case "clean":
 | |
| 			clean(opts)
 | |
| 
 | |
| 		default:
 | |
| 			log.Println("Unknown command", cmd)
 | |
| 			return 1
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0
 | |
| }
 | |
| 
 | |
| func yarn(params ...string) {
 | |
| 	runPrint(`yarn run`, params...)
 | |
| }
 | |
| 
 | |
| func genPackageVersion(version string, iteration string) string {
 | |
| 	if iteration != "" {
 | |
| 		return fmt.Sprintf("%v-%v", version, iteration)
 | |
| 	} else {
 | |
| 		return version
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func setup(goos string) {
 | |
| 	args := []string{"install", "-v"}
 | |
| 	if goos == GoOSWindows {
 | |
| 		args = append(args, "-buildmode=exe")
 | |
| 	}
 | |
| 	args = append(args, "./pkg/cmd/grafana-server")
 | |
| 	runPrint("go", args...)
 | |
| }
 | |
| 
 | |
| func doBuild(binaryName, pkg string, opts BuildOpts) error {
 | |
| 	log.Println("building", binaryName, pkg)
 | |
| 
 | |
| 	if err := setBuildEnv(opts); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	libcPart := ""
 | |
| 	if opts.libc != "" {
 | |
| 		libcPart = fmt.Sprintf("-%s", opts.libc)
 | |
| 	}
 | |
| 	binary := fmt.Sprintf("./bin/%s", binaryName)
 | |
| 
 | |
| 	//don't include os/arch/libc in output path in dev environment
 | |
| 	if !opts.isDev {
 | |
| 		binary = fmt.Sprintf("./bin/%s-%s%s/%s", opts.goos, opts.goarch, libcPart, binaryName)
 | |
| 	}
 | |
| 
 | |
| 	if opts.goos == GoOSWindows {
 | |
| 		binary += ".exe"
 | |
| 	}
 | |
| 
 | |
| 	if !opts.isDev {
 | |
| 		rmr(binary, binary+".md5")
 | |
| 	}
 | |
| 
 | |
| 	lf, err := ldflags(opts)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	args := []string{"build", "-ldflags", lf}
 | |
| 
 | |
| 	if opts.goos == GoOSWindows {
 | |
| 		// Work around a linking error on Windows: "export ordinal too large"
 | |
| 		args = append(args, "-buildmode=exe")
 | |
| 	}
 | |
| 
 | |
| 	if len(opts.buildTags) > 0 {
 | |
| 		args = append(args, "-tags", strings.Join(opts.buildTags, ","))
 | |
| 	}
 | |
| 
 | |
| 	if opts.race {
 | |
| 		args = append(args, "-race")
 | |
| 	}
 | |
| 
 | |
| 	args = append(args, "-o", binary)
 | |
| 	args = append(args, pkg)
 | |
| 
 | |
| 	runPrint("go", args...)
 | |
| 
 | |
| 	if opts.isDev {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	runPrint("go", "version")
 | |
| 	libcPart = ""
 | |
| 	if opts.libc != "" {
 | |
| 		libcPart = fmt.Sprintf("/%s", opts.libc)
 | |
| 	}
 | |
| 	fmt.Printf("Targeting %s/%s%s\n", opts.goos, opts.goarch, libcPart)
 | |
| 
 | |
| 	// Create an md5 checksum of the binary, to be included in the archive for
 | |
| 	// automatic upgrades.
 | |
| 	return md5File(binary)
 | |
| }
 | |
| 
 | |
| func ldflags(opts BuildOpts) (string, error) {
 | |
| 	buildStamp, err := buildStamp()
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	commitSha := getGitSha()
 | |
| 	if v := os.Getenv("COMMIT_SHA"); v != "" {
 | |
| 		commitSha = v
 | |
| 	}
 | |
| 
 | |
| 	var enterpriseCommitSha string
 | |
| 	if opts.enterprise {
 | |
| 		enterpriseCommitSha = getGitEnterpriseSha()
 | |
| 		if v := os.Getenv("ENTERPRISE_COMMIT_SHA"); v != "" {
 | |
| 			enterpriseCommitSha = v
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	buildBranch := getGitBranch()
 | |
| 	if v := os.Getenv("BUILD_BRANCH"); v != "" {
 | |
| 		buildBranch = v
 | |
| 	}
 | |
| 	var b bytes.Buffer
 | |
| 	b.WriteString("-w")
 | |
| 	b.WriteString(fmt.Sprintf(" -X main.version=%s", opts.version))
 | |
| 	b.WriteString(fmt.Sprintf(" -X main.commit=%s", commitSha))
 | |
| 	if enterpriseCommitSha != "" {
 | |
| 		b.WriteString(fmt.Sprintf(" -X main.enterpriseCommit=%s", enterpriseCommitSha))
 | |
| 	}
 | |
| 	b.WriteString(fmt.Sprintf(" -X main.buildstamp=%d", buildStamp))
 | |
| 	b.WriteString(fmt.Sprintf(" -X main.buildBranch=%s", buildBranch))
 | |
| 	if v := os.Getenv("LDFLAGS"); v != "" {
 | |
| 		b.WriteString(fmt.Sprintf(" -extldflags \"%s\"", v))
 | |
| 	}
 | |
| 
 | |
| 	return b.String(), nil
 | |
| }
 | |
| 
 | |
| func setBuildEnv(opts BuildOpts) error {
 | |
| 	if err := os.Setenv("GOOS", opts.goos); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if opts.goos == GoOSWindows {
 | |
| 		// require windows >=7
 | |
| 		if err := os.Setenv("CGO_CFLAGS", "-D_WIN32_WINNT=0x0601"); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if opts.goarch != "amd64" || opts.goos != GoOSLinux {
 | |
| 		// needed for all other archs
 | |
| 		opts.cgo = true
 | |
| 	}
 | |
| 
 | |
| 	if strings.HasPrefix(opts.goarch, "armv") {
 | |
| 		if err := os.Setenv("GOARCH", "arm"); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		if err := os.Setenv("GOARM", opts.goarch[4:]); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	} else {
 | |
| 		if err := os.Setenv("GOARCH", opts.goarch); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if opts.cgo {
 | |
| 		if err := os.Setenv("CGO_ENABLED", "1"); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if opts.gocc == "" {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return os.Setenv("CC", opts.gocc)
 | |
| }
 | |
| 
 | |
| func buildStamp() (int64, error) {
 | |
| 	// use SOURCE_DATE_EPOCH if set.
 | |
| 	if v, ok := os.LookupEnv("SOURCE_DATE_EPOCH"); ok {
 | |
| 		return strconv.ParseInt(v, 10, 64)
 | |
| 	}
 | |
| 
 | |
| 	bs, err := runError("git", "show", "-s", "--format=%ct")
 | |
| 	if err != nil {
 | |
| 		return time.Now().Unix(), nil
 | |
| 	}
 | |
| 
 | |
| 	return strconv.ParseInt(string(bs), 10, 64)
 | |
| }
 | |
| 
 | |
| func clean(opts BuildOpts) {
 | |
| 	rmr("dist")
 | |
| 	rmr("tmp")
 | |
| 	rmr(filepath.Join(build.Default.GOPATH, fmt.Sprintf("pkg/%s_%s/github.com/grafana", opts.goos, opts.goarch)))
 | |
| }
 |