Source file
src/cmd/dist/buildtool.go
1
2
3
4
5
6
7
8
9
10
11
12 package main
13
14 import (
15 "fmt"
16 "os"
17 "path/filepath"
18 "runtime"
19 "strings"
20 )
21
22
23
24
25
26
27
28
29
30
31
32
33 var bootstrapDirs = []string{
34 "cmd/asm",
35 "cmd/asm/internal/...",
36 "cmd/cgo",
37 "cmd/compile",
38 "cmd/compile/internal/...",
39 "cmd/internal/archive",
40 "cmd/internal/bio",
41 "cmd/internal/codesign",
42 "cmd/internal/dwarf",
43 "cmd/internal/edit",
44 "cmd/internal/gcprog",
45 "cmd/internal/goobj",
46 "cmd/internal/obj/...",
47 "cmd/internal/objabi",
48 "cmd/internal/pkgpath",
49 "cmd/internal/src",
50 "cmd/internal/sys",
51 "cmd/link",
52 "cmd/link/internal/...",
53 "compress/flate",
54 "compress/zlib",
55 "container/heap",
56 "debug/dwarf",
57 "debug/elf",
58 "debug/macho",
59 "debug/pe",
60 "go/constant",
61 "internal/buildcfg",
62 "internal/goexperiment",
63 "internal/goversion",
64 "internal/race",
65 "internal/unsafeheader",
66 "internal/xcoff",
67 "math/big",
68 "math/bits",
69 "sort",
70 "strconv",
71 }
72
73
74
75 var ignorePrefixes = []string{
76 ".",
77 "_",
78 "#",
79 }
80
81
82
83
84 var ignoreSuffixes = []string{
85 "_arm64.s",
86 "_arm64.go",
87 "_riscv64.s",
88 "_riscv64.go",
89 "_wasm.s",
90 "_wasm.go",
91 "_test.s",
92 "_test.go",
93 }
94
95 func bootstrapBuildTools() {
96 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
97 if goroot_bootstrap == "" {
98 goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
99 }
100 xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap)
101
102 mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot))
103 mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))
104
105
106
107
108
109
110 workspace := pathf("%s/pkg/bootstrap", goroot)
111 xremoveall(workspace)
112 xatexit(func() { xremoveall(workspace) })
113 base := pathf("%s/src/bootstrap", workspace)
114 xmkdirall(base)
115
116
117 writefile("module bootstrap\n", pathf("%s/%s", base, "go.mod"), 0)
118 for _, dir := range bootstrapDirs {
119 recurse := strings.HasSuffix(dir, "/...")
120 dir = strings.TrimSuffix(dir, "/...")
121 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
122 if err != nil {
123 fatalf("walking bootstrap dirs failed: %v: %v", path, err)
124 }
125
126 name := filepath.Base(path)
127 src := pathf("%s/src/%s", goroot, path)
128 dst := pathf("%s/%s", base, path)
129
130 if info.IsDir() {
131 if !recurse && path != dir || name == "testdata" {
132 return filepath.SkipDir
133 }
134
135 xmkdirall(dst)
136 if path == "cmd/cgo" {
137
138
139 mkzdefaultcc("", pathf("%s/zdefaultcc.go", src))
140 mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst))
141 }
142 return nil
143 }
144
145 for _, pre := range ignorePrefixes {
146 if strings.HasPrefix(name, pre) {
147 return nil
148 }
149 }
150 for _, suf := range ignoreSuffixes {
151 if strings.HasSuffix(name, suf) {
152 return nil
153 }
154 }
155
156 text := bootstrapRewriteFile(src)
157 writefile(text, dst, 0)
158 return nil
159 })
160 }
161
162
163
164
165
166
167
168
169
170
171
172 defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
173 os.Setenv("GOROOT", goroot_bootstrap)
174
175 defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
176 os.Setenv("GOPATH", workspace)
177
178 defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
179 os.Setenv("GOBIN", "")
180
181 os.Setenv("GOOS", "")
182 os.Setenv("GOHOSTOS", "")
183 os.Setenv("GOARCH", "")
184 os.Setenv("GOHOSTARCH", "")
185
186
187
188
189
190
191
192
193
194 cmd := []string{
195 pathf("%s/bin/go", goroot_bootstrap),
196 "install",
197 "-gcflags=-l",
198 "-tags=math_big_pure_go compiler_bootstrap",
199 }
200 if vflag > 0 {
201 cmd = append(cmd, "-v")
202 }
203 if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" {
204 cmd = append(cmd, "-toolexec="+tool)
205 }
206 cmd = append(cmd, "bootstrap/cmd/...")
207 run(base, ShowOutput|CheckExit, cmd...)
208
209
210 for _, name := range bootstrapDirs {
211 if !strings.HasPrefix(name, "cmd/") {
212 continue
213 }
214 name = name[len("cmd/"):]
215 if !strings.Contains(name, "/") {
216 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
217 }
218 }
219
220 if vflag > 0 {
221 xprintf("\n")
222 }
223 }
224
225 var ssaRewriteFileSubstring = filepath.FromSlash("src/cmd/compile/internal/ssa/rewrite")
226
227
228
229
230
231
232
233 func isUnneededSSARewriteFile(srcFile string) (archCaps string, unneeded bool) {
234 if !strings.Contains(srcFile, ssaRewriteFileSubstring) {
235 return "", false
236 }
237 fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go")
238 if fileArch == "" {
239 return "", false
240 }
241 b := fileArch[0]
242 if b == '_' || ('a' <= b && b <= 'z') {
243 return "", false
244 }
245 archCaps = fileArch
246 fileArch = strings.ToLower(fileArch)
247 fileArch = strings.TrimSuffix(fileArch, "splitload")
248 if fileArch == os.Getenv("GOHOSTARCH") {
249 return "", false
250 }
251 if fileArch == strings.TrimSuffix(runtime.GOARCH, "le") {
252 return "", false
253 }
254 if fileArch == strings.TrimSuffix(os.Getenv("GOARCH"), "le") {
255 return "", false
256 }
257 return archCaps, true
258 }
259
260 func bootstrapRewriteFile(srcFile string) string {
261
262
263
264
265 if archCaps, ok := isUnneededSSARewriteFile(srcFile); ok {
266 return fmt.Sprintf(`// Code generated by go tool dist; DO NOT EDIT.
267
268 package ssa
269
270 func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") }
271 func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") }
272 `, archCaps, archCaps)
273 }
274
275 return bootstrapFixImports(srcFile)
276 }
277
278 func bootstrapFixImports(srcFile string) string {
279 lines := strings.SplitAfter(readfile(srcFile), "\n")
280 inBlock := false
281 for i, line := range lines {
282 if strings.HasPrefix(line, "import (") {
283 inBlock = true
284 continue
285 }
286 if inBlock && strings.HasPrefix(line, ")") {
287 inBlock = false
288 continue
289 }
290 if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
291 inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"") || strings.HasPrefix(line, "\texec \"")) {
292 line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
293
294 line = strings.Replace(line, `exec "internal/execabs"`, `"os/exec"`, -1)
295 for _, dir := range bootstrapDirs {
296 if strings.HasPrefix(dir, "cmd/") {
297 continue
298 }
299 line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
300 }
301 lines[i] = line
302 }
303 }
304
305 lines[0] = "// Code generated by go tool dist; DO NOT EDIT.\n// This is a bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]
306
307 return strings.Join(lines, "")
308 }
309
View as plain text