github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/internal/goroot/importcfg.go (about) 1 // Copyright 2022 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 5 package goroot 6 7 import ( 8 "bytes" 9 "fmt" 10 "os/exec" 11 "strings" 12 "sync" 13 ) 14 15 // Importcfg returns an importcfg file to be passed to the 16 // Go compiler that contains the cached paths for the .a files for the 17 // standard library. 18 func Importcfg() (string, error) { 19 var icfg bytes.Buffer 20 21 m, err := PkgfileMap() 22 if err != nil { 23 return "", err 24 } 25 fmt.Fprintf(&icfg, "# import config") 26 for importPath, export := range m { 27 if importPath != "unsafe" && export != "" { // unsafe 28 fmt.Fprintf(&icfg, "\npackagefile %s=%s", importPath, export) 29 } 30 } 31 s := icfg.String() 32 return s, nil 33 } 34 35 var ( 36 stdlibPkgfileMap map[string]string 37 stdlibPkgfileErr error 38 once sync.Once 39 ) 40 41 // PkgfileMap returns a map of package paths to the location on disk 42 // of the .a file for the package. 43 // The caller must not modify the map. 44 func PkgfileMap() (map[string]string, error) { 45 once.Do(func() { 46 m := make(map[string]string) 47 output, err := exec.Command("go", "list", "-export", "-e", "-f", "{{.ImportPath}} {{.Export}}", "std", "cmd").Output() 48 if err != nil { 49 stdlibPkgfileErr = err 50 } 51 for _, line := range strings.Split(string(output), "\n") { 52 if line == "" { 53 continue 54 } 55 sp := strings.SplitN(line, " ", 2) 56 if len(sp) != 2 { 57 err = fmt.Errorf("determining pkgfile map: invalid line in go list output: %q", line) 58 return 59 } 60 importPath, export := sp[0], sp[1] 61 m[importPath] = export 62 } 63 stdlibPkgfileMap = m 64 }) 65 return stdlibPkgfileMap, stdlibPkgfileErr 66 }