gitee.com/mirrors_opencollective/goreleaser@v0.45.0/pipeline/build/build.go (about) 1 package build 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 "strings" 8 9 "github.com/apex/log" 10 "github.com/pkg/errors" 11 "golang.org/x/sync/errgroup" 12 13 "github.com/goreleaser/goreleaser/config" 14 "github.com/goreleaser/goreleaser/context" 15 "github.com/goreleaser/goreleaser/internal/artifact" 16 "github.com/goreleaser/goreleaser/internal/buildtarget" 17 "github.com/goreleaser/goreleaser/internal/ext" 18 ) 19 20 // Pipe for build 21 type Pipe struct{} 22 23 func (Pipe) String() string { 24 return "building binaries" 25 } 26 27 // Run the pipe 28 func (Pipe) Run(ctx *context.Context) error { 29 for _, build := range ctx.Config.Builds { 30 log.WithField("build", build).Debug("building") 31 if err := checkMain(ctx, build); err != nil { 32 return err 33 } 34 if err := runPipeOnBuild(ctx, build); err != nil { 35 return err 36 } 37 } 38 return nil 39 } 40 41 // Default sets the pipe defaults 42 func (Pipe) Default(ctx *context.Context) error { 43 for i, build := range ctx.Config.Builds { 44 ctx.Config.Builds[i] = buildWithDefaults(ctx, build) 45 } 46 if len(ctx.Config.Builds) == 0 { 47 ctx.Config.Builds = []config.Build{ 48 buildWithDefaults(ctx, ctx.Config.SingleBuild), 49 } 50 } 51 return nil 52 } 53 54 func buildWithDefaults(ctx *context.Context, build config.Build) config.Build { 55 if build.Binary == "" { 56 build.Binary = ctx.Config.Release.GitHub.Name 57 } 58 if build.Main == "" { 59 build.Main = "." 60 } 61 if len(build.Goos) == 0 { 62 build.Goos = []string{"linux", "darwin"} 63 } 64 if len(build.Goarch) == 0 { 65 build.Goarch = []string{"amd64", "386"} 66 } 67 if len(build.Goarm) == 0 { 68 build.Goarm = []string{"6"} 69 } 70 if build.Ldflags == "" { 71 build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}" 72 } 73 return build 74 } 75 76 func runPipeOnBuild(ctx *context.Context, build config.Build) error { 77 if err := runHook(ctx, build.Env, build.Hooks.Pre); err != nil { 78 return errors.Wrap(err, "pre hook failed") 79 } 80 sem := make(chan bool, ctx.Parallelism) 81 var g errgroup.Group 82 for _, target := range buildtarget.All(build) { 83 sem <- true 84 target := target 85 build := build 86 g.Go(func() error { 87 defer func() { 88 <-sem 89 }() 90 return doBuild(ctx, build, target) 91 }) 92 } 93 if err := g.Wait(); err != nil { 94 return err 95 } 96 return errors.Wrap(runHook(ctx, build.Env, build.Hooks.Post), "post hook failed") 97 } 98 99 func runHook(ctx *context.Context, env []string, hook string) error { 100 if hook == "" { 101 return nil 102 } 103 log.WithField("hook", hook).Info("running hook") 104 cmd := strings.Fields(hook) 105 return run(ctx, buildtarget.Runtime, cmd, env) 106 } 107 108 func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target) error { 109 var ext = ext.For(target) 110 var binaryName = build.Binary + ext 111 var binary = filepath.Join(ctx.Config.Dist, target.String(), binaryName) 112 log.WithField("binary", binary).Info("building") 113 cmd := []string{"go", "build"} 114 if build.Flags != "" { 115 cmd = append(cmd, strings.Fields(build.Flags)...) 116 } 117 flags, err := ldflags(ctx, build) 118 if err != nil { 119 return err 120 } 121 cmd = append(cmd, "-ldflags="+flags, "-o", binary, build.Main) 122 if err := run(ctx, target, cmd, build.Env); err != nil { 123 return errors.Wrapf(err, "failed to build for %s", target) 124 } 125 ctx.Artifacts.Add(artifact.Artifact{ 126 Type: artifact.Binary, 127 Path: binary, 128 Name: binaryName, 129 Goos: target.OS, 130 Goarch: target.Arch, 131 Goarm: target.Arm, 132 Extra: map[string]string{ 133 "Binary": build.Binary, 134 "Ext": ext, 135 }, 136 }) 137 return nil 138 } 139 140 func run(ctx *context.Context, target buildtarget.Target, command, env []string) error { 141 /* #nosec */ 142 var cmd = exec.CommandContext(ctx, command[0], command[1:]...) 143 env = append(env, target.Env()...) 144 var log = log.WithField("target", target.PrettyString()). 145 WithField("env", env). 146 WithField("cmd", command) 147 cmd.Env = append(cmd.Env, os.Environ()...) 148 cmd.Env = append(cmd.Env, env...) 149 log.Debug("running") 150 if out, err := cmd.CombinedOutput(); err != nil { 151 log.WithError(err).Debug("failed") 152 return errors.New(string(out)) 153 } 154 return nil 155 }