// Build performs a build job. This function is blocking. If the build // job succeeds, it will automatically delete itself when it expires. // If it fails, resources are not automatically cleaned up. func (b *Build) Build() error { // Prepare the build builder, err := caddybuild.PrepareBuild(b.Features) defer builder.Teardown() // always perform cleanup if err != nil { return err } // Perform the build if b.GoArch == "arm" { var armInt int if b.GoARM != "" { armInt, err = strconv.Atoi(b.GoARM) if err != nil { return err } } err = builder.BuildStaticARM(b.GoOS, armInt, b.OutputFile) } else { err = builder.BuildStatic(b.GoOS, b.GoArch, b.OutputFile) } if err != nil { return err } // File list to include with build, then compress the build fileList := []string{ filepath.Join(CaddyPath, "/dist/README.txt"), filepath.Join(CaddyPath, "/dist/LICENSES.txt"), filepath.Join(CaddyPath, "/dist/CHANGES.txt"), b.OutputFile, } if b.DownloadFileCompression == CompressZip { err = Zip(b.DownloadFile, fileList) } else if b.DownloadFileCompression == CompressTarGz { err = TarGz(b.DownloadFile, fileList) } else { return fmt.Errorf("unknown compress type %v", b.DownloadFileCompression) } if err != nil { return err } // Delete uncompressed binary err = os.Remove(b.OutputFile) if err != nil { return err } // Finalize the build and have it clean itself // up after its expiration b.finish() return nil }
func prepareBuild(args cliArgs, config caddybuild.Config) (App, error) { caddybuild.SetConfig(config) var builder custombuild.Builder var f *os.File var caddyProcess *os.Process // remove temp files. addCleanUpFunc(func() { if caddyProcess != nil { caddyProcess.Kill() } builder.Teardown() if f != nil { os.Remove(f.Name()) } }) builder, err := caddybuild.PrepareBuild(config.Plugins, false) exitIfErr(err) // if output is set, generate binary only. if args.output != "" { err := saveCaddy(builder, args.output, args.goArgs) exitIfErr(err) os.Exit(0) } // create temporary file for binary f, err = ioutil.TempFile("", "caddydev") exitIfErr(err) f.Close() // fix for windows exe fName := f.Name() if runtime.GOOS == "windows" { fName += ".exe" } return &caddyApp{ file: fName, goArgs: args.goArgs, caddyArgs: args.caddyArgs, builder: builder, }, nil }
func main() { // parse cli arguments. args, err := parseArgs() exitIfErr(err) // read config file. config, err := readConfig(args) exitIfErr(err) fetched := false // if caddy source does not exits, pull source. if !isLocalPkg(caddybuild.CaddyPackage) { fmt.Print("Caddy source not found. Fetching...") err := fetchCaddy() exitIfErr(err) fmt.Println(" done.") fetched = true } // if update flag is set, pull source. if args.update && !fetched { fmt.Print("Updating caddy source...") err := fetchCaddy() exitIfErr(err) fmt.Println(" done.") } caddybuild.SetConfig(config) var builder custombuild.Builder var f *os.File var caddyProcess *os.Process // remove temp files. addCleanUpFunc(func() { if caddyProcess != nil { caddyProcess.Kill() } builder.Teardown() if f != nil { os.Remove(f.Name()) } }) builder, err = caddybuild.PrepareBuild(features.Middlewares{config.Middleware}) exitIfErr(err) // if output is set, generate binary only. if args.output != "" { err := saveCaddy(builder, args.output, args.goArgs) exitIfErr(err) return } // create temporary file for binary f, err = ioutil.TempFile("", "caddydev") exitIfErr(err) f.Close() // perform custom build err = builder.Build("", "", f.Name(), args.goArgs...) exitIfErr(err) fmt.Println("Starting caddy...") // trap os interrupts to ensure cleaning up temp files. done := trapInterrupts() // start custom caddy. go func() { cmd, err := startCaddy(f.Name(), args.caddyArgs) exitIfErr(err) caddyProcess = cmd.Process err = cmd.Wait() cleanUp() exitIfErr(err) done <- struct{}{} }() // wait for exit signal <-done }
// Build performs a build job. This function is blocking. If the build // job succeeds, it will automatically delete itself when it expires. // If it fails, resources are not automatically cleaned up. func (b *Build) Build() error { // Prepare the build builder, err := caddybuild.PrepareBuild(b.Features, false) // TODO: PullLatest (go get -u) DISABLED for stability; updates are manual for now defer builder.Teardown() // always perform cleanup if err != nil { return err } builder.CommandName = "./build.bash" origRepoPath := filepath.Join(os.Getenv("GOPATH"), "src/github.com/mholt/caddy") // Perform the build if b.GoArch == "arm" { var armInt int if b.GoARM != "" { armInt, err = strconv.Atoi(b.GoARM) if err != nil { return err } } else { armInt = defaultARM } err = builder.BuildStaticARM(b.GoOS, armInt, b.OutputFile, origRepoPath) } else if b.GoOS == "darwin" { // At time of writing, building with CGO_ENABLED=0 for darwin can break stuff: https://www.reddit.com/r/golang/comments/46bd5h/ama_we_are_the_go_contributors_ask_us_anything/d03rmc9 err = builder.Build(b.GoOS, b.GoArch, b.OutputFile, origRepoPath) } else { err = builder.BuildStatic(b.GoOS, b.GoArch, b.OutputFile, origRepoPath) } if err != nil { return err } // File list to include with build, then compress the build fileList := []string{ filepath.Join(CaddyPath, "/dist/README.txt"), filepath.Join(CaddyPath, "/dist/LICENSES.txt"), filepath.Join(CaddyPath, "/dist/CHANGES.txt"), filepath.Join(CaddyPath, "/dist/init"), b.OutputFile, } if b.DownloadFileCompression == CompressZip { err = archiver.Zip(b.DownloadFile, fileList) } else if b.DownloadFileCompression == CompressTarGz { err = archiver.TarGz(b.DownloadFile, fileList) } else { return fmt.Errorf("unknown compress type %v", b.DownloadFileCompression) } if err != nil { return fmt.Errorf("error compressing: %v", err) } // Delete uncompressed binary err = os.Remove(b.OutputFile) if err != nil { return err } // Finalize the build and have it clean itself // up after its expiration b.finish() return nil }