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  }