]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: fix linker arguments
authorRuss Cox <rsc@golang.org>
Thu, 12 Jan 2012 18:18:03 +0000 (10:18 -0800)
committerRuss Cox <rsc@golang.org>
Thu, 12 Jan 2012 18:18:03 +0000 (10:18 -0800)
Especially affects tests, but not test-specific.
The linker was only being told where to find the
direct dependencies of package main.  Sometimes that
was sufficient to find the rest; sometimes not.

Fixes #2657.
Fixes #2666.
Fixes #2680.

R=golang-dev, adg, rogpeppe
CC=golang-dev
https://golang.org/cl/5528079

src/cmd/go/build.go
src/cmd/go/pkg.go

index 2abc944ef8691d999071c9b028863facd5868621..02e2172b96838e09f74c1a934615c2b5d21d21d7 100644 (file)
@@ -483,7 +483,7 @@ func (b *builder) build(a *action) error {
                fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
        }
 
-       // make build directory
+       // Make build directory.
        obj := a.objdir
        if err := b.mkdir(obj); err != nil {
                return err
@@ -494,7 +494,7 @@ func (b *builder) build(a *action) error {
        cfiles = append(cfiles, a.p.CFiles...)
        sfiles = append(sfiles, a.p.SFiles...)
 
-       // run cgo
+       // Run cgo.
        if len(a.p.CgoFiles) > 0 {
                // In a package using cgo, cgo compiles the C and assembly files with gcc.  
                // There is one exception: runtime/cgo's job is to bridge the
@@ -528,34 +528,10 @@ func (b *builder) build(a *action) error {
                gofiles = append(gofiles, outGo...)
        }
 
-       // prepare Go import path list
-       inc := []string{}
-       incMap := map[string]bool{}
-
-       incMap[b.work] = true                 // handled later
-       incMap[build.Path[0].PkgDir()] = true // goroot
-       incMap[""] = true                     // ignore empty strings
-
-       // temporary build package directories of dependencies.
-       for _, a1 := range a.deps {
-               if pkgdir := a1.pkgdir; pkgdir != a1.p.t.PkgDir() && !incMap[pkgdir] {
-                       incMap[pkgdir] = true
-                       inc = append(inc, "-I", pkgdir)
-               }
-       }
+       // Prepare Go import path list.
+       inc := b.includeArgs("-I", a.deps)
 
-       // work directory
-       inc = append(inc, "-I", b.work)
-
-       // then installed package directories of dependencies
-       for _, a1 := range a.deps {
-               if pkgdir := a1.p.t.PkgDir(); pkgdir == a1.pkgdir && !incMap[pkgdir] {
-                       incMap[pkgdir] = true
-                       inc = append(inc, "-I", pkgdir)
-               }
-       }
-
-       // compile Go
+       // Compile Go.
        if len(gofiles) > 0 {
                out := "_go_." + b.arch
                gcargs := []string{"-p", a.p.ImportPath}
@@ -570,7 +546,7 @@ func (b *builder) build(a *action) error {
                objects = append(objects, out)
        }
 
-       // copy .h files named for goos or goarch or goos_goarch
+       // Copy .h files named for goos or goarch or goos_goarch
        // to names using GOOS and GOARCH.
        // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
        _goos_goarch := "_" + b.goos + "_" + b.goarch + ".h"
@@ -604,7 +580,7 @@ func (b *builder) build(a *action) error {
                objects = append(objects, out)
        }
 
-       // assemble .s files
+       // Assemble .s files.
        for _, file := range sfiles {
                out := file[:len(file)-len(".s")] + "." + b.arch
                if err := b.asm(a.p, obj, obj+out, file); err != nil {
@@ -619,19 +595,18 @@ func (b *builder) build(a *action) error {
        // http://golang.org/issue/2601
        objects = append(objects, cgoObjects...)
 
-       // pack into archive in obj directory
+       // Pack into archive in obj directory
        if err := b.gopack(a.p, obj, a.objpkg, objects); err != nil {
                return err
        }
 
-       // link if needed.
+       // Link if needed.
        if a.link {
-               // command.
-               // import paths for compiler are introduced by -I.
-               // for linker, they are introduced by -L.
-               for i := 0; i < len(inc); i += 2 {
-                       inc[i] = "-L"
-               }
+               // The compiler only cares about direct imports, but the
+               // linker needs the whole dependency tree.
+               all := actionList(a)
+               all = all[:len(all)-1] // drop a
+               inc := b.includeArgs("-L", all)
                if err := b.ld(a.p, a.target, inc, a.objpkg); err != nil {
                        return err
                }
@@ -659,6 +634,41 @@ func (b *builder) install(a *action) error {
        return b.copyFile(a.target, a1.target, perm)
 }
 
+// includeArgs returns the -I or -L directory list for access
+// to the results of the list of actions.
+func (b *builder) includeArgs(flag string, all []*action) []string {
+       inc := []string{}
+       incMap := map[string]bool{
+               b.work:                 true, // handled later
+               build.Path[0].PkgDir(): true, // goroot
+               "":                     true, // ignore empty strings
+       }
+
+       // Look in the temporary space for results of test-specific actions.
+       // This is the $WORK/my/package/_test directory for the
+       // package being built, so there are few of these.
+       for _, a1 := range all {
+               if dir := a1.pkgdir; dir != a1.p.t.PkgDir() && !incMap[dir] {
+                       incMap[dir] = true
+                       inc = append(inc, flag, dir)
+               }
+       }
+
+       // Also look in $WORK for any non-test packages that have
+       // been built but not installed.
+       inc = append(inc, flag, b.work)
+
+       // Finally, look in the installed package directories for each action.
+       for _, a1 := range all {
+               if dir := a1.pkgdir; dir == a1.p.t.PkgDir() && !incMap[dir] {
+                       incMap[dir] = true
+                       inc = append(inc, flag, dir)
+               }
+       }
+
+       return inc
+}
+
 // removeByRenaming removes file name by moving it to a tmp
 // directory and deleting the target if possible.
 func removeByRenaming(name string) error {
index 02a7d5b216856b3d500ca470574a177eba7f725e..33bbc6d9fe3616d537c593f8e679d5ed28a16e44 100644 (file)
@@ -48,6 +48,7 @@ type Package struct {
        pkgdir  string
        info    *build.DirInfo
        imports []*Package
+       deps    []*Package
        gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
        target  string   // installed file for this package (may be executable)
        fake    bool     // synthesized package
@@ -244,6 +245,9 @@ Stale:
                p.Deps = append(p.Deps, dep)
        }
        sort.Strings(p.Deps)
+       for _, dep := range p.Deps {
+               p.deps = append(p.deps, packageCache[dep])
+       }
 
        // unsafe is a fake package and is never out-of-date.
        if p.Standard && p.ImportPath == "unsafe" {