Commit 725f084b authored by Russ Cox's avatar Russ Cox

cmd/go: fix linker arguments

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
parent a03c519a
......@@ -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 {
......
......@@ -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" {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment