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