"bufio"
"fmt"
"go/build"
+ "internal/goroot"
"internal/pkgbits"
"io"
"os"
+ "path"
"path/filepath"
"strings"
// debugging/development support
const debug = false
-var pkgExts = [...]string{".a", ".o"}
+func lookupGorootExport(pkgpath, srcRoot, srcDir string) (string, bool) {
+ pkgpath = filepath.ToSlash(pkgpath)
+ m, err := goroot.PkgfileMap()
+ if err != nil {
+ return "", false
+ }
+ if export, ok := m[pkgpath]; ok {
+ return export, true
+ }
+ vendorPrefix := "vendor"
+ if strings.HasPrefix(srcDir, filepath.Join(srcRoot, "cmd")) {
+ vendorPrefix = path.Join("cmd", vendorPrefix)
+ }
+ pkgpath = path.Join(vendorPrefix, pkgpath)
+ fmt.Fprintln(os.Stderr, "looking up ", pkgpath)
+ export, ok := m[pkgpath]
+ return export, ok
+}
+
+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
}
bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" {
- id = path // make sure we have an id to print in error message
- return
+ var ok bool
+ if bp.Goroot {
+ filename, ok = lookupGorootExport(path, bp.SrcRoot, srcDir)
+ }
+ if !ok {
+ id = path // make sure we have an id to print in error message
+ return
+ }
+ } else {
+ noext = strings.TrimSuffix(bp.PkgObj, ".a")
+ id = bp.ImportPath
}
- noext = strings.TrimSuffix(bp.PkgObj, ".a")
- id = bp.ImportPath
case build.IsLocalImport(path):
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
}
}
+ if filename != "" {
+ if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+ return
+ }
+ }
// try extensions
for _, ext := range pkgExts {
filename = noext + ext
"internal/testenv"
"os"
"os/exec"
+ "path"
"path/filepath"
"runtime"
"strings"
// compile runs the compiler on filename, with dirname as the working directory,
// and writes the output file to outdirname.
-func compile(t *testing.T, dirname, filename, outdirname string) string {
+// compile gives the resulting package a packagepath of testdata/<filebasename>.
+func compile(t *testing.T, dirname, filename, outdirname string, packagefiles map[string]string) string {
// filename must end with ".go"
- if !strings.HasSuffix(filename, ".go") {
+ basename, ok := strings.CutSuffix(filepath.Base(filename), ".go")
+ if !ok {
t.Fatalf("filename doesn't end in .go: %s", filename)
}
- basename := filepath.Base(filename)
- outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", strings.TrimSuffix(outname, ".o"), "-o", outname, filename)
+ objname := basename + ".o"
+ outname := filepath.Join(outdirname, objname)
+ importcfgfile := filepath.Join(outdirname, basename) + ".importcfg"
+ testenv.WriteImportcfg(t, importcfgfile, packagefiles)
+ pkgpath := path.Join("testdata", basename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", pkgpath, "-D", "testdata", "-importcfg", importcfgfile, "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"), nil)
path := "./testdata/" + strings.TrimSuffix(testfile, ".go")
if pkg := testPath(t, path, tmpdir); pkg != nil {
if err != nil {
t.Fatal(err)
}
- compile(t, "testdata", "a.go", testoutdir)
- compile(t, testoutdir, bpath, testoutdir)
+ compile(t, "testdata", "a.go", testoutdir, nil)
+ compile(t, testoutdir, bpath, testoutdir, map[string]string{"testdata/a": filepath.Join(testoutdir, "a.o")})
// import must succeed (test for issue at hand)
pkg := importPkg(t, "./testdata/b", tmpdir)
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"), nil)
// Multiple imports of p must succeed without redeclaration errors.
// We use an import path that's not cleaned up so that the eventual
func compileAndImportPkg(t *testing.T, name string) *types2.Package {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"), nil)
return importPkg(t, "./testdata/"+name, tmpdir)
}
"internal/coverage",
"internal/buildcfg",
"internal/goexperiment",
+ "internal/goroot",
"internal/goversion",
"internal/pkgbits",
"internal/race",
go1src := filepath.Join("testdata", "go1.go")
go2src := filepath.Join("testdata", "go2.go")
- out, err := exec.Command(gotool, "tool", "compile", "-p=p", "-o", go1obj, go1src).CombinedOutput()
+ importcfgfile := filepath.Join(buildDir, "importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
+ out, err := exec.Command(gotool, "tool", "compile", "-importcfg="+importcfgfile, "-p=p", "-o", go1obj, go1src).CombinedOutput()
if err != nil {
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go1obj, go1src, err, out)
}
- out, err = exec.Command(gotool, "tool", "compile", "-p=p", "-o", go2obj, go2src).CombinedOutput()
+ out, err = exec.Command(gotool, "tool", "compile", "-importcfg="+importcfgfile, "-p=p", "-o", go2obj, go2src).CombinedOutput()
if err != nil {
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go2obj, go2src, err, out)
}
tmpdir := t.TempDir()
+ importcfgfile := filepath.Join(tmpdir, "importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
err := os.WriteFile(filepath.Join(tmpdir, "main.go"), []byte(source), 0666)
if err != nil {
t.Fatalf("failed to write main.go: %v\n", err)
}
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "main.go")
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-importcfg="+importcfgfile, "-p=main", "main.go")
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("failed to compile main.go: %v, output: %s\n", err, out)
}
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "main.o")
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-importcfg="+importcfgfile, "main.o")
cmd.Dir = tmpdir
out, err = cmd.CombinedOutput()
if err != nil {
}
}
+ importcfgfile := filepath.Join(tmpdir, "importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
// Compile a main package.
write("main.go", "package main; func main() {}")
- runGo("tool", "compile", "-p=main", "main.go")
+ runGo("tool", "compile", "-importcfg="+importcfgfile, "-p=main", "main.go")
runGo("tool", "pack", "c", "main.a", "main.o")
// Add an extra section with a short, non-.o name.
// Verify that the linker does not attempt
// to compile the extra section.
- runGo("tool", "link", "main.a")
+ runGo("tool", "link", "-importcfg="+importcfgfile, "main.a")
}
func TestUnresolved(t *testing.T) {
cc := strings.TrimSpace(runGo("env", "CC"))
cflags := strings.Fields(runGo("env", "GOGCCFLAGS"))
+ importcfgfile := filepath.Join(tmpdir, "importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
// Compile, assemble and pack the Go and C code.
runGo("tool", "asm", "-p=main", "-gensymabis", "-o", "symabis", "x.s")
- runGo("tool", "compile", "-symabis", "symabis", "-p=main", "-o", "x1.o", "main.go")
+ runGo("tool", "compile", "-importcfg="+importcfgfile, "-symabis", "symabis", "-p=main", "-o", "x1.o", "main.go")
runGo("tool", "asm", "-p=main", "-o", "x2.o", "x.s")
run(cc, append(cflags, "-c", "-o", "x3.o", "x.c")...)
runGo("tool", "pack", "c", "x.a", "x1.o", "x2.o", "x3.o")
// Now attempt to link using the internal linker.
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "link", "-linkmode=internal", "x.a")
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "link", "-importcfg="+importcfgfile, "-linkmode=internal", "x.a")
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err == nil {
mObj := filepath.Join(tmpdir, "main.o")
exe := filepath.Join(tmpdir, "main.exe")
+ importcfgFile := filepath.Join(tmpdir, "stdlib.importcfg")
+ testenv.WriteImportcfg(t, importcfgFile, nil)
+ importcfgWithAFile := filepath.Join(tmpdir, "witha.importcfg")
+ testenv.WriteImportcfg(t, importcfgWithAFile, map[string]string{"a": aObj})
+
// Build a program with main package importing package a.
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=a", "-o", aObj, aSrc)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-importcfg="+importcfgFile, "-p=a", "-o", aObj, aSrc)
t.Log(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("compiling a.go failed: %v\n%s", err, out)
}
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=main", "-I", tmpdir, "-o", mObj, mSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-importcfg="+importcfgWithAFile, "-p=main", "-I", tmpdir, "-o", mObj, mSrc)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("compiling main.go failed: %v\n%s", err, out)
}
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-L", tmpdir, "-o", exe, mObj)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-importcfg="+importcfgWithAFile, "-L", tmpdir, "-o", exe, mObj)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err != nil {
// Now, overwrite a.o with the object of b.go. This should
// result in an index mismatch.
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=a", "-o", aObj, bSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-importcfg="+importcfgFile, "-p=a", "-o", aObj, bSrc)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("compiling a.go failed: %v\n%s", err, out)
}
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-L", tmpdir, "-o", exe, mObj)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-importcfg="+importcfgWithAFile, "-L", tmpdir, "-o", exe, mObj)
t.Log(cmd)
out, err = cmd.CombinedOutput()
if err == nil {
func TestDisasmGoobj(t *testing.T) {
mustHaveDisasm(t)
+ importcfgfile := filepath.Join(tmp, "hello.importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
hello := filepath.Join(tmp, "hello.o")
- args := []string{"tool", "compile", "-p=main", "-o", hello}
+ args := []string{"tool", "compile", "-p=main", "-importcfg=" + importcfgfile, "-o", hello}
args = append(args, "testdata/fmthello.go")
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
if err != nil {
return doRun(t, dir, args...)
}
+ importcfgfile := filepath.Join(dir, "hello.importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "-p=main", "hello.go")
+ run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=main", "hello.go")
run("./pack", "grc", "hello.a", "hello.o")
- run(goBin, "tool", "link", "-o", "a.out", "hello.a")
+ run(goBin, "tool", "link", "-importcfg="+importcfgfile, "-o", "a.out", "hello.a")
out := run("./a.out")
if out != "hello world\n" {
t.Fatalf("incorrect output: %q, want %q", out, "hello world\n")
return doRun(t, dir, args...)
}
+ importcfgfile := filepath.Join(dir, "hello.importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
goBin := testenv.GoToolPath(t)
run(goBin, "build", "cmd/pack") // writes pack binary to dir
- run(goBin, "tool", "compile", "-p=large", "large.go")
+ run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=large", "large.go")
run("./pack", "grc", "large.a", "large.o")
- run(goBin, "tool", "compile", "-p=main", "-I", ".", "main.go")
- run(goBin, "tool", "link", "-L", ".", "-o", "a.out", "main.o")
+ testenv.WriteImportcfg(t, importcfgfile, map[string]string{"large": filepath.Join(dir, "large.o")})
+ run(goBin, "tool", "compile", "-importcfg="+importcfgfile, "-p=main", "main.go")
+ run(goBin, "tool", "link", "-importcfg="+importcfgfile, "-L", ".", "-o", "a.out", "main.o")
out := run("./a.out")
if out != "ok\n" {
t.Fatalf("incorrect output: %q, want %q", out, "ok\n")
internal/fuzz, internal/testlog, runtime/pprof, regexp
< testing/internal/testdeps;
- OS, flag, testing, internal/cfg, internal/platform
+ OS, flag, testing, internal/cfg, internal/platform, internal/goroot
< internal/testenv;
OS, encoding/base64
testenv.MustHaveGoBuild(t)
const thePackage = "math/big"
- out, err := exec.Command(testenv.GoToolPath(t), "list", "-f={{context.Compiler}}:{{.Target}}", thePackage).CombinedOutput()
+ out, err := exec.Command(testenv.GoToolPath(t), "list", "-export", "-f={{context.Compiler}}:{{.Export}}", thePackage).CombinedOutput()
if err != nil {
t.Fatalf("go list %s: %v\n%s", thePackage, err, out)
}
- target := strings.TrimSpace(string(out))
- compiler, target, _ := strings.Cut(target, ":")
- if !strings.HasSuffix(target, ".a") {
- t.Fatalf("unexpected package %s target %q (not *.a)", thePackage, target)
- }
+ export := strings.TrimSpace(string(out))
+ compiler, target, _ := strings.Cut(export, ":")
if compiler == "gccgo" {
t.Skip("golang.org/issue/22500")
"go/build"
"go/token"
"go/types"
+ "internal/goroot"
"internal/pkgbits"
"io"
"os"
+ "path"
"path/filepath"
"strings"
)
// debugging/development support
const debug = false
-var pkgExts = [...]string{".a", ".o"}
+func lookupGorootExport(pkgpath, srcRoot, srcDir string) (string, bool) {
+ pkgpath = filepath.ToSlash(pkgpath)
+ m, err := goroot.PkgfileMap()
+ if err != nil {
+ return "", false
+ }
+ if export, ok := m[pkgpath]; ok {
+ return export, true
+ }
+ vendorPrefix := "vendor"
+ if strings.HasPrefix(srcDir, filepath.Join(srcRoot, "cmd")) {
+ vendorPrefix = path.Join("cmd", vendorPrefix)
+ }
+ pkgpath = path.Join(vendorPrefix, pkgpath)
+ export, ok := m[pkgpath]
+ return export, ok
+}
+
+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
}
bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" {
- id = path // make sure we have an id to print in error message
- return
+ var ok bool
+ if bp.Goroot {
+ filename, ok = lookupGorootExport(path, bp.SrcRoot, srcDir)
+ }
+ if !ok {
+ id = path // make sure we have an id to print in error message
+ return
+ }
+ } else {
+ noext = strings.TrimSuffix(bp.PkgObj, ".a")
+ id = bp.ImportPath
}
- noext = strings.TrimSuffix(bp.PkgObj, ".a")
- id = bp.ImportPath
case build.IsLocalImport(path):
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
}
}
+ if filename != "" {
+ if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+ return
+ }
+ }
// try extensions
for _, ext := range pkgExts {
filename = noext + ext
"internal/testenv"
"os"
"os/exec"
+ "path"
"path/filepath"
"runtime"
"strings"
// compile runs the compiler on filename, with dirname as the working directory,
// and writes the output file to outdirname.
-func compile(t *testing.T, dirname, filename, outdirname string) string {
+// compile gives the resulting package a packagepath of testdata/<filebasename>.
+func compile(t *testing.T, dirname, filename, outdirname string, packagefiles map[string]string) string {
// filename must end with ".go"
- if !strings.HasSuffix(filename, ".go") {
+ basename, ok := strings.CutSuffix(filepath.Base(filename), ".go")
+ if !ok {
t.Fatalf("filename doesn't end in .go: %s", filename)
}
- basename := filepath.Base(filename)
- outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", strings.TrimSuffix(outname, ".o"), "-o", outname, filename)
+ objname := basename + ".o"
+ outname := filepath.Join(outdirname, objname)
+ importcfgfile := filepath.Join(outdirname, basename) + ".importcfg"
+ testenv.WriteImportcfg(t, importcfgfile, packagefiles)
+ pkgpath := path.Join("testdata", basename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p", pkgpath, "-D", "testdata", "-importcfg", importcfgfile, "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"), nil)
path := "./testdata/" + strings.TrimSuffix(testfile, ".go")
if pkg := testPath(t, path, tmpdir); pkg != nil {
// Compile and import, and compare the resulting package with the package
// that was type-checked directly.
- compile(t, rootDir, entry.Name(), filepath.Join(tmpdir, "testdata"))
+ compile(t, rootDir, entry.Name(), filepath.Join(tmpdir, "testdata"), nil)
pkgName := strings.TrimSuffix(entry.Name(), ".go")
imported := importPkg(t, "./testdata/"+pkgName, tmpdir)
checked := checkFile(t, filename, src)
if err != nil {
t.Fatal(err)
}
- compile(t, "testdata", "a.go", testoutdir)
- compile(t, testoutdir, bpath, testoutdir)
+ compile(t, "testdata", "a.go", testoutdir, nil)
+ compile(t, testoutdir, bpath, testoutdir, map[string]string{"testdata/a": filepath.Join(testoutdir, "a.o")})
// import must succeed (test for issue at hand)
pkg := importPkg(t, "./testdata/b", tmpdir)
defer os.RemoveAll(tmpdir)
testoutdir := filepath.Join(tmpdir, "testdata")
- compile(t, "testdata", "g.go", testoutdir)
+ compile(t, "testdata", "g.go", testoutdir, nil)
// import must succeed (test for issue at hand)
_ = importPkg(t, "./testdata/g", tmpdir)
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"), nil)
// Multiple imports of p must succeed without redeclaration errors.
// We use an import path that's not cleaned up so that the eventual
func compileAndImportPkg(t *testing.T, name string) *types.Package {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
- compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"))
+ compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"), nil)
return importPkg(t, "./testdata/"+name, tmpdir)
}
symabi := filepath.Join(tmpdir, "symabi")
obj := filepath.Join(tmpdir, "x.o")
+ importcfgfile := filepath.Join(tmpdir, "hello.importcfg")
+ testenv.WriteImportcfg(t, importcfgfile, nil)
+
// parse assembly code for symabi.
cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-gensymabis", "-o", symabi, asmSrc)
out, err := cmd.CombinedOutput()
}
// compile go code.
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-p=p", "-symabis", symabi, "-o", obj, goSrc)
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-importcfg="+importcfgfile, "-p=p", "-symabis", symabi, "-o", obj, goSrc)
out, err = cmd.CombinedOutput()
if err == nil {
t.Fatalf("go tool compile did not fail")
const prefix = "libraries: ="
var dirs []string
for _, dirEntry := range dirsEntries {
- if after, found := strings.CutPrefix(dirEntry, prefix); found {
- dirs = filepath.SplitList(after)
+ if strings.HasPrefix(dirEntry, prefix) {
+ dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
break
}
}
--- /dev/null
+// Copyright 2022 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 goroot
+
+import (
+ "bytes"
+ "fmt"
+ "os/exec"
+ "strings"
+ "sync"
+)
+
+// Importcfg returns an importcfg file to be passed to the
+// Go compiler that contains the cached paths for the .a files for the
+// standard library.
+func Importcfg() (string, error) {
+ var icfg bytes.Buffer
+
+ m, err := PkgfileMap()
+ if err != nil {
+ return "", err
+ }
+ fmt.Fprintf(&icfg, "# import config")
+ for importPath, export := range m {
+ if importPath != "unsafe" && export != "" { // unsafe
+ fmt.Fprintf(&icfg, "\npackagefile %s=%s", importPath, export)
+ }
+ }
+ s := icfg.String()
+ return s, nil
+}
+
+var (
+ stdlibPkgfileMap map[string]string
+ stdlibPkgfileErr error
+ once sync.Once
+)
+
+// PkgfileMap returns a map of package paths to the location on disk
+// of the .a file for the package.
+// The caller must not modify the map.
+func PkgfileMap() (map[string]string, error) {
+ once.Do(func() {
+ m := make(map[string]string)
+ output, err := exec.Command("go", "list", "-export", "-e", "-f", "{{.ImportPath}} {{.Export}}", "std", "cmd").Output()
+ if err != nil {
+ stdlibPkgfileErr = err
+ }
+ for _, line := range strings.Split(string(output), "\n") {
+ if line == "" {
+ continue
+ }
+ sp := strings.SplitN(line, " ", 2)
+ if len(sp) != 2 {
+ err = fmt.Errorf("determining pkgfile map: invalid line in go list output: %q", line)
+ return
+ }
+ importPath, export := sp[0], sp[1]
+ m[importPath] = export
+ }
+ stdlibPkgfileMap = m
+ })
+ return stdlibPkgfileMap, stdlibPkgfileErr
+}
"flag"
"fmt"
"internal/cfg"
+ "internal/goroot"
"internal/platform"
"os"
"os/exec"
return b.Bytes(), err
}
+
+// WriteImportcfg writes an importcfg file used by the compiler or linker to
+// dstPath containing entries for the packages in std and cmd in addition
+// to the package to package file mappings in additionalPackageFiles.
+func WriteImportcfg(t testing.TB, dstPath string, additionalPackageFiles map[string]string) {
+ importcfg, err := goroot.Importcfg()
+ for k, v := range additionalPackageFiles {
+ importcfg += fmt.Sprintf("\npackagefile %s=%s", k, v)
+ }
+ if err != nil {
+ t.Fatalf("preparing the importcfg failed: %s", err)
+ }
+ os.WriteFile(dstPath, []byte(importcfg), 0655)
+ if err != nil {
+ t.Fatalf("writing the importcfg failed: %s", err)
+ }
+}
"go/importer"
"go/parser"
"go/token"
+ "internal/testenv"
"reflect"
"strings"
"testing"
)
func TestErrorCodeExamples(t *testing.T) {
+ testenv.MustHaveGoBuild(t) // go command needed to resolve std .a files for importer.Default().
+
walkCodes(t, func(name string, value int, spec *ast.ValueSpec) {
t.Run(name, func(t *testing.T) {
doc := spec.Doc.Text()
"go/printer"
"go/token"
"go/types"
+ "internal/testenv"
"os"
"regexp"
"runtime"
// Check that 64-bit fields on which we apply atomic operations
// are aligned to 8 bytes. This can be a problem on 32-bit systems.
func TestAtomicAlignment(t *testing.T) {
+ testenv.MustHaveGoBuild(t) // go command needed to resolve std .a files for importer.Default().
+
// Read the code making the tables above, to see which fields and
// variables we are currently checking.
checked := map[string]bool{}