1// Copyright 2012 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "fmt" 9 "io" 10 "os" 11 "path/filepath" 12 "sort" 13 "strings" 14) 15 16/* 17 * Helpers for building cmd/go and cmd/cgo. 18 */ 19 20// generatedHeader is the string that all source files generated by dist start with. 21// 22// DO NOT CHANGE THIS STRING. If this string is changed then during 23// 24// ./make.bash 25// git checkout other-rev 26// ./make.bash 27// 28// the second make.bash will not find the files generated by the first make.bash 29// and will not clean up properly. 30const generatedHeader = "// Code generated by go tool dist; DO NOT EDIT.\n\n" 31 32// writeHeader emits the standard "generated by" header for all files generated 33// by dist. 34func writeHeader(w io.Writer) { 35 fmt.Fprint(w, generatedHeader) 36} 37 38// mkzdefaultcc writes zdefaultcc.go: 39// 40// package main 41// const defaultCC = <defaultcc> 42// const defaultCXX = <defaultcxx> 43// const defaultPkgConfig = <defaultpkgconfig> 44// 45// It is invoked to write cmd/go/internal/cfg/zdefaultcc.go 46// but we also write cmd/cgo/zdefaultcc.go 47func mkzdefaultcc(dir, file string) { 48 if strings.Contains(file, filepath.FromSlash("go/internal/cfg")) { 49 var buf strings.Builder 50 writeHeader(&buf) 51 fmt.Fprintf(&buf, "package cfg\n") 52 fmt.Fprintln(&buf) 53 fmt.Fprintf(&buf, "const DefaultPkgConfig = `%s`\n", defaultpkgconfig) 54 buf.WriteString(defaultCCFunc("DefaultCC", defaultcc)) 55 buf.WriteString(defaultCCFunc("DefaultCXX", defaultcxx)) 56 writefile(buf.String(), file, writeSkipSame) 57 return 58 } 59 60 var buf strings.Builder 61 writeHeader(&buf) 62 fmt.Fprintf(&buf, "package main\n") 63 fmt.Fprintln(&buf) 64 fmt.Fprintf(&buf, "const defaultPkgConfig = `%s`\n", defaultpkgconfig) 65 buf.WriteString(defaultCCFunc("defaultCC", defaultcc)) 66 buf.WriteString(defaultCCFunc("defaultCXX", defaultcxx)) 67 writefile(buf.String(), file, writeSkipSame) 68} 69 70func defaultCCFunc(name string, defaultcc map[string]string) string { 71 var buf strings.Builder 72 73 fmt.Fprintf(&buf, "func %s(goos, goarch string) string {\n", name) 74 fmt.Fprintf(&buf, "\tswitch goos+`/`+goarch {\n") 75 var keys []string 76 for k := range defaultcc { 77 if k != "" { 78 keys = append(keys, k) 79 } 80 } 81 sort.Strings(keys) 82 for _, k := range keys { 83 fmt.Fprintf(&buf, "\tcase %s:\n\t\treturn %s\n", quote(k), quote(defaultcc[k])) 84 } 85 fmt.Fprintf(&buf, "\t}\n") 86 if cc := defaultcc[""]; cc != "" { 87 fmt.Fprintf(&buf, "\treturn %s\n", quote(cc)) 88 } else { 89 clang, gcc := "clang", "gcc" 90 if strings.HasSuffix(name, "CXX") { 91 clang, gcc = "clang++", "g++" 92 } 93 fmt.Fprintf(&buf, "\tswitch goos {\n") 94 fmt.Fprintf(&buf, "\tcase ") 95 for i, os := range clangos { 96 if i > 0 { 97 fmt.Fprintf(&buf, ", ") 98 } 99 fmt.Fprintf(&buf, "%s", quote(os)) 100 } 101 fmt.Fprintf(&buf, ":\n") 102 fmt.Fprintf(&buf, "\t\treturn %s\n", quote(clang)) 103 fmt.Fprintf(&buf, "\t}\n") 104 fmt.Fprintf(&buf, "\treturn %s\n", quote(gcc)) 105 } 106 fmt.Fprintf(&buf, "}\n") 107 108 return buf.String() 109} 110 111// mkzcgo writes zcgo.go for the go/build package: 112// 113// package build 114// const defaultCGO_ENABLED = <CGO_ENABLED> 115// 116// It is invoked to write go/build/zcgo.go. 117func mkzcgo(dir, file string) { 118 var buf strings.Builder 119 writeHeader(&buf) 120 fmt.Fprintf(&buf, "package build\n") 121 fmt.Fprintln(&buf) 122 fmt.Fprintf(&buf, "const defaultCGO_ENABLED = %s\n", quote(os.Getenv("CGO_ENABLED"))) 123 124 writefile(buf.String(), file, writeSkipSame) 125} 126 127// mktzdata src/time/tzdata/zzipdata.go: 128// 129// package tzdata 130// const zipdata = "PK..." 131func mktzdata(dir, file string) { 132 zip := readfile(filepath.Join(dir, "../../../lib/time/zoneinfo.zip")) 133 134 var buf strings.Builder 135 writeHeader(&buf) 136 fmt.Fprintf(&buf, "package tzdata\n") 137 fmt.Fprintln(&buf) 138 fmt.Fprintf(&buf, "const zipdata = %s\n", quote(zip)) 139 140 writefile(buf.String(), file, writeSkipSame) 141} 142 143// quote is like strconv.Quote but simpler and has output 144// that does not depend on the exact Go bootstrap version. 145func quote(s string) string { 146 const hex = "0123456789abcdef" 147 var out strings.Builder 148 out.WriteByte('"') 149 for i := 0; i < len(s); i++ { 150 c := s[i] 151 if 0x20 <= c && c <= 0x7E && c != '"' && c != '\\' { 152 out.WriteByte(c) 153 } else { 154 out.WriteByte('\\') 155 out.WriteByte('x') 156 out.WriteByte(hex[c>>4]) 157 out.WriteByte(hex[c&0xf]) 158 } 159 } 160 out.WriteByte('"') 161 return out.String() 162} 163