diff options
Diffstat (limited to 'src/cmd/dist/buildgo.go')
-rw-r--r-- | src/cmd/dist/buildgo.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/cmd/dist/buildgo.go b/src/cmd/dist/buildgo.go new file mode 100644 index 0000000..884e9d7 --- /dev/null +++ b/src/cmd/dist/buildgo.go @@ -0,0 +1,162 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" +) + +/* + * Helpers for building cmd/go and cmd/cgo. + */ + +// generatedHeader is the string that all source files generated by dist start with. +// +// DO NOT CHANGE THIS STRING. If this string is changed then during +// +// ./make.bash +// git checkout other-rev +// ./make.bash +// +// the second make.bash will not find the files generated by the first make.bash +// and will not clean up properly. +const generatedHeader = "// Code generated by go tool dist; DO NOT EDIT.\n\n" + +// writeHeader emits the standard "generated by" header for all files generated +// by dist. +func writeHeader(w io.Writer) { + fmt.Fprint(w, generatedHeader) +} + +// mkzdefaultcc writes zdefaultcc.go: +// +// package main +// const defaultCC = <defaultcc> +// const defaultCXX = <defaultcxx> +// const defaultPkgConfig = <defaultpkgconfig> +// +// It is invoked to write cmd/go/internal/cfg/zdefaultcc.go +// but we also write cmd/cgo/zdefaultcc.go +func mkzdefaultcc(dir, file string) { + if strings.Contains(file, filepath.FromSlash("go/internal/cfg")) { + var buf strings.Builder + writeHeader(&buf) + fmt.Fprintf(&buf, "package cfg\n") + fmt.Fprintln(&buf) + fmt.Fprintf(&buf, "const DefaultPkgConfig = `%s`\n", defaultpkgconfig) + buf.WriteString(defaultCCFunc("DefaultCC", defaultcc)) + buf.WriteString(defaultCCFunc("DefaultCXX", defaultcxx)) + writefile(buf.String(), file, writeSkipSame) + return + } + + var buf strings.Builder + writeHeader(&buf) + fmt.Fprintf(&buf, "package main\n") + fmt.Fprintln(&buf) + fmt.Fprintf(&buf, "const defaultPkgConfig = `%s`\n", defaultpkgconfig) + buf.WriteString(defaultCCFunc("defaultCC", defaultcc)) + buf.WriteString(defaultCCFunc("defaultCXX", defaultcxx)) + writefile(buf.String(), file, writeSkipSame) +} + +func defaultCCFunc(name string, defaultcc map[string]string) string { + var buf strings.Builder + + fmt.Fprintf(&buf, "func %s(goos, goarch string) string {\n", name) + fmt.Fprintf(&buf, "\tswitch goos+`/`+goarch {\n") + var keys []string + for k := range defaultcc { + if k != "" { + keys = append(keys, k) + } + } + sort.Strings(keys) + for _, k := range keys { + fmt.Fprintf(&buf, "\tcase %s:\n\t\treturn %s\n", quote(k), quote(defaultcc[k])) + } + fmt.Fprintf(&buf, "\t}\n") + if cc := defaultcc[""]; cc != "" { + fmt.Fprintf(&buf, "\treturn %s\n", quote(cc)) + } else { + clang, gcc := "clang", "gcc" + if strings.HasSuffix(name, "CXX") { + clang, gcc = "clang++", "g++" + } + fmt.Fprintf(&buf, "\tswitch goos {\n") + fmt.Fprintf(&buf, "\tcase ") + for i, os := range clangos { + if i > 0 { + fmt.Fprintf(&buf, ", ") + } + fmt.Fprintf(&buf, "%s", quote(os)) + } + fmt.Fprintf(&buf, ":\n") + fmt.Fprintf(&buf, "\t\treturn %s\n", quote(clang)) + fmt.Fprintf(&buf, "\t}\n") + fmt.Fprintf(&buf, "\treturn %s\n", quote(gcc)) + } + fmt.Fprintf(&buf, "}\n") + + return buf.String() +} + +// mkzcgo writes zcgo.go for the go/build package: +// +// package build +// const defaultCGO_ENABLED = <CGO_ENABLED> +// +// It is invoked to write go/build/zcgo.go. +func mkzcgo(dir, file string) { + var buf strings.Builder + writeHeader(&buf) + fmt.Fprintf(&buf, "package build\n") + fmt.Fprintln(&buf) + fmt.Fprintf(&buf, "const defaultCGO_ENABLED = %s\n", quote(os.Getenv("CGO_ENABLED"))) + + writefile(buf.String(), file, writeSkipSame) +} + +// mktzdata src/time/tzdata/zzipdata.go: +// +// package tzdata +// const zipdata = "PK..." +func mktzdata(dir, file string) { + zip := readfile(filepath.Join(dir, "../../../lib/time/zoneinfo.zip")) + + var buf strings.Builder + writeHeader(&buf) + fmt.Fprintf(&buf, "package tzdata\n") + fmt.Fprintln(&buf) + fmt.Fprintf(&buf, "const zipdata = %s\n", quote(zip)) + + writefile(buf.String(), file, writeSkipSame) +} + +// quote is like strconv.Quote but simpler and has output +// that does not depend on the exact Go bootstrap version. +func quote(s string) string { + const hex = "0123456789abcdef" + var out strings.Builder + out.WriteByte('"') + for i := 0; i < len(s); i++ { + c := s[i] + if 0x20 <= c && c <= 0x7E && c != '"' && c != '\\' { + out.WriteByte(c) + } else { + out.WriteByte('\\') + out.WriteByte('x') + out.WriteByte(hex[c>>4]) + out.WriteByte(hex[c&0xf]) + } + } + out.WriteByte('"') + return out.String() +} |