Commit 0be2d52e authored by Russ Cox's avatar Russ Cox

cmd/go: use -importcfg to invoke compiler, linker

This is a step toward using cached build artifacts: the importcfg
will direct the compiler and linker to read them right from the cache
if necessary. However, this CL does not have a cache yet, so it still
reads them from the usual install location or build location.
Even so, this fixes a long-standing issue that -I and -L (no longer used)
are not expressive enough to describe complex GOPATH setups.

Shared libraries are handled enough that all.bash passes, but
there may still be more work to do here. If so, tests and fixes
can be added in follow-up CLs.

Gccgo will need updating to support -importcfg as well.

Fixes #14271.

Change-Id: I5c52a0a5df0ffbf7436e1130c74e9e24fceff80f
Reviewed-on: https://go-review.googlesource.com/56279
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent a2993456
...@@ -47,7 +47,7 @@ func run(t *testing.T, msg string, args ...string) { ...@@ -47,7 +47,7 @@ func run(t *testing.T, msg string, args ...string) {
func goCmd(t *testing.T, args ...string) { func goCmd(t *testing.T, args ...string) {
newargs := []string{args[0], "-installsuffix=" + suffix} newargs := []string{args[0], "-installsuffix=" + suffix}
if testing.Verbose() { if testing.Verbose() {
newargs = append(newargs, "-v") newargs = append(newargs, "-x")
} }
newargs = append(newargs, args[1:]...) newargs = append(newargs, args[1:]...)
c := exec.Command("go", newargs...) c := exec.Command("go", newargs...)
...@@ -58,6 +58,7 @@ func goCmd(t *testing.T, args ...string) { ...@@ -58,6 +58,7 @@ func goCmd(t *testing.T, args ...string) {
c.Stdout = os.Stdout c.Stdout = os.Stdout
c.Stderr = os.Stderr c.Stderr = os.Stderr
err = c.Run() err = c.Run()
output = []byte("(output above)")
} else { } else {
output, err = c.CombinedOutput() output, err = c.CombinedOutput()
} }
......
...@@ -128,3 +128,28 @@ func isGOROOT(path string) bool { ...@@ -128,3 +128,28 @@ func isGOROOT(path string) bool {
} }
return stat.IsDir() return stat.IsDir()
} }
// ExternalLinkingForced reports whether external linking is being
// forced even for programs that do not use cgo.
func ExternalLinkingForced() bool {
if !BuildContext.CgoEnabled {
return false
}
// Currently build modes c-shared, pie (on systems that do not
// support PIE with internal linking mode (currently all
// systems: issue #18968)), plugin, and -linkshared force
// external linking mode, as of course does
// -ldflags=-linkmode=external. External linking mode forces
// an import of runtime/cgo.
pieCgo := BuildBuildmode == "pie"
linkmodeExternal := false
for i, a := range BuildLdflags {
if a == "-linkmode=external" {
linkmodeExternal = true
}
if a == "-linkmode" && i+1 < len(BuildLdflags) && BuildLdflags[i+1] == "external" {
linkmodeExternal = true
}
}
return BuildBuildmode == "c-shared" || BuildBuildmode == "plugin" || pieCgo || BuildLinkshared || linkmodeExternal
}
...@@ -99,6 +99,7 @@ type PackageInternal struct { ...@@ -99,6 +99,7 @@ type PackageInternal struct {
SFiles []string SFiles []string
AllGoFiles []string // gofiles + IgnoredGoFiles, absolute paths AllGoFiles []string // gofiles + IgnoredGoFiles, absolute paths
Target string // installed file for this package (may be executable) Target string // installed file for this package (may be executable)
Pkgfile string // where package will be (or is already) built or installed
Fake bool // synthesized package Fake bool // synthesized package
External bool // synthesized external test package External bool // synthesized external test package
ForceLibrary bool // this package is a library (even if named "main") ForceLibrary bool // this package is a library (even if named "main")
...@@ -951,27 +952,9 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -951,27 +952,9 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
importPaths = append(importPaths, "syscall") importPaths = append(importPaths, "syscall")
} }
if cfg.BuildContext.CgoEnabled && p.Name == "main" && !p.Goroot { if p.Name == "main" && !p.Goroot && cfg.ExternalLinkingForced() {
// Currently build modes c-shared, pie (on systems that do not
// support PIE with internal linking mode (currently all
// systems: issue #18968)), plugin, and -linkshared force
// external linking mode, as of course does
// -ldflags=-linkmode=external. External linking mode forces
// an import of runtime/cgo.
pieCgo := cfg.BuildBuildmode == "pie"
linkmodeExternal := false
for i, a := range cfg.BuildLdflags {
if a == "-linkmode=external" {
linkmodeExternal = true
}
if a == "-linkmode" && i+1 < len(cfg.BuildLdflags) && cfg.BuildLdflags[i+1] == "external" {
linkmodeExternal = true
}
}
if cfg.BuildBuildmode == "c-shared" || cfg.BuildBuildmode == "plugin" || pieCgo || cfg.BuildLinkshared || linkmodeExternal {
importPaths = append(importPaths, "runtime/cgo") importPaths = append(importPaths, "runtime/cgo")
} }
}
// Everything depends on runtime, except runtime, its internal // Everything depends on runtime, except runtime, its internal
// subpackages, and unsafe. // subpackages, and unsafe.
......
...@@ -887,7 +887,11 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin ...@@ -887,7 +887,11 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
// The generated main also imports testing, regexp, and os. // The generated main also imports testing, regexp, and os.
stk.Push("testmain") stk.Push("testmain")
for _, dep := range testMainDeps { deps := testMainDeps
if cfg.ExternalLinkingForced() {
deps = str.StringList(deps, "runtime/cgo")
}
for _, dep := range deps {
if dep == ptest.ImportPath { if dep == ptest.ImportPath {
pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
} else { } else {
......
...@@ -877,6 +877,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo ...@@ -877,6 +877,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
// p.Stale==false implies that p.Internal.Target is up-to-date. // p.Stale==false implies that p.Internal.Target is up-to-date.
// Record target name for use by actions depending on this one. // Record target name for use by actions depending on this one.
a.Target = p.Internal.Target a.Target = p.Internal.Target
p.Internal.Pkgfile = a.Target
return a return a
} }
...@@ -897,6 +898,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo ...@@ -897,6 +898,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
a.Func = BuildInstallFunc a.Func = BuildInstallFunc
a.Deps = []*Action{b.action1(ModeBuild, depMode, p, lookshared, forShlib)} a.Deps = []*Action{b.action1(ModeBuild, depMode, p, lookshared, forShlib)}
a.Target = a.Package.Internal.Target a.Target = a.Package.Internal.Target
a.Package.Internal.Pkgfile = a.Target
// Install header for cgo in c-archive and c-shared modes. // Install header for cgo in c-archive and c-shared modes.
if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
...@@ -923,6 +925,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo ...@@ -923,6 +925,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
case ModeBuild: case ModeBuild:
a.Func = (*Builder).build a.Func = (*Builder).build
a.Target = a.Objpkg a.Target = a.Objpkg
a.Package.Internal.Pkgfile = a.Target
if a.Link { if a.Link {
// An executable file. (This is the name of a temporary file.) // An executable file. (This is the name of a temporary file.)
// Because we run the temporary file in 'go run' and 'go test', // Because we run the temporary file in 'go run' and 'go test',
...@@ -1088,31 +1091,6 @@ func ActionList(root *Action) []*Action { ...@@ -1088,31 +1091,6 @@ func ActionList(root *Action) []*Action {
return all return all
} }
// allArchiveActions returns a list of the archive dependencies of root.
// This is needed because if package p depends on package q that is in libr.so, the
// action graph looks like p->libr.so->q and so just scanning through p's
// dependencies does not find the import dir for q.
func allArchiveActions(root *Action) []*Action {
seen := map[*Action]bool{}
r := []*Action{}
var walk func(*Action)
walk = func(a *Action) {
if seen[a] {
return
}
seen[a] = true
if strings.HasSuffix(a.Target, ".so") || a == root {
for _, a1 := range a.Deps {
walk(a1)
}
} else if strings.HasSuffix(a.Target, ".a") {
r = append(r, a)
}
}
walk(root)
return r
}
// do runs the action graph rooted at root. // do runs the action graph rooted at root.
func (b *Builder) Do(root *Action) { func (b *Builder) Do(root *Action) {
// Build list of all actions, assigning depth-first post-order priority. // Build list of all actions, assigning depth-first post-order priority.
...@@ -1391,11 +1369,46 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -1391,11 +1369,46 @@ func (b *Builder) build(a *Action) (err error) {
} }
} }
// Prepare Go import path list. // NOTE: We used to call allArchiveActions(a) here and use it for -I.
inc := b.includeArgs("-I", allArchiveActions(a)) // The comment on allArchiveActions(a) said:
//
// allArchiveActions returns a list of the archive dependencies of root.
// This is needed because if package p depends on package q that is in libr.so, the
// action graph looks like p->libr.so->q and so just scanning through p's
// dependencies does not find the import dir for q.
//
// If that's true, then the action graph is wrong, and q should be listed
// as a direct dependency of p as well as indirectly through libr.so.
// Prepare Go import config.
var icfg bytes.Buffer
for _, path := range a.Package.Imports {
i := strings.LastIndex(path, "/vendor/")
if i >= 0 {
i += len("/vendor/")
} else if strings.HasPrefix(path, "vendor/") {
i = len("vendor/")
} else {
continue
}
fmt.Fprintf(&icfg, "importmap %s=%s\n", path[i:], path)
}
for _, p1 := range a.Package.Internal.Imports {
if p1.ImportPath == "unsafe" {
continue
}
// TODO(rsc): runtime/internal/sys appears twice sometimes,
// because of the blind append in ../load/pkg.go that
// claims to fix issue 13655. That's probably not the right fix.
// Look into that.
fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, p1.Internal.Pkgfile)
}
if err := b.writeFile(objdir+"importcfg", icfg.Bytes()); err != nil {
return err
}
// Compile Go. // Compile Go.
ofile, out, err := BuildToolchain.gc(b, a.Package, a.Objpkg, objdir, len(sfiles) > 0, inc, gofiles) ofile, out, err := BuildToolchain.gc(b, a.Package, a.Objpkg, objdir, objdir+"importcfg", len(sfiles) > 0, gofiles)
if len(out) > 0 { if len(out) > 0 {
b.showOutput(a.Package.Dir, a.Package.ImportPath, b.processOutput(out)) b.showOutput(a.Package.Dir, a.Package.ImportPath, b.processOutput(out))
if err != nil { if err != nil {
...@@ -1477,11 +1490,16 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -1477,11 +1490,16 @@ func (b *Builder) build(a *Action) (err error) {
// Link if needed. // Link if needed.
if a.Link { if a.Link {
importcfg := a.Objdir + "importcfg.link"
if err := b.writeLinkImportcfg(a, importcfg); err != nil {
return err
}
// The compiler only cares about direct imports, but the // The compiler only cares about direct imports, but the
// linker needs the whole dependency tree. // linker needs the whole dependency tree.
all := ActionList(a) all := ActionList(a)
all = all[:len(all)-1] // drop a all = all[:len(all)-1] // drop a
if err := BuildToolchain.ld(b, a, a.Target, all, a.Objpkg, objects); err != nil { if err := BuildToolchain.ld(b, a, a.Target, importcfg, all, a.Objpkg, objects); err != nil {
return err return err
} }
} }
...@@ -1489,6 +1507,32 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -1489,6 +1507,32 @@ func (b *Builder) build(a *Action) (err error) {
return nil return nil
} }
func (b *Builder) writeLinkImportcfg(a *Action, file string) error {
// Prepare Go import cfg.
var icfg bytes.Buffer
p := a.Package
if p == nil {
// For linkShared, build fake package to serve as root
// for InternalDeps call.
p = new(load.Package)
for _, a1 := range a.Deps {
if a1.Package != nil {
p.Internal.Imports = append(p.Internal.Imports, a1.Package)
}
}
}
for _, p1 := range p.InternalDeps() {
if p1.ImportPath == "unsafe" {
continue
}
fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, p1.Internal.Pkgfile)
if p1.Shlib != "" {
fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib)
}
}
return b.writeFile(file, icfg.Bytes())
}
// PkgconfigCmd returns a pkg-config binary name // PkgconfigCmd returns a pkg-config binary name
// defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist. // defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
func (b *Builder) PkgconfigCmd() string { func (b *Builder) PkgconfigCmd() string {
...@@ -1569,9 +1613,14 @@ func (b *Builder) installShlibname(a *Action) error { ...@@ -1569,9 +1613,14 @@ func (b *Builder) installShlibname(a *Action) error {
} }
func (b *Builder) linkShared(a *Action) (err error) { func (b *Builder) linkShared(a *Action) (err error) {
importcfg := a.Objdir + "importcfg.link"
if err := b.writeLinkImportcfg(a, importcfg); err != nil {
return err
}
allactions := ActionList(a) allactions := ActionList(a)
allactions = allactions[:len(allactions)-1] allactions = allactions[:len(allactions)-1]
return BuildToolchain.ldShared(b, a.Deps, a.Target, allactions) return BuildToolchain.ldShared(b, a.Deps, a.Target, importcfg, allactions)
} }
// BuildInstallFunc is the action for installing a single package or executable. // BuildInstallFunc is the action for installing a single package or executable.
...@@ -1775,6 +1824,17 @@ func (b *Builder) copyFile(a *Action, dst, src string, perm os.FileMode, force b ...@@ -1775,6 +1824,17 @@ func (b *Builder) copyFile(a *Action, dst, src string, perm os.FileMode, force b
return nil return nil
} }
// writeFile writes the text to file.
func (b *Builder) writeFile(file string, text []byte) error {
if cfg.BuildN || cfg.BuildX {
b.Showcmd("", "cat >%s << 'EOF' # internal\n%sEOF", file, text)
}
if cfg.BuildN {
return nil
}
return ioutil.WriteFile(file, text, 0666)
}
// Install the cgo export header file, if there is one. // Install the cgo export header file, if there is one.
func (b *Builder) installHeader(a *Action) error { func (b *Builder) installHeader(a *Action) error {
src := a.Objdir + "_cgo_install.h" src := a.Objdir + "_cgo_install.h"
...@@ -2114,7 +2174,7 @@ func mkAbs(dir, f string) string { ...@@ -2114,7 +2174,7 @@ func mkAbs(dir, f string) string {
type toolchain interface { type toolchain interface {
// gc runs the compiler in a specific directory on a set of files // gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file. // and returns the name of the generated output file.
gc(b *Builder, p *load.Package, archive, objdir string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file // cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file. // to produce an output file.
cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error
...@@ -2128,9 +2188,9 @@ type toolchain interface { ...@@ -2128,9 +2188,9 @@ type toolchain interface {
// typically it is run in the object directory. // typically it is run in the object directory.
pack(b *Builder, p *load.Package, objdir, afile string, ofiles []string) error pack(b *Builder, p *load.Package, objdir, afile string, ofiles []string) error
// ld runs the linker to create an executable starting at mainpkg. // ld runs the linker to create an executable starting at mainpkg.
ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error ld(b *Builder, root *Action, out, importcfg string, allactions []*Action, mainpkg string, ofiles []string) error
// ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error
compiler() string compiler() string
linker() string linker() string
...@@ -2153,7 +2213,7 @@ func (noToolchain) linker() string { ...@@ -2153,7 +2213,7 @@ func (noToolchain) linker() string {
return "" return ""
} }
func (noToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) { func (noToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
return "", nil, noCompiler() return "", nil, noCompiler()
} }
...@@ -2170,11 +2230,11 @@ func (noToolchain) pack(b *Builder, p *load.Package, objdir, afile string, ofile ...@@ -2170,11 +2230,11 @@ func (noToolchain) pack(b *Builder, p *load.Package, objdir, afile string, ofile
return noCompiler() return noCompiler()
} }
func (noToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error { func (noToolchain) ld(b *Builder, root *Action, out, importcfg string, allactions []*Action, mainpkg string, ofiles []string) error {
return noCompiler() return noCompiler()
} }
func (noToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error { func (noToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
return noCompiler() return noCompiler()
} }
...@@ -2193,7 +2253,7 @@ func (gcToolchain) linker() string { ...@@ -2193,7 +2253,7 @@ func (gcToolchain) linker() string {
return base.Tool("link") return base.Tool("link")
} }
func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
if archive != "" { if archive != "" {
ofile = archive ofile = archive
} else { } else {
...@@ -2266,7 +2326,10 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhd ...@@ -2266,7 +2326,10 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhd
} }
} }
} }
args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.WorkDir, gcflags, gcargs, "-D", p.Internal.LocalPrefix, importArgs} args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.WorkDir, gcflags, gcargs, "-D", p.Internal.LocalPrefix}
if importcfg != "" {
args = append(args, "-importcfg", importcfg)
}
if ofile == archive { if ofile == archive {
args = append(args, "-pack") args = append(args, "-pack")
} }
...@@ -2521,8 +2584,7 @@ func setextld(ldflags []string, compiler []string) []string { ...@@ -2521,8 +2584,7 @@ func setextld(ldflags []string, compiler []string) []string {
return ldflags return ldflags
} }
func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error { func (gcToolchain) ld(b *Builder, root *Action, out, importcfg string, allactions []*Action, mainpkg string, ofiles []string) error {
importArgs := b.includeArgs("-L", allactions)
cxx := len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0 cxx := len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0
for _, a := range allactions { for _, a := range allactions {
if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) { if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) {
...@@ -2572,11 +2634,10 @@ func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action ...@@ -2572,11 +2634,10 @@ func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action
dir, out = filepath.Split(out) dir, out = filepath.Split(out)
} }
return b.run(dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags, mainpkg) return b.run(dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags, mainpkg)
} }
func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error { func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
importArgs := b.includeArgs("-L", allactions)
ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix} ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix}
ldflags = append(ldflags, "-buildmode=shared") ldflags = append(ldflags, "-buildmode=shared")
ldflags = append(ldflags, cfg.BuildLdflags...) ldflags = append(ldflags, cfg.BuildLdflags...)
...@@ -2603,7 +2664,7 @@ func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, a ...@@ -2603,7 +2664,7 @@ func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, a
} }
ldflags = append(ldflags, d.Package.ImportPath+"="+d.Target) ldflags = append(ldflags, d.Package.ImportPath+"="+d.Target)
} }
return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags) return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags)
} }
func (gcToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error { func (gcToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error {
...@@ -2642,7 +2703,7 @@ func checkGccgoBin() { ...@@ -2642,7 +2703,7 @@ func checkGccgoBin() {
os.Exit(2) os.Exit(2)
} }
func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
out := "_go_.o" out := "_go_.o"
ofile = objdir + out ofile = objdir + out
gcargs := []string{"-g"} gcargs := []string{"-g"}
...@@ -2654,57 +2715,11 @@ func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir stri ...@@ -2654,57 +2715,11 @@ func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir stri
gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix) gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix)
} }
// Handle vendor directories args := str.StringList(tools.compiler(), "-c", gcargs, "-o", ofile)
savedirs := []string{} if importcfg != "" {
for _, incdir := range importArgs { args = append(args, "-importcfg", importcfg)
if incdir != "-I" {
savedirs = append(savedirs, incdir)
}
}
for _, path := range p.Imports {
// If this is a new vendor path, add it to the list of importArgs
if i := strings.LastIndex(path, "/vendor"); i >= 0 {
for _, dir := range savedirs {
// Check if the vendor path is already included in dir
if strings.HasSuffix(dir, path[:i+len("/vendor")]) {
continue
}
// Make sure this vendor path is not already in the list for importArgs
vendorPath := dir + "/" + path[:i+len("/vendor")]
for _, imp := range importArgs {
if imp == "-I" {
continue
}
// This vendorPath is already in the list
if imp == vendorPath {
goto nextSuffixPath
}
}
// New vendorPath not yet in the importArgs list, so add it
importArgs = append(importArgs, "-I", vendorPath)
nextSuffixPath:
} }
} else if strings.HasPrefix(path, "vendor/") { args = append(args, buildGccgoflags...)
for _, dir := range savedirs {
// Make sure this vendor path is not already in the list for importArgs
vendorPath := dir + "/" + path[len("/vendor"):]
for _, imp := range importArgs {
if imp == "-I" {
continue
}
if imp == vendorPath {
goto nextPrefixPath
}
}
// This vendor path is needed and not already in the list, so add it
importArgs = append(importArgs, "-I", vendorPath)
nextPrefixPath:
}
}
}
args := str.StringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
for _, f := range gofiles { for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f)) args = append(args, mkAbs(p.Dir, f))
} }
...@@ -2748,7 +2763,7 @@ func (gccgoToolchain) pack(b *Builder, p *load.Package, objdir, afile string, of ...@@ -2748,7 +2763,7 @@ func (gccgoToolchain) pack(b *Builder, p *load.Package, objdir, afile string, of
return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objdir, afile), absOfiles) return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objdir, afile), absOfiles)
} }
func (tools gccgoToolchain) link(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string, buildmode, desc string) error { func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string, allactions []*Action, mainpkg string, ofiles []string, buildmode, desc string) error {
// gccgo needs explicit linking with all package dependencies, // gccgo needs explicit linking with all package dependencies,
// and all LDFLAGS from cgo dependencies. // and all LDFLAGS from cgo dependencies.
apackagePathsSeen := make(map[string]bool) apackagePathsSeen := make(map[string]bool)
...@@ -3014,14 +3029,14 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out string, allaction ...@@ -3014,14 +3029,14 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out string, allaction
return nil return nil
} }
func (tools gccgoToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error { func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg string, allactions []*Action, mainpkg string, ofiles []string) error {
return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.Package.ImportPath) return tools.link(b, root, out, importcfg, allactions, mainpkg, ofiles, ldBuildmode, root.Package.ImportPath)
} }
func (tools gccgoToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error { func (tools gccgoToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
fakeRoot := &Action{} fakeRoot := &Action{}
fakeRoot.Deps = toplevelactions fakeRoot.Deps = toplevelactions
return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out) return tools.link(b, fakeRoot, out, importcfg, allactions, "", nil, "shared", out)
} }
func (tools gccgoToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error { func (tools gccgoToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error {
...@@ -3638,7 +3653,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { ...@@ -3638,7 +3653,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
p := load.GoFilesPackage(srcs) p := load.GoFilesPackage(srcs)
if _, _, e := BuildToolchain.gc(b, p, "", objdir, false, nil, srcs); e != nil { if _, _, e := BuildToolchain.gc(b, p, "", objdir, "", false, srcs); e != nil {
return "32", nil return "32", nil
} }
return "64", nil return "64", nil
......
...@@ -116,6 +116,16 @@ func findlib(ctxt *Link, lib string) (string, bool) { ...@@ -116,6 +116,16 @@ func findlib(ctxt *Link, lib string) (string, bool) {
pname = name pname = name
} else { } else {
pkg := pkgname(lib) pkg := pkgname(lib)
// Add .a if needed; the new -importcfg modes
// do not put .a into the package name anymore.
// This only matters when people try to mix
// compiles using -importcfg with links not using -importcfg,
// such as when running quick things like
// 'go tool compile x.go && go tool link x.o'
// by hand against a standard library built using -importcfg.
if !strings.HasSuffix(name, ".a") && !strings.HasSuffix(name, ".o") {
name += ".a"
}
// try dot, -L "libdir", and then goroot. // try dot, -L "libdir", and then goroot.
for _, dir := range ctxt.Libdir { for _, dir := range ctxt.Libdir {
if *FlagLinkshared { if *FlagLinkshared {
...@@ -163,14 +173,15 @@ func addlib(ctxt *Link, src string, obj string, lib string) *Library { ...@@ -163,14 +173,15 @@ func addlib(ctxt *Link, src string, obj string, lib string) *Library {
* objref: object file referring to package * objref: object file referring to package
* file: object file, e.g., /home/rsc/go/pkg/container/vector.a * file: object file, e.g., /home/rsc/go/pkg/container/vector.a
* pkg: package import path, e.g. container/vector * pkg: package import path, e.g. container/vector
* shlib: path to shared library, or .shlibname file holding path
*/ */
func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg string, shlibnamefile string) *Library { func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg string, shlib string) *Library {
if l := ctxt.LibraryByPkg[pkg]; l != nil { if l := ctxt.LibraryByPkg[pkg]; l != nil {
return l return l
} }
if ctxt.Debugvlog > 1 { if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s shlibnamefile: %s\n", Cputime(), srcref, objref, file, pkg, shlibnamefile) ctxt.Logf("%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s shlib: %s\n", Cputime(), srcref, objref, file, pkg, shlib)
} }
l := &Library{} l := &Library{}
...@@ -180,12 +191,15 @@ func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg strin ...@@ -180,12 +191,15 @@ func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg strin
l.Srcref = srcref l.Srcref = srcref
l.File = file l.File = file
l.Pkg = pkg l.Pkg = pkg
if shlibnamefile != "" { if shlib != "" {
shlibbytes, err := ioutil.ReadFile(shlibnamefile) if strings.HasSuffix(shlib, ".shlibname") {
data, err := ioutil.ReadFile(shlib)
if err != nil { if err != nil {
Errorf(nil, "cannot read %s: %v", shlibnamefile, err) Errorf(nil, "cannot read %s: %v", shlib, err)
}
shlib = strings.TrimSpace(string(data))
} }
l.Shlib = strings.TrimSpace(string(shlibbytes)) l.Shlib = shlib
} }
return l return l
} }
......
...@@ -338,8 +338,8 @@ func errorexit() { ...@@ -338,8 +338,8 @@ func errorexit() {
func loadinternal(ctxt *Link, name string) *Library { func loadinternal(ctxt *Link, name string) *Library {
if *FlagLinkshared && ctxt.PackageShlib != nil { if *FlagLinkshared && ctxt.PackageShlib != nil {
if shlibname := ctxt.PackageShlib[name]; shlibname != "" { if shlib := ctxt.PackageShlib[name]; shlib != "" {
return addlibpath(ctxt, "internal", "internal", "", name, shlibname) return addlibpath(ctxt, "internal", "internal", "", name, shlib)
} }
} }
if ctxt.PackageFile != nil { if ctxt.PackageFile != nil {
...@@ -423,22 +423,23 @@ func (ctxt *Link) loadlib() { ...@@ -423,22 +423,23 @@ func (ctxt *Link) loadlib() {
loadinternal(ctxt, "runtime/msan") loadinternal(ctxt, "runtime/msan")
} }
var i int // ctxt.Library grows during the loop, so not a range loop.
for i = 0; i < len(ctxt.Library); i++ { for i := 0; i < len(ctxt.Library); i++ {
if ctxt.Library[i].Shlib == "" { lib := ctxt.Library[i]
if lib.Shlib == "" {
if ctxt.Debugvlog > 1 { if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), ctxt.Library[i].File, ctxt.Library[i].Objref) ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.File, lib.Objref)
} }
objfile(ctxt, ctxt.Library[i]) objfile(ctxt, lib)
} }
} }
for i = 0; i < len(ctxt.Library); i++ { for _, lib := range ctxt.Library {
if ctxt.Library[i].Shlib != "" { if lib.Shlib != "" {
if ctxt.Debugvlog > 1 { if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), ctxt.Library[i].Shlib, ctxt.Library[i].Objref) ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.Shlib, lib.Objref)
} }
ldshlibsyms(ctxt, ctxt.Library[i].Shlib) ldshlibsyms(ctxt, lib.Shlib)
} }
} }
...@@ -461,21 +462,19 @@ func (ctxt *Link) loadlib() { ...@@ -461,21 +462,19 @@ func (ctxt *Link) loadlib() {
toc.Type = SDYNIMPORT toc.Type = SDYNIMPORT
} }
if Linkmode == LinkExternal && !iscgo { if Linkmode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil {
// This indicates a user requested -linkmode=external. // This indicates a user requested -linkmode=external.
// The startup code uses an import of runtime/cgo to decide // The startup code uses an import of runtime/cgo to decide
// whether to initialize the TLS. So give it one. This could // whether to initialize the TLS. So give it one. This could
// be handled differently but it's an unusual case. // be handled differently but it's an unusual case.
loadinternal(ctxt, "runtime/cgo") if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
if lib.Shlib != "" {
if i < len(ctxt.Library) { ldshlibsyms(ctxt, lib.Shlib)
if ctxt.Library[i].Shlib != "" {
ldshlibsyms(ctxt, ctxt.Library[i].Shlib)
} else { } else {
if Buildmode == BuildmodeShared || *FlagLinkshared { if Buildmode == BuildmodeShared || *FlagLinkshared {
Exitf("cannot implicitly include runtime/cgo in a shared library") Exitf("cannot implicitly include runtime/cgo in a shared library")
} }
objfile(ctxt, ctxt.Library[i]) objfile(ctxt, lib)
} }
} }
} }
...@@ -633,9 +632,9 @@ func (ctxt *Link) loadlib() { ...@@ -633,9 +632,9 @@ func (ctxt *Link) loadlib() {
// If package versioning is required, generate a hash of the // If package versioning is required, generate a hash of the
// the packages used in the link. // the packages used in the link.
if Buildmode == BuildmodeShared || Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil { if Buildmode == BuildmodeShared || Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
for i = 0; i < len(ctxt.Library); i++ { for _, lib := range ctxt.Library {
if ctxt.Library[i].Shlib == "" { if lib.Shlib == "" {
genhash(ctxt, ctxt.Library[i]) genhash(ctxt, lib)
} }
} }
} }
...@@ -1538,6 +1537,9 @@ func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) { ...@@ -1538,6 +1537,9 @@ func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
} }
func findshlib(ctxt *Link, shlib string) string { func findshlib(ctxt *Link, shlib string) string {
if filepath.IsAbs(shlib) {
return shlib
}
for _, libdir := range ctxt.Libdir { for _, libdir := range ctxt.Libdir {
libpath := filepath.Join(libdir, shlib) libpath := filepath.Join(libdir, shlib)
if _, err := os.Stat(libpath); err == nil { if _, err := os.Stat(libpath); err == nil {
...@@ -1549,10 +1551,16 @@ func findshlib(ctxt *Link, shlib string) string { ...@@ -1549,10 +1551,16 @@ func findshlib(ctxt *Link, shlib string) string {
} }
func ldshlibsyms(ctxt *Link, shlib string) { func ldshlibsyms(ctxt *Link, shlib string) {
libpath := findshlib(ctxt, shlib) var libpath string
if filepath.IsAbs(shlib) {
libpath = shlib
shlib = filepath.Base(shlib)
} else {
libpath = findshlib(ctxt, shlib)
if libpath == "" { if libpath == "" {
return return
} }
}
for _, processedlib := range ctxt.Shlibs { for _, processedlib := range ctxt.Shlibs {
if processedlib.Path == libpath { if processedlib.Path == libpath {
return return
...@@ -1580,7 +1588,22 @@ func ldshlibsyms(ctxt *Link, shlib string) { ...@@ -1580,7 +1588,22 @@ func ldshlibsyms(ctxt *Link, shlib string) {
Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err) Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
return return
} }
deps := strings.Split(string(depsbytes), "\n") var deps []string
for _, dep := range strings.Split(string(depsbytes), "\n") {
if dep == "" {
continue
}
if !filepath.IsAbs(dep) {
// If the dep can be interpreted as a path relative to the shlib
// in which it was found, do that. Otherwise, we will leave it
// to be resolved by libdir lookup.
abs := filepath.Join(filepath.Dir(libpath), dep)
if _, err := os.Stat(abs); err == nil {
dep = abs
}
}
deps = append(deps, dep)
}
syms, err := f.DynamicSymbols() syms, err := f.DynamicSymbols()
if err != nil { if err != nil {
......
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