// Copyright 2011 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 gcimporter implements Import for gc-generated object files.
package gcimporter // import "go/internal/gcimporter"import ()// debugging/development supportconst debug = falsevar exportMap sync.Map// package dir → func() (string, error)// lookupGorootExport returns the location of the export data// (normally found in the build cache, but located in GOROOT/pkg// in prior Go releases) for the package located in pkgDir.//// (We use the package's directory instead of its import path// mainly to simplify handling of the packages in src/vendor// and cmd/vendor.)func lookupGorootExport( string) (string, error) { , := exportMap.Load()if ! {var (sync.Oncestringerror ) , _ = exportMap.LoadOrStore(, func() (string, error) { .Do(func() { := exec.Command(filepath.Join(build.Default.GOROOT, "bin", "go"), "list", "-export", "-f", "{{.Export}}", ) .Dir = build.Default.GOROOT .Env = append(os.Environ(), "PWD="+.Dir, "GOROOT="+build.Default.GOROOT)var []byte , = .Output()if != nil {if , := .(*exec.ExitError); && len(.Stderr) > 0 { = errors.New(string(.Stderr)) }return } := strings.Split(string(bytes.TrimSpace()), "\n")iflen() != 1 { = fmt.Errorf("go list reported %d exports; expected 1", len())return } = [0] })return , }) }return .(func() (string, error))()}var pkgExts = [...]string{".a", ".o"} // a file from the build cache will have no extension// FindPkg returns the filename and unique package id for an import// path based on package information provided by build.Import (using// the build.Default build.Context). A relative srcDir is interpreted// relative to the current working directory.func (, string) (, string, error) {if == "" {return"", "", errors.New("path is empty") }varstringswitch {default:// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // Don't require the source files to be present.if , := filepath.Abs(); == nil { // see issue 14282 = }var *build.Package , = build.Import(, , build.FindOnly|build.AllowBinary)if .PkgObj == "" {if .Goroot && .Dir != "" { , = lookupGorootExport(.Dir)if == nil { _, = os.Stat() }if == nil {return , .ImportPath, nil } }goto } else { = strings.TrimSuffix(.PkgObj, ".a") } = .ImportPathcasebuild.IsLocalImport():// "./x" -> "/this/directory/x.ext", "/this/directory/x" = filepath.Join(, ) = casefilepath.IsAbs():// for completeness only - go/build.Import // does not support absolute imports // "/x" -> "/x.ext", "/x" = = }iffalse { // for debuggingif != {fmt.Printf("%s -> %s\n", , ) } }// try extensionsfor , := rangepkgExts { = + , := os.Stat()if == nil && !.IsDir() {return , , nil }if == nil { = } }:if == nil {return"", , fmt.Errorf("can't find import: %q", ) }return"", , fmt.Errorf("can't find import: %q: %w", , )}// Import imports a gc-generated package given its import path and srcDir, adds// the corresponding package object to the packages map, and returns the object.// The packages map must contain all packages already imported.func ( *token.FileSet, map[string]*types.Package, , string, func( string) (io.ReadCloser, error)) ( *types.Package, error) {vario.ReadCloservarstringif != nil {// With custom lookup specified, assume that caller has // converted path to a canonical import path for use in the map.if == "unsafe" {returntypes.Unsafe, nil } = // No need to re-import if the package was imported completely before.if = []; != nil && .Complete() {return } , := ()if != nil {returnnil, } = } else {varstring , , = FindPkg(, )if == "" {if == "unsafe" {returntypes.Unsafe, nil }returnnil, }// no need to re-import if the package was imported completely beforeif = []; != nil && .Complete() {return }// open file , := os.Open()if != nil {returnnil, }deferfunc() {if != nil {// add file name to error = fmt.Errorf("%s: %v", , ) } }() = }defer .Close() := bufio.NewReader() , , := FindExportData()if != nil {return }switch {case"$$\n": = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", )case"$$B\n":varbyteif , = .ReadByte(); != nil {return } --// The unified export format starts with a 'u'; the indexed export // format starts with an 'i'; and the older binary export format // starts with a 'c', 'd', or 'v' (from "version"). Select // appropriate importer.switch {case'u':var []bytevario.Reader = if >= 0 {if , = saferio.ReadData(, uint64()); != nil {return } } elseif , = io.ReadAll(); != nil {return } := string() = [:strings.LastIndex(, "\n$$\n")] := pkgbits.NewPkgDecoder(, ) = readUnifiedPackage(, nil, , )case'i': , = iImportData(, , , )default: = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", ) }default: = fmt.Errorf("import %q: unknown export data header: %q", , ) }return}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.