mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			306 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			6.2 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
 | 
						|
	}
 | 
						|
 | 
						|
	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))
 | 
						|
	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)))
 | 
						|
}
 |