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 "regexp"
19 "strings"
20 )
21
22
23
24
25
26
27
28
29
30
31
32
33 var bootstrapDirs = []string{
34 "cmp",
35 "cmd/asm",
36 "cmd/asm/internal/...",
37 "cmd/cgo",
38 "cmd/compile",
39 "cmd/compile/internal/...",
40 "cmd/internal/archive",
41 "cmd/internal/bio",
42 "cmd/internal/codesign",
43 "cmd/internal/dwarf",
44 "cmd/internal/edit",
45 "cmd/internal/gcprog",
46 "cmd/internal/goobj",
47 "cmd/internal/notsha256",
48 "cmd/internal/obj/...",
49 "cmd/internal/objabi",
50 "cmd/internal/pgo",
51 "cmd/internal/pkgpath",
52 "cmd/internal/quoted",
53 "cmd/internal/src",
54 "cmd/internal/sys",
55 "cmd/internal/telemetry",
56 "cmd/internal/telemetry/counter",
57 "cmd/link",
58 "cmd/link/internal/...",
59 "compress/flate",
60 "compress/zlib",
61 "container/heap",
62 "debug/dwarf",
63 "debug/elf",
64 "debug/macho",
65 "debug/pe",
66 "go/build/constraint",
67 "go/constant",
68 "go/version",
69 "internal/abi",
70 "internal/coverage",
71 "cmd/internal/cov/covcmd",
72 "internal/bisect",
73 "internal/buildcfg",
74 "internal/goarch",
75 "internal/godebugs",
76 "internal/goexperiment",
77 "internal/goroot",
78 "internal/gover",
79 "internal/goversion",
80
81
82
83
84 "internal/lazyregexp",
85 "internal/pkgbits",
86 "internal/platform",
87 "internal/profile",
88 "internal/race",
89 "internal/saferio",
90 "internal/syscall/unix",
91 "internal/types/errors",
92 "internal/unsafeheader",
93 "internal/xcoff",
94 "internal/zstd",
95 "math/bits",
96 "sort",
97 }
98
99
100
101 var ignorePrefixes = []string{
102 ".",
103 "_",
104 "#",
105 }
106
107
108
109
110 var ignoreSuffixes = []string{
111 "_test.s",
112 "_test.go",
113
114
115
116 ".pgo",
117
118 "~",
119 }
120
121 var tryDirs = []string{
122 "sdk/go1.17",
123 "go1.17",
124 }
125
126 func bootstrapBuildTools() {
127 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
128 if goroot_bootstrap == "" {
129 home := os.Getenv("HOME")
130 goroot_bootstrap = pathf("%s/go1.4", home)
131 for _, d := range tryDirs {
132 if p := pathf("%s/%s", home, d); isdir(p) {
133 goroot_bootstrap = p
134 }
135 }
136 }
137 xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap)
138
139 mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot))
140 mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))
141
142
143
144
145
146
147 workspace := pathf("%s/pkg/bootstrap", goroot)
148 xremoveall(workspace)
149 xatexit(func() { xremoveall(workspace) })
150 base := pathf("%s/src/bootstrap", workspace)
151 xmkdirall(base)
152
153
154 writefile("module bootstrap\ngo 1.20\n", pathf("%s/%s", base, "go.mod"), 0)
155 for _, dir := range bootstrapDirs {
156 recurse := strings.HasSuffix(dir, "/...")
157 dir = strings.TrimSuffix(dir, "/...")
158 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
159 if err != nil {
160 fatalf("walking bootstrap dirs failed: %v: %v", path, err)
161 }
162
163 name := filepath.Base(path)
164 src := pathf("%s/src/%s", goroot, path)
165 dst := pathf("%s/%s", base, path)
166
167 if info.IsDir() {
168 if !recurse && path != dir || name == "testdata" {
169 return filepath.SkipDir
170 }
171
172 xmkdirall(dst)
173 if path == "cmd/cgo" {
174
175
176 mkzdefaultcc("", pathf("%s/zdefaultcc.go", src))
177 mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst))
178 }
179 return nil
180 }
181
182 for _, pre := range ignorePrefixes {
183 if strings.HasPrefix(name, pre) {
184 return nil
185 }
186 }
187 for _, suf := range ignoreSuffixes {
188 if strings.HasSuffix(name, suf) {
189 return nil
190 }
191 }
192
193 text := bootstrapRewriteFile(src)
194 writefile(text, dst, 0)
195 return nil
196 })
197 }
198
199
200
201
202
203
204
205
206
207
208
209 defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
210 os.Setenv("GOROOT", goroot_bootstrap)
211
212 defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
213 os.Setenv("GOPATH", workspace)
214
215 defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
216 os.Setenv("GOBIN", "")
217
218 os.Setenv("GOOS", "")
219 os.Setenv("GOHOSTOS", "")
220 os.Setenv("GOARCH", "")
221 os.Setenv("GOHOSTARCH", "")
222
223
224
225
226
227
228 cmd := []string{
229 pathf("%s/bin/go", goroot_bootstrap),
230 "install",
231 "-tags=math_big_pure_go compiler_bootstrap purego",
232 }
233 if vflag > 0 {
234 cmd = append(cmd, "-v")
235 }
236 if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" {
237 cmd = append(cmd, "-toolexec="+tool)
238 }
239 cmd = append(cmd, "bootstrap/cmd/...")
240 run(base, ShowOutput|CheckExit, cmd...)
241
242
243 for _, name := range bootstrapDirs {
244 if !strings.HasPrefix(name, "cmd/") {
245 continue
246 }
247 name = name[len("cmd/"):]
248 if !strings.Contains(name, "/") {
249 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
250 }
251 }
252
253 if vflag > 0 {
254 xprintf("\n")
255 }
256 }
257
258 var ssaRewriteFileSubstring = filepath.FromSlash("src/cmd/compile/internal/ssa/rewrite")
259
260
261
262
263
264
265
266 func isUnneededSSARewriteFile(srcFile, goArch string) (archCaps string, unneeded bool) {
267 if !strings.Contains(srcFile, ssaRewriteFileSubstring) {
268 return "", false
269 }
270 fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go")
271 if fileArch == "" {
272 return "", false
273 }
274 b := fileArch[0]
275 if b == '_' || ('a' <= b && b <= 'z') {
276 return "", false
277 }
278 archCaps = fileArch
279 fileArch = strings.ToLower(fileArch)
280 fileArch = strings.TrimSuffix(fileArch, "splitload")
281 fileArch = strings.TrimSuffix(fileArch, "latelower")
282 if fileArch == goArch {
283 return "", false
284 }
285 if fileArch == strings.TrimSuffix(goArch, "le") {
286 return "", false
287 }
288 return archCaps, true
289 }
290
291 func bootstrapRewriteFile(srcFile string) string {
292
293
294
295
296 if archCaps, ok := isUnneededSSARewriteFile(srcFile, gohostarch); ok {
297 return fmt.Sprintf(`%spackage ssa
298
299 func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") }
300 func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") }
301 `, generatedHeader, archCaps, archCaps)
302 }
303
304 return bootstrapFixImports(srcFile)
305 }
306
307 var (
308 importRE = regexp.MustCompile(`\Aimport\s+(\.|[A-Za-z0-9_]+)?\s*"([^"]+)"\s*(//.*)?\n\z`)
309 importBlockRE = regexp.MustCompile(`\A\s*(?:(\.|[A-Za-z0-9_]+)?\s*"([^"]+)")?\s*(//.*)?\n\z`)
310 )
311
312 func bootstrapFixImports(srcFile string) string {
313 text := readfile(srcFile)
314 if !strings.Contains(srcFile, "/cmd/") && !strings.Contains(srcFile, `\cmd\`) {
315 text = regexp.MustCompile(`\bany\b`).ReplaceAllString(text, "interface{}")
316 }
317 lines := strings.SplitAfter(text, "\n")
318 inBlock := false
319 inComment := false
320 for i, line := range lines {
321 if strings.HasSuffix(line, "*/\n") {
322 inComment = false
323 }
324 if strings.HasSuffix(line, "/*\n") {
325 inComment = true
326 }
327 if inComment {
328 continue
329 }
330 if strings.HasPrefix(line, "import (") {
331 inBlock = true
332 continue
333 }
334 if inBlock && strings.HasPrefix(line, ")") {
335 inBlock = false
336 continue
337 }
338
339 var m []string
340 if !inBlock {
341 if !strings.HasPrefix(line, "import ") {
342 continue
343 }
344 m = importRE.FindStringSubmatch(line)
345 if m == nil {
346 fatalf("%s:%d: invalid import declaration: %q", srcFile, i+1, line)
347 }
348 } else {
349 m = importBlockRE.FindStringSubmatch(line)
350 if m == nil {
351 fatalf("%s:%d: invalid import block line", srcFile, i+1)
352 }
353 if m[2] == "" {
354 continue
355 }
356 }
357
358 path := m[2]
359 if strings.HasPrefix(path, "cmd/") {
360 path = "bootstrap/" + path
361 } else {
362 for _, dir := range bootstrapDirs {
363 if path == dir {
364 path = "bootstrap/" + dir
365 break
366 }
367 }
368 }
369
370
371 if path == "internal/reflectlite" {
372 lines[i] = strings.ReplaceAll(line, `"reflect"`, `reflectlite "reflect"`)
373 continue
374 }
375
376
377
378
379
380
381
382
383 if strings.HasPrefix(path, "internal/") {
384 fatalf("%s:%d: bootstrap-copied source file cannot import %s", srcFile, i+1, path)
385 }
386 if path != m[2] {
387 lines[i] = strings.ReplaceAll(line, `"`+m[2]+`"`, `"`+path+`"`)
388 }
389 }
390
391 lines[0] = generatedHeader + "// This is a bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]
392
393 return strings.Join(lines, "")
394 }
395
View as plain text