blob: 71bbe14cd1bd4f67abd5d9827c005a48607676a9 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// The makestdlib.go script builds the standard library for GOROOT.
// It is used as part of the GN+ninja build.
package main
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
)
var (
flagFuchsiaRoot = flag.String("fuchsia-root", "", "Path to root of the Fuchsia project")
flagDepfile = flag.String("depfile", "", "Stdlib depfile")
flagRootOutDir = flag.String("root-out-dir", "", "GN variable")
flagRootGenDir = flag.String("root-gen-dir", "", "GN variable")
flagTargetCPU = flag.String("target-cpu", "", "GN variable")
flagBootstrapPath = flag.String("bootstrap-path", "", "Path to bootstrap Go installation")
)
func genDepfileStdlib() {
// Change anything under src/*, and we rebuild the standard library.
// The command we use, "go install std", is very efficient about what
// packages it rebuilds.
path := *flagDepfile
if path == "" {
return
}
os.Remove(path)
buf := new(bytes.Buffer)
buf.WriteString(relGenDir() + "/gostdlib.done:")
if err := collectDeps(buf); err != nil {
log.Fatal("gen depfile stdlib: %v", err)
}
if err := ioutil.WriteFile(path, buf.Bytes(), 0664); err != nil {
log.Fatal("gen depfile stdlib: %v", err)
}
}
func relGenDir() string {
return (*flagRootGenDir)[len(*flagRootOutDir)+1:]
}
func collectDeps(w io.Writer) error {
fn := func(path string, info os.FileInfo, err error) error {
if info.IsDir() || strings.HasSuffix(path, "_test.go") {
return err
}
fmt.Fprintf(w, " %s", path)
return err
}
return filepath.Walk(filepath.Join(*flagBootstrapPath, "src"), fn)
}
func convCPU(cpu string) (arch string) {
switch cpu {
case "x64":
return "amd64"
case "arm64":
return "arm64"
}
return ""
}
func main() {
log.SetFlags(0)
log.SetPrefix("makestdlib.go: ")
flag.Parse()
if *flagRootGenDir == "" {
log.Fatal("must specify -root-gen-dir")
}
goarchTarget := convCPU(*flagTargetCPU)
if goarchTarget == "" {
log.Fatalf("unsupported target CPU: %s", *flagTargetCPU)
}
genDepfileStdlib()
var wg sync.WaitGroup
wg.Add(1)
go func() {
// Generate the stdlib for the host.
// It is changed by third_party/go srcs being symlinked into buildtools.
cmd := exec.Command(filepath.Join(*flagBootstrapPath, "bin/go"), "install", "std")
cmd.Env = []string{
"PATH=" + os.Getenv("PATH"),
"GOROOT=" + *flagBootstrapPath,
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal("go install std for host failed")
}
wg.Done()
}()
wg.Add(1)
go func() {
// Now generate the stdlib for the Fuchsia target.
cmd := exec.Command(filepath.Join(*flagBootstrapPath, "bin/go"), "install", "std")
cmd.Env = []string{
"PATH=" + os.Getenv("PATH"),
"GOOS=fuchsia",
"GOARCH=" + goarchTarget,
"GOROOT=" + *flagBootstrapPath,
"CGO_ENABLED=1",
"CC=" + filepath.Join(*flagBootstrapPath, "misc/fuchsia/gccwrap.sh"),
"MAGENTA=" + filepath.Join(*flagFuchsiaRoot, "magenta"), // used by gccwrap.sh
"MAGENTA_BUILD_DIR=" + os.Getenv("MAGENTA_BUILD_DIR"), // used by gccwrap.sh
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal("go install std for target failed")
}
wg.Done()
}()
wg.Wait()
donePath := filepath.Join(*flagRootGenDir, "gostdlib.done")
os.Remove(donePath)
if err := ioutil.WriteFile(donePath, []byte("done"), 0664); err != nil {
log.Fatalf("writing done file failed: %v", err)
}
os.Exit(0)
}