// 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 = // const defaultCXX = // const 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 = // // 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() }