Skip to content

Instantly share code, notes, and snippets.

@kaneshin
Created March 12, 2015 03:27
Show Gist options
  • Select an option

  • Save kaneshin/5c75788ba64bb2a198b4 to your computer and use it in GitHub Desktop.

Select an option

Save kaneshin/5c75788ba64bb2a198b4 to your computer and use it in GitHub Desktop.
diff --git a/harness/build.go b/harness/build.go
index b67b4fa..5cd992f 100644
--- a/harness/build.go
+++ b/harness/build.go
@@ -17,6 +17,81 @@ import (
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
+// Custom Build the app:
+// 1. No Generate the the main.go file.
+// 2. Run the appropriate "go build" command.
+// Requires that revel.Init has been called previously.
+// Returns the path to the built binary, and an error if there was a problem building it.
+func CustomBuild(custom bool) (app *App, compileError *revel.Error) {
+ if custom {
+ return Build()
+ }
+
+ // Read build config.
+ buildTags := revel.Config.StringDefault("build.tags", "")
+
+ // Build the user program (all code under app).
+ // It relies on the user having "go" installed.
+ goPath, err := exec.LookPath("go")
+ if err != nil {
+ revel.ERROR.Fatalf("Go executable not found in PATH.")
+ }
+
+ pkg, err := build.Default.Import(revel.ImportPath, "", build.FindOnly)
+ if err != nil {
+ revel.ERROR.Fatalln("Failure importing", revel.ImportPath)
+ }
+ binName := path.Join(pkg.BinDir, path.Base(revel.BasePath))
+ if runtime.GOOS == "windows" {
+ binName += ".exe"
+ }
+
+ gotten := make(map[string]struct{})
+ for {
+ appVersion := getAppVersion()
+ versionLinkerFlags := fmt.Sprintf("-X %s/app.APP_VERSION \"%s\"", revel.ImportPath, appVersion)
+
+ buildCmd := exec.Command(goPath, "build",
+ "-ldflags", versionLinkerFlags,
+ "-tags", buildTags,
+ "-o", binName, path.Join(revel.ImportPath, "app", "tmp"))
+ revel.TRACE.Println("Exec:", buildCmd.Args)
+ output, err := buildCmd.CombinedOutput()
+
+ // If the build succeeded, we're done.
+ if err == nil {
+ return NewApp(binName), nil
+ }
+ revel.ERROR.Println(string(output))
+
+ // See if it was an import error that we can go get.
+ matches := importErrorPattern.FindStringSubmatch(string(output))
+ if matches == nil {
+ return nil, newCompileError(output)
+ }
+
+ // Ensure we haven't already tried to go get it.
+ pkgName := matches[1]
+ if _, alreadyTried := gotten[pkgName]; alreadyTried {
+ return nil, newCompileError(output)
+ }
+ gotten[pkgName] = struct{}{}
+
+ // Execute "go get <pkg>"
+ getCmd := exec.Command(goPath, "get", pkgName)
+ revel.TRACE.Println("Exec:", getCmd.Args)
+ getOutput, err := getCmd.CombinedOutput()
+ if err != nil {
+ revel.ERROR.Println(string(getOutput))
+ return nil, newCompileError(output)
+ }
+
+ // Success getting the import, attempt to build again.
+ }
+ revel.ERROR.Fatalf("Not reachable")
+ return nil, nil
+}
+
// Build the app:
// 1. Generate the the main.go file.
// 2. Run the appropriate "go build" command.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment