forked from tonistiigi/llb-gobuild
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gobuild.go
124 lines (105 loc) · 3.26 KB
/
gobuild.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package gobuild
import (
"bytes"
"encoding/json"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client/llb/llbbuild"
)
type Opt struct {
DevMode bool
}
func New(opt *Opt) *GoBuilder {
devMode := false
if opt != nil && opt.DevMode {
devMode = true
}
return &GoBuilder{DevMode: devMode}
}
type BuildOpt struct {
Source llb.State
MountPath string
Pkg string
CgoEnabled bool
BuildTags []string
GOARCH string
GOOS string
}
type BuildOptJSON struct {
Source string
SourceIndex int
SourceDef []byte
MountPath string
Pkg string
CgoEnabled bool
BuildTags []string
GOARCH string
GOOS string
GOPATH string
}
type GoBuilder struct {
DevMode bool
}
func (gb *GoBuilder) BuildExe(opt BuildOpt) (*llb.State, error) {
inp, err := opt.Source.Output().ToInput()
if err != nil {
return nil, err
}
def, err := opt.Source.Marshal()
if err != nil {
return nil, err
}
buf := &bytes.Buffer{}
if err := llb.WriteTo(def, buf); err != nil {
return nil, err
}
dt, err := json.Marshal(BuildOptJSON{
Source: inp.Digest.String(),
SourceIndex: int(inp.Index),
SourceDef: buf.Bytes(),
MountPath: opt.MountPath,
Pkg: opt.Pkg,
CgoEnabled: opt.CgoEnabled,
BuildTags: opt.BuildTags,
GOARCH: opt.GOARCH,
GOOS: opt.GOOS,
})
if err != nil {
return nil, err
}
goBuild := llb.Image("docker.io/tonistiigi/llb-gobuild@sha256:c97016d4a19b9b9888ac6104800f894ca58bff52aa0810f89b3c0bf269633853")
if gb.DevMode {
goBuild = gobuildDev()
}
run := goBuild.Run(llb.Shlexf("gobuild %s", opt.Pkg), llb.AddEnv("GOOPT", string(dt)))
run.AddMount(opt.MountPath, opt.Source, llb.Readonly)
out := run.AddMount("/out", llb.Scratch()).With(llbbuild.Build())
return &out, nil
}
func gobuildDev() llb.State {
gobDev := llb.Local("gobuild-dev")
build := goBuildBase().
Run(llb.Shlex("apk add --no-cache git")).
Dir("/go/src/github.com/tonistiigi/llb-gobuild").
Run(llb.Shlex("sh -c \"go get -d github.com/moby/buildkit/client/llb && rm -rf /go/src/github.com/moby/buildkit/vendor/github.com/opencontainers/go-digest && go get -d github.com/opencontainers/go-digest\"")).
Run(llb.Shlex("go build -o /out/gobuild github.com/tonistiigi/llb-gobuild/cmd/gobuild"))
build.AddMount("/go/src/github.com/tonistiigi/llb-gobuild", gobDev, llb.Readonly)
out := build.AddMount("/out", llb.Scratch())
alpine := llb.Image("docker.io/library/alpine:latest")
return copy(out, "/gobuild", alpine, "/bin")
}
func goBuildBase() llb.State {
goAlpine := llb.Image("docker.io/library/golang:1.9-alpine@sha256:354be5853ea170e6f8bf3e258154e10ba0ed03f909d8be8625faf61592c515c8")
return goAlpine.
AddEnv("CGO_ENABLED", "0").
AddEnv("GOPATH", "/go").
AddEnv("PATH", "/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") //.
//AddEnv("GOPATH", "/go").Run(llb.Shlex("apk add --no-cache gcc libc-dev")).
// Root()
}
// copy copies files between 2 states using cp until there is no copyOp
func copy(src llb.State, srcPath string, dest llb.State, destPath string) llb.State {
cpImage := llb.Image("docker.io/library/alpine:latest")
cp := cpImage.Run(llb.Shlexf("cp -a /src%s /dest%s", srcPath, destPath))
cp.AddMount("/src", src, llb.Readonly)
return cp.AddMount("/dest", dest)
}