| // 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) |
| } |