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/pkgpath",
51 "cmd/internal/quoted",
52 "cmd/internal/src",
53 "cmd/internal/sys",
54 "cmd/link",
55 "cmd/link/internal/...",
56 "compress/flate",
57 "compress/zlib",
58 "container/heap",
59 "debug/dwarf",
60 "debug/elf",
61 "debug/macho",
62 "debug/pe",
63 "go/build/constraint",
64 "go/constant",
65 "go/version",
66 "internal/abi",
67 "internal/coverage",
68 "cmd/internal/cov/covcmd",
69 "internal/bisect",
70 "internal/buildcfg",
71 "internal/goarch",
72 "internal/godebugs",
73 "internal/goexperiment",
74 "internal/goroot",
75 "internal/gover",
76 "internal/goversion",
77
78
79
80
81 "internal/lazyregexp",
82 "internal/pkgbits",
83 "internal/platform",
84 "internal/profile",
85 "internal/race",
86 "internal/saferio",
87 "internal/syscall/unix",
88 "internal/types/errors",
89 "internal/unsafeheader",
90 "internal/xcoff",
91 "internal/zstd",
92 "math/bits",
93 "sort",
94 }
95
96
97
98 var ignorePrefixes = []string{
99 ".",
100 "_",
101 "#",
102 }
103
104
105
106
107 var ignoreSuffixes = []string{
108 "_test.s",
109 "_test.go",
110
111
112
113 ".pgo",
114 }
115
116 var tryDirs = []string{
117 "sdk/go1.17",
118 "go1.17",
119 }
120
121 func bootstrapBuildTools() {
122 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
123 if goroot_bootstrap == "" {
124 home := os.Getenv("HOME")
125 goroot_bootstrap = pathf("%s/go1.4", home)
126 for _, d := range tryDirs {
127 if p := pathf("%s/%s", home, d); isdir(p) {
128 goroot_bootstrap = p
129 }
130 }
131 }
132 xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap)
133
134 mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot))
135 mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))
136
137
138
139
140
141
142 workspace := pathf("%s/pkg/bootstrap", goroot)
143 xremoveall(workspace)
144 xatexit(func() { xremoveall(workspace) })
145 base := pathf("%s/src/bootstrap", workspace)
146 xmkdirall(base)
147
148
149 writefile("module bootstrap\ngo 1.20\n", pathf("%s/%s", base, "go.mod"), 0)
150 for _, dir := range bootstrapDirs {
151 recurse := strings.HasSuffix(dir, "/...")
152 dir = strings.TrimSuffix(dir, "/...")
153 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
154 if err != nil {
155 fatalf("walking bootstrap dirs failed: %v: %v", path, err)
156 }
157
158 name := filepath.Base(path)
159 src := pathf("%s/src/%s", goroot, path)
160 dst := pathf("%s/%s", base, path)
161
162 if info.IsDir() {
163 if !recurse && path != dir || name == "testdata" {
164 return filepath.SkipDir
165 }
166
167 xmkdirall(dst)
168 if path == "cmd/cgo" {
169
170
171 mkzdefaultcc("", pathf("%s/zdefaultcc.go", src))
172 mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst))
173 }
174 return nil
175 }
176
177 for _, pre := range ignorePrefixes {
178 if strings.HasPrefix(name, pre) {
179 return nil
180 }
181 }
182 for _, suf := range ignoreSuffixes {
183 if strings.HasSuffix(name, suf) {
184 return nil
185 }
186 }
187
188 text := bootstrapRewriteFile(src)
189 writefile(text, dst, 0)
190 return nil
191 })
192 }
193
194
195
196
197
198
199
200
201
202
203
204 defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
205 os.Setenv("GOROOT", goroot_bootstrap)
206
207 defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
208 os.Setenv("GOPATH", workspace)
209
210 defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
211 os.Setenv("GOBIN", "")
212
213 os.Setenv("GOOS", "")
214 os.Setenv("GOHOSTOS", "")
215 os.Setenv("GOARCH", "")
216 os.Setenv("GOHOSTARCH", "")
217
218
219
220
221
222
223 cmd := []string{
224 pathf("%s/bin/go", goroot_bootstrap),
225 "install",
226 "-tags=math_big_pure_go compiler_bootstrap purego",
227 }
228 if vflag > 0 {
229 cmd = append(cmd, "-v")
230 }
231 if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" {
232 cmd = append(cmd, "-toolexec="+tool)
233 }
234 cmd = append(cmd, "bootstrap/cmd/...")
235 run(base, ShowOutput|CheckExit, cmd...)
236
237
238 for _, name := range bootstrapDirs {
239 if !strings.HasPrefix(name, "cmd/") {
240 continue
241 }
242 name = name[len("cmd/"):]
243 if !strings.Contains(name, "/") {
244 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
245 }
246 }
247
248 if vflag > 0 {
249 xprintf("\n")
250 }
251 }
252
253 var ssaRewriteFileSubstring = filepath.FromSlash("src/cmd/compile/internal/ssa/rewrite")
254
255
256
257
258
259
260
261 func isUnneededSSARewriteFile(srcFile, goArch string) (archCaps string, unneeded bool) {
262 if !strings.Contains(srcFile, ssaRewriteFileSubstring) {
263 return "", false
264 }
265 fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go")
266 if fileArch == "" {
267 return "", false
268 }
269 b := fileArch[0]
270 if b == '_' || ('a' <= b && b <= 'z') {
271 return "", false
272 }
273 archCaps = fileArch
274 fileArch = strings.ToLower(fileArch)
275 fileArch = strings.TrimSuffix(fileArch, "splitload")
276 fileArch = strings.TrimSuffix(fileArch, "latelower")
277 if fileArch == goArch {
278 return "", false
279 }
280 if fileArch == strings.TrimSuffix(goArch, "le") {
281 return "", false
282 }
283 return archCaps, true
284 }
285
286 func bootstrapRewriteFile(srcFile string) string {
287
288
289
290
291 if archCaps, ok := isUnneededSSARewriteFile(srcFile, gohostarch); ok {
292 return fmt.Sprintf(`%spackage ssa
293
294 func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") }
295 func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") }
296 `, generatedHeader, archCaps, archCaps)
297 }
298
299 return bootstrapFixImports(srcFile)
300 }
301
302 func bootstrapFixImports(srcFile string) string {
303 text := readfile(srcFile)
304 if !strings.Contains(srcFile, "/cmd/") && !strings.Contains(srcFile, `\cmd\`) {
305 text = regexp.MustCompile(`\bany\b`).ReplaceAllString(text, "interface{}")
306 }
307 lines := strings.SplitAfter(text, "\n")
308 inBlock := false
309 for i, line := range lines {
310 if strings.HasPrefix(line, "import (") {
311 inBlock = true
312 continue
313 }
314 if inBlock && strings.HasPrefix(line, ")") {
315 inBlock = false
316 continue
317 }
318 if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
319 inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"") || strings.HasPrefix(line, "\texec \"") || strings.HasPrefix(line, "\trtabi \"")) {
320 line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1)
321 for _, dir := range bootstrapDirs {
322 if strings.HasPrefix(dir, "cmd/") {
323 continue
324 }
325 line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1)
326 }
327 lines[i] = line
328 }
329 }
330
331 lines[0] = generatedHeader + "// This is a bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]
332
333 return strings.Join(lines, "")
334 }
335
View as plain text