blob: 884e9d729a6a3596c7713a30ebeee413fd2b3245 [file] [log] [blame]
// 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()
}