mirror of https://github.com/golang/go.git
cmd/go: add go list -cgo and -export
We want package analysis tools to be able to ask cmd/go for cgo-translated files and for the names of files holding export type information, instead of reinventing that logic themselves. Allow them to do so, with the new list -cgo and -export flags. Change-Id: I860df530d8dcc130f1f328413381b5664cc81c3b Reviewed-on: https://go-review.googlesource.com/108156 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
5f2b4f26aa
commit
baf399b02e
|
|
@ -579,7 +579,7 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// go list [-deps] [-e] [-f format] [-json] [-test] [build flags] [packages]
|
||||
// go list [-cgo] [-deps] [-e] [-f format] [-json] [-list] [-test] [build flags] [packages]
|
||||
//
|
||||
// List lists the packages named by the import paths, one per line.
|
||||
//
|
||||
|
|
@ -609,6 +609,9 @@
|
|||
// Root string // Go root or Go path dir containing this package
|
||||
// ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
// BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
// ForTest string // package is only for use in named test
|
||||
// DepOnly bool // package is only a dependency, not explicitly listed
|
||||
// Export string // file containing export data (when using -export)
|
||||
//
|
||||
// // Source files
|
||||
// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
|
|
@ -683,9 +686,15 @@
|
|||
// The -json flag causes the package data to be printed in JSON format
|
||||
// instead of using the template format.
|
||||
//
|
||||
// The -cgo flag causes list to set CgoFiles not to the original *.go files
|
||||
// importing "C" but instead to the translated files generated by the cgo
|
||||
// command.
|
||||
//
|
||||
// The -deps flag causes list to iterate over not just the named packages
|
||||
// but also all their dependencies. It visits them in a depth-first post-order
|
||||
// traversal, so that a package is listed only after all its dependencies.
|
||||
// Packages not explicitly listed on the command line will have the DepOnly
|
||||
// field set to true.
|
||||
//
|
||||
// The -e flag changes the handling of erroneous packages, those that
|
||||
// cannot be found or are malformed. By default, the list command
|
||||
|
|
@ -697,6 +706,10 @@
|
|||
// a non-nil Error field; other information may or may not be missing
|
||||
// (zeroed).
|
||||
//
|
||||
// The -export flag causes list to set the package's Export field to
|
||||
// the name of a file containing up-to-date export information for
|
||||
// the given package.
|
||||
//
|
||||
// The -test flag causes list to report not only the named packages
|
||||
// but also their test binaries (for packages with tests), to convey to
|
||||
// source code analysis tools exactly how test binaries are constructed.
|
||||
|
|
@ -707,7 +720,18 @@
|
|||
// package itself). The reported import path of a package recompiled
|
||||
// for a particular test binary is followed by a space and the name of
|
||||
// the test binary in brackets, as in "math/rand [math/rand.test]"
|
||||
// or "regexp [sort.test]".
|
||||
// or "regexp [sort.test]". The ForTest field is also set to the name
|
||||
// of the package being tested ("math/rand" or "sort" in the previous
|
||||
// examples).
|
||||
//
|
||||
// The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
|
||||
// are all absolute paths.
|
||||
//
|
||||
// By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
|
||||
// (that is, paths relative to Dir, not absolute paths).
|
||||
// The extra entries added by the -cgo and -test flags are absolute paths
|
||||
// referring to cached copies of generated Go source files.
|
||||
// Although they are Go source files, the paths may not end in ".go".
|
||||
//
|
||||
// For more about build flags, see 'go help build'.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1977,6 +1977,55 @@ func TestGoListTest(t *testing.T) {
|
|||
tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
|
||||
}
|
||||
|
||||
func TestGoListCgo(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOCACHE", tg.tempdir)
|
||||
|
||||
tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
|
||||
if tg.stdout.String() == "" {
|
||||
t.Skip("net does not use cgo")
|
||||
}
|
||||
if strings.Contains(tg.stdout.String(), tg.tempdir) {
|
||||
t.Fatalf(".CgoFiles without -cgo unexpectedly mentioned cache %s", tg.tempdir)
|
||||
}
|
||||
tg.run("list", "-cgo", "-f", `{{join .CgoFiles "\n"}}`, "net")
|
||||
if !strings.Contains(tg.stdout.String(), tg.tempdir) {
|
||||
t.Fatalf(".CgoFiles with -cgo did not mention cache %s", tg.tempdir)
|
||||
}
|
||||
for _, file := range strings.Split(tg.stdout.String(), "\n") {
|
||||
if file == "" {
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
t.Fatalf("cannot find .CgoFiles result %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoListExport(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOCACHE", tg.tempdir)
|
||||
|
||||
tg.run("list", "-f", "{{.Export}}", "strings")
|
||||
if tg.stdout.String() != "" {
|
||||
t.Fatalf(".Export without -export unexpectedly set")
|
||||
}
|
||||
tg.run("list", "-export", "-f", "{{.Export}}", "strings")
|
||||
file := strings.TrimSpace(tg.stdout.String())
|
||||
if file == "" {
|
||||
t.Fatalf(".Export with -export was empty")
|
||||
}
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
t.Fatalf("cannot find .Export result %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 4096. Validate the output of unsuccessful go install foo/quxx.
|
||||
func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
)
|
||||
|
||||
var CmdList = &base.Command{
|
||||
UsageLine: "list [-deps] [-e] [-f format] [-json] [-test] [build flags] [packages]",
|
||||
UsageLine: "list [-cgo] [-deps] [-e] [-f format] [-json] [-list] [-test] [build flags] [packages]",
|
||||
Short: "list packages",
|
||||
Long: `
|
||||
List lists the packages named by the import paths, one per line.
|
||||
|
|
@ -54,6 +54,9 @@ syntax of package template. The default output is equivalent to -f
|
|||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
ForTest string // package is only for use in named test
|
||||
DepOnly bool // package is only a dependency, not explicitly listed
|
||||
Export string // file containing export data (when using -export)
|
||||
|
||||
// Source files
|
||||
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
|
|
@ -128,9 +131,15 @@ for the go/build package's Context type.
|
|||
The -json flag causes the package data to be printed in JSON format
|
||||
instead of using the template format.
|
||||
|
||||
The -cgo flag causes list to set CgoFiles not to the original *.go files
|
||||
importing "C" but instead to the translated files generated by the cgo
|
||||
command.
|
||||
|
||||
The -deps flag causes list to iterate over not just the named packages
|
||||
but also all their dependencies. It visits them in a depth-first post-order
|
||||
traversal, so that a package is listed only after all its dependencies.
|
||||
Packages not explicitly listed on the command line will have the DepOnly
|
||||
field set to true.
|
||||
|
||||
The -e flag changes the handling of erroneous packages, those that
|
||||
cannot be found or are malformed. By default, the list command
|
||||
|
|
@ -142,6 +151,10 @@ printing. Erroneous packages will have a non-empty ImportPath and
|
|||
a non-nil Error field; other information may or may not be missing
|
||||
(zeroed).
|
||||
|
||||
The -export flag causes list to set the package's Export field to
|
||||
the name of a file containing up-to-date export information for
|
||||
the given package.
|
||||
|
||||
The -test flag causes list to report not only the named packages
|
||||
but also their test binaries (for packages with tests), to convey to
|
||||
source code analysis tools exactly how test binaries are constructed.
|
||||
|
|
@ -152,7 +165,18 @@ dependencies specially for that test (most commonly the tested
|
|||
package itself). The reported import path of a package recompiled
|
||||
for a particular test binary is followed by a space and the name of
|
||||
the test binary in brackets, as in "math/rand [math/rand.test]"
|
||||
or "regexp [sort.test]".
|
||||
or "regexp [sort.test]". The ForTest field is also set to the name
|
||||
of the package being tested ("math/rand" or "sort" in the previous
|
||||
examples).
|
||||
|
||||
The Dir, Target, Shlib, Root, ConflictDir, and Export file paths
|
||||
are all absolute paths.
|
||||
|
||||
By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir
|
||||
(that is, paths relative to Dir, not absolute paths).
|
||||
The extra entries added by the -cgo and -test flags are absolute paths
|
||||
referring to cached copies of generated Go source files.
|
||||
Although they are Go source files, the paths may not end in ".go".
|
||||
|
||||
For more about build flags, see 'go help build'.
|
||||
|
||||
|
|
@ -165,8 +189,10 @@ func init() {
|
|||
work.AddBuildFlags(CmdList)
|
||||
}
|
||||
|
||||
var listCgo = CmdList.Flag.Bool("cgo", false, "")
|
||||
var listDeps = CmdList.Flag.Bool("deps", false, "")
|
||||
var listE = CmdList.Flag.Bool("e", false, "")
|
||||
var listExport = CmdList.Flag.Bool("export", false, "")
|
||||
var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "")
|
||||
var listJson = CmdList.Flag.Bool("json", false, "")
|
||||
var listTest = CmdList.Flag.Bool("test", false, "")
|
||||
|
|
@ -222,11 +248,22 @@ func runList(cmd *base.Command, args []string) {
|
|||
pkgs = load.Packages(args)
|
||||
}
|
||||
|
||||
if *listTest {
|
||||
c := cache.Default()
|
||||
if c == nil {
|
||||
if cache.Default() == nil {
|
||||
// These flags return file names pointing into the build cache,
|
||||
// so the build cache must exist.
|
||||
if *listCgo {
|
||||
base.Fatalf("go list -cgo requires build cache")
|
||||
}
|
||||
if *listExport {
|
||||
base.Fatalf("go list -export requires build cache")
|
||||
}
|
||||
if *listTest {
|
||||
base.Fatalf("go list -test requires build cache")
|
||||
}
|
||||
}
|
||||
|
||||
if *listTest {
|
||||
c := cache.Default()
|
||||
// Add test binaries to packages to be listed.
|
||||
for _, p := range pkgs {
|
||||
if p.Error != nil {
|
||||
|
|
@ -279,13 +316,14 @@ func runList(cmd *base.Command, args []string) {
|
|||
pkgs = load.PackageList(pkgs)
|
||||
}
|
||||
|
||||
// Estimate whether staleness information is needed,
|
||||
// since it's a little bit of work to compute.
|
||||
// Do we need to run a build to gather information?
|
||||
needStale := *listJson || strings.Contains(*listFmt, ".Stale")
|
||||
if needStale {
|
||||
if needStale || *listExport || *listCgo {
|
||||
var b work.Builder
|
||||
b.Init()
|
||||
b.ComputeStaleOnly = true
|
||||
b.IsCmdList = true
|
||||
b.NeedExport = *listExport
|
||||
b.NeedCgoFiles = *listCgo
|
||||
a := &work.Action{}
|
||||
// TODO: Use pkgsFilter?
|
||||
for _, p := range pkgs {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ type PackagePublic struct {
|
|||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
ForTest string `json:",omitempty"` // package is only for use in named test
|
||||
DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed
|
||||
Export string `json:",omitempty"` // file containing export data (set by go list -export)
|
||||
|
||||
// Stale and StaleReason remain here *only* for the list command.
|
||||
// They are only initialized in preparation for list execution.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ type Builder struct {
|
|||
flagCache map[[2]string]bool // a cache of supported compiler flags
|
||||
Print func(args ...interface{}) (int, error)
|
||||
|
||||
ComputeStaleOnly bool // compute staleness for go list; no actual build
|
||||
IsCmdList bool // running as part of go list; set p.Stale and additional fields below
|
||||
NeedError bool // list needs p.Error
|
||||
NeedExport bool // list needs p.Export
|
||||
NeedCgoFiles bool // list needs p.CgoFiles to cgo-generated files, not originals
|
||||
|
||||
objdirSeq int // counter for NewObjdir
|
||||
pkgSeq int
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
|
|||
// already up-to-date, then to avoid a rebuild, report the package
|
||||
// as up-to-date as well. See "Build IDs" comment above.
|
||||
// TODO(rsc): Rewrite this code to use a TryCache func on the link action.
|
||||
if target != "" && !cfg.BuildA && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" {
|
||||
if target != "" && !cfg.BuildA && !b.NeedExport && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" {
|
||||
buildID, err := buildid.ReadFile(target)
|
||||
if err == nil {
|
||||
id := strings.Split(buildID, buildIDSeparator)
|
||||
|
|
@ -455,8 +455,8 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
|
|||
return true
|
||||
}
|
||||
|
||||
if b.ComputeStaleOnly {
|
||||
// Invoked during go list only to compute and record staleness.
|
||||
if b.IsCmdList {
|
||||
// Invoked during go list to compute and record staleness.
|
||||
if p := a.Package; p != nil && !p.Stale {
|
||||
p.Stale = true
|
||||
if cfg.BuildA {
|
||||
|
|
@ -521,10 +521,6 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
|
|||
a.output = []byte{}
|
||||
}
|
||||
|
||||
if b.ComputeStaleOnly {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -609,11 +605,17 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
|
|||
panic("internal error: a.output not set")
|
||||
}
|
||||
outputID, _, err := c.Put(a.actionID, r)
|
||||
r.Close()
|
||||
if err == nil && cfg.BuildX {
|
||||
b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, c.OutputFile(outputID))))
|
||||
}
|
||||
if b.NeedExport {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Package.Export = c.OutputFile(outputID)
|
||||
}
|
||||
c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output)
|
||||
r.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ func actionList(root *Action) []*Action {
|
|||
|
||||
// do runs the action graph rooted at root.
|
||||
func (b *Builder) Do(root *Action) {
|
||||
if c := cache.Default(); c != nil && !b.ComputeStaleOnly {
|
||||
if c := cache.Default(); c != nil && !b.IsCmdList {
|
||||
// If we're doing real work, take time at the end to trim the cache.
|
||||
defer c.Trim()
|
||||
}
|
||||
|
|
@ -296,11 +296,11 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
|
|||
return h.Sum()
|
||||
}
|
||||
|
||||
// needCgoHeader reports whether the actions triggered by this one
|
||||
// needCgoHdr reports whether the actions triggered by this one
|
||||
// expect to be able to access the cgo-generated header file.
|
||||
func needCgoHeader(a *Action) bool {
|
||||
func (b *Builder) needCgoHdr(a *Action) bool {
|
||||
// If this build triggers a header install, run cgo to get the header.
|
||||
if (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
|
||||
if !b.IsCmdList && (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
|
||||
for _, t1 := range a.triggers {
|
||||
if t1.Mode == "install header" {
|
||||
return true
|
||||
|
|
@ -317,19 +317,54 @@ func needCgoHeader(a *Action) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
needBuild uint32 = 1 << iota
|
||||
needCgoHdr
|
||||
needVet
|
||||
needCgoFiles
|
||||
needStale
|
||||
)
|
||||
|
||||
// build is the action for building a single package.
|
||||
// Note that any new influence on this logic must be reported in b.buildActionID above as well.
|
||||
func (b *Builder) build(a *Action) (err error) {
|
||||
p := a.Package
|
||||
|
||||
bit := func(x uint32, b bool) uint32 {
|
||||
if b {
|
||||
return x
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
cached := false
|
||||
needCgo := needCgoHeader(a)
|
||||
need := bit(needBuild, !b.IsCmdList || b.NeedExport) |
|
||||
bit(needCgoHdr, b.needCgoHdr(a)) |
|
||||
bit(needVet, a.needVet) |
|
||||
bit(needCgoFiles, b.NeedCgoFiles && (p.UsesCgo() || p.UsesSwig()))
|
||||
|
||||
// Save p.CgoFiles now, because we may modify it for go list.
|
||||
cgofiles := append([]string{}, p.CgoFiles...)
|
||||
|
||||
if !p.BinaryOnly {
|
||||
if b.useCache(a, p, b.buildActionID(a), p.Target) {
|
||||
if b.ComputeStaleOnly || !needCgo && !a.needVet {
|
||||
return nil
|
||||
// We found the main output in the cache.
|
||||
// If we don't need any other outputs, we can stop.
|
||||
need &^= needBuild
|
||||
if b.NeedExport {
|
||||
p.Export = a.built
|
||||
}
|
||||
if need&needCgoFiles != 0 && b.loadCachedCgoFiles(a) {
|
||||
need &^= needCgoFiles
|
||||
}
|
||||
// Otherwise, we need to write files to a.Objdir (needVet, needCgoHdr).
|
||||
// Remember that we might have them in cache
|
||||
// and check again after we create a.Objdir.
|
||||
cached = true
|
||||
a.output = []byte{} // start saving output in case we miss any cache results
|
||||
}
|
||||
if need == 0 {
|
||||
return nil
|
||||
}
|
||||
defer b.flushOutput(a)
|
||||
}
|
||||
|
|
@ -338,6 +373,9 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
if err != nil && err != errPrintedOutput {
|
||||
err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err)
|
||||
}
|
||||
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
|
||||
p.Error = &load.PackageError{Err: err.Error()}
|
||||
}
|
||||
}()
|
||||
if cfg.BuildN {
|
||||
// In -n mode, print a banner between packages.
|
||||
|
|
@ -357,16 +395,16 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
if err == nil {
|
||||
a.built = a.Package.Target
|
||||
a.Target = a.Package.Target
|
||||
if b.NeedExport {
|
||||
a.Package.Export = a.Package.Target
|
||||
}
|
||||
a.buildID = b.fileHash(a.Package.Target)
|
||||
a.Package.Stale = false
|
||||
a.Package.StaleReason = "binary-only package"
|
||||
return nil
|
||||
}
|
||||
if b.ComputeStaleOnly {
|
||||
a.Package.Stale = true
|
||||
a.Package.StaleReason = "missing or invalid binary-only package"
|
||||
return nil
|
||||
}
|
||||
a.Package.Stale = true
|
||||
a.Package.StaleReason = "missing or invalid binary-only package"
|
||||
return fmt.Errorf("missing or invalid binary-only package")
|
||||
}
|
||||
|
||||
|
|
@ -375,8 +413,21 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
}
|
||||
objdir := a.Objdir
|
||||
|
||||
if cached && (!needCgo || b.loadCachedCgo(a)) && (!a.needVet || b.loadCachedVet(a)) {
|
||||
return nil
|
||||
if cached {
|
||||
if need&needCgoHdr != 0 && b.loadCachedCgoHdr(a) {
|
||||
need &^= needCgoHdr
|
||||
}
|
||||
|
||||
// Load cached vet config, but only if that's all we have left
|
||||
// (need == needVet, not testing just the one bit).
|
||||
// If we are going to do a full build anyway,
|
||||
// we're going to regenerate the files below anyway.
|
||||
if need == needVet && b.loadCachedVet(a) {
|
||||
need &^= needVet
|
||||
}
|
||||
if need == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// make target directory
|
||||
|
|
@ -387,9 +438,8 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
var gofiles, cgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
|
||||
var gofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
|
||||
gofiles = append(gofiles, a.Package.GoFiles...)
|
||||
cgofiles = append(cgofiles, a.Package.CgoFiles...)
|
||||
cfiles = append(cfiles, a.Package.CFiles...)
|
||||
sfiles = append(sfiles, a.Package.SFiles...)
|
||||
cxxfiles = append(cxxfiles, a.Package.CXXFiles...)
|
||||
|
|
@ -500,19 +550,27 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
}
|
||||
b.cacheGofiles(a, gofiles)
|
||||
|
||||
// Running cgo generated the cgo header.
|
||||
need &^= needCgoHdr
|
||||
|
||||
// Sanity check only, since Package.load already checked as well.
|
||||
if len(gofiles) == 0 {
|
||||
return &load.NoGoError{Package: a.Package}
|
||||
}
|
||||
|
||||
// Prepare Go vet config if needed.
|
||||
if a.needVet {
|
||||
if need&needVet != 0 {
|
||||
buildVetConfig(a, gofiles)
|
||||
need &^= needVet
|
||||
}
|
||||
if cached {
|
||||
// The cached package file is OK, so we don't need to run the compile.
|
||||
// We've only gone this far in order to prepare the vet configuration
|
||||
// or cgo header, and now we have.
|
||||
if need&needCgoFiles != 0 {
|
||||
if !b.loadCachedCgoFiles(a) {
|
||||
return fmt.Errorf("failed to cache translated CgoFiles")
|
||||
}
|
||||
need &^= needCgoFiles
|
||||
}
|
||||
if need == 0 {
|
||||
// Nothing left to do.
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -656,17 +714,25 @@ func (b *Builder) cacheObjdirFile(a *Action, c *cache.Cache, name string) error
|
|||
return err
|
||||
}
|
||||
|
||||
func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error {
|
||||
func (b *Builder) findCachedObjdirFile(a *Action, c *cache.Cache, name string) (string, error) {
|
||||
entry, err := c.Get(cache.Subkey(a.actionID, name))
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
out := c.OutputFile(entry.OutputID)
|
||||
info, err := os.Stat(out)
|
||||
if err != nil || info.Size() != entry.Size {
|
||||
return fmt.Errorf("not in cache")
|
||||
return "", fmt.Errorf("not in cache")
|
||||
}
|
||||
return b.copyFile(a.Objdir+name, out, 0666, true)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error {
|
||||
cached, err := b.findCachedObjdirFile(a, c, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.copyFile(a.Objdir+name, cached, 0666, true)
|
||||
}
|
||||
|
||||
func (b *Builder) cacheCgoHdr(a *Action) {
|
||||
|
|
@ -677,7 +743,7 @@ func (b *Builder) cacheCgoHdr(a *Action) {
|
|||
b.cacheObjdirFile(a, c, "_cgo_install.h")
|
||||
}
|
||||
|
||||
func (b *Builder) loadCachedCgo(a *Action) bool {
|
||||
func (b *Builder) loadCachedCgoHdr(a *Action) bool {
|
||||
c := cache.Default()
|
||||
if c == nil {
|
||||
return false
|
||||
|
|
@ -737,6 +803,33 @@ func (b *Builder) loadCachedVet(a *Action) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (b *Builder) loadCachedCgoFiles(a *Action) bool {
|
||||
c := cache.Default()
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
list, _, err := c.GetBytes(cache.Subkey(a.actionID, "gofiles"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var files []string
|
||||
for _, name := range strings.Split(string(list), "\n") {
|
||||
if name == "" { // end of list
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(name, "./") {
|
||||
continue
|
||||
}
|
||||
file, err := b.findCachedObjdirFile(a, c, name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
files = append(files, file)
|
||||
}
|
||||
a.Package.CgoFiles = files
|
||||
return true
|
||||
}
|
||||
|
||||
type vetConfig struct {
|
||||
Compiler string
|
||||
Dir string
|
||||
|
|
@ -939,7 +1032,7 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
|
|||
// link is the action for linking a single command.
|
||||
// Note that any new influence on this logic must be reported in b.linkActionID above as well.
|
||||
func (b *Builder) link(a *Action) (err error) {
|
||||
if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) {
|
||||
if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) || b.IsCmdList {
|
||||
return nil
|
||||
}
|
||||
defer b.flushOutput(a)
|
||||
|
|
@ -1172,7 +1265,7 @@ func (b *Builder) linkSharedActionID(a *Action) cache.ActionID {
|
|||
}
|
||||
|
||||
func (b *Builder) linkShared(a *Action) (err error) {
|
||||
if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) {
|
||||
if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) || b.IsCmdList {
|
||||
return nil
|
||||
}
|
||||
defer b.flushOutput(a)
|
||||
|
|
@ -1236,13 +1329,17 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
|
|||
// We want to hide that awful detail as much as possible, so don't
|
||||
// advertise it by touching the mtimes (usually the libraries are up
|
||||
// to date).
|
||||
if !a.buggyInstall && !b.ComputeStaleOnly {
|
||||
if !a.buggyInstall && !b.IsCmdList {
|
||||
now := time.Now()
|
||||
os.Chtimes(a.Target, now, now)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if b.ComputeStaleOnly {
|
||||
|
||||
// If we're building for go list -export,
|
||||
// never install anything; just keep the cache reference.
|
||||
if b.IsCmdList {
|
||||
a.built = a1.built
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue