Commit 4f2269ed authored by Russ Cox's avatar Russ Cox

cmd/link: add -importcfg to specify import resolution

Adds the ability to specify the file location of each imported package,
like in the -importcfg added to cmd/compile in a related CL.
In effect, -importcfg is a generalization of and supersedes -installsuffix
and -L. Of course, those flags will continue to be supported, for
compatibility with other tools.

Having this flag in Go 1.9 will let us try some experiments involving
package management without needing guinea pigs to build a custom
Go toolchain.

This flag also helps with #14271 at some later point.

For #20579.

Change-Id: Ie4c171bcd3aa2faa446ac340e36516f2f9853882
Reviewed-on: https://go-review.googlesource.com/44851
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 4d6b08de
...@@ -33,6 +33,7 @@ package ld ...@@ -33,6 +33,7 @@ package ld
import ( import (
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
...@@ -40,6 +41,51 @@ import ( ...@@ -40,6 +41,51 @@ import (
"strings" "strings"
) )
func (ctxt *Link) readImportCfg(file string) {
ctxt.PackageFile = make(map[string]string)
ctxt.PackageShlib = make(map[string]string)
data, err := ioutil.ReadFile(file)
if err != nil {
log.Fatalf("-importcfg: %v", err)
}
for lineNum, line := range strings.Split(string(data), "\n") {
lineNum++ // 1-based
line = strings.TrimSpace(line)
if line == "" {
continue
}
if line == "" || strings.HasPrefix(line, "#") {
continue
}
var verb, args string
if i := strings.Index(line, " "); i < 0 {
verb = line
} else {
verb, args = line[:i], strings.TrimSpace(line[i+1:])
}
var before, after string
if i := strings.Index(args, "="); i >= 0 {
before, after = args[:i], args[i+1:]
}
switch verb {
default:
log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
case "packagefile":
if before == "" || after == "" {
log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
}
ctxt.PackageFile[before] = after
case "packageshlib":
if before == "" || after == "" {
log.Fatalf(`%s:%d: invalid packageshlib: syntax is "packageshlib path=filename"`, file, lineNum)
}
ctxt.PackageShlib[before] = after
}
}
}
func addlib(ctxt *Link, src string, obj string, pathname string) *Library { func addlib(ctxt *Link, src string, obj string, pathname string) *Library {
name := path.Clean(pathname) name := path.Clean(pathname)
...@@ -56,6 +102,17 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library { ...@@ -56,6 +102,17 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library {
var pname string var pname string
isshlib := false isshlib := false
if *FlagLinkshared && ctxt.PackageShlib[name] != "" {
pname = ctxt.PackageShlib[name]
isshlib = true
} else if ctxt.PackageFile != nil {
pname = ctxt.PackageFile[name]
if pname == "" {
ctxt.Logf("cannot find package %s (using -importcfg)\n", name)
return nil
}
} else {
if filepath.IsAbs(name) { if filepath.IsAbs(name) {
pname = name pname = name
} else { } else {
...@@ -74,8 +131,8 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library { ...@@ -74,8 +131,8 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library {
} }
} }
} }
pname = path.Clean(pname) pname = path.Clean(pname)
}
if ctxt.Debugvlog > 1 { if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f addlib: %s %s pulls in %s isshlib %v\n", elapsed(), obj, src, pname, isshlib) ctxt.Logf("%5.2f addlib: %s %s pulls in %s isshlib %v\n", elapsed(), obj, src, pname, isshlib)
......
...@@ -333,6 +333,19 @@ func errorexit() { ...@@ -333,6 +333,19 @@ func errorexit() {
} }
func loadinternal(ctxt *Link, name string) *Library { func loadinternal(ctxt *Link, name string) *Library {
if *FlagLinkshared && ctxt.PackageShlib != nil {
if shlibname := ctxt.PackageShlib[name]; shlibname != "" {
return addlibpath(ctxt, "internal", "internal", "", name, shlibname)
}
}
if ctxt.PackageFile != nil {
if pname := ctxt.PackageFile[name]; pname != "" {
return addlibpath(ctxt, "internal", "internal", pname, name, "")
}
ctxt.Logf("loadinternal: cannot find %s\n", name)
return nil
}
for i := 0; i < len(ctxt.Libdir); i++ { for i := 0; i < len(ctxt.Libdir); i++ {
if *FlagLinkshared { if *FlagLinkshared {
shlibname := filepath.Join(ctxt.Libdir[i], name+".shlibname") shlibname := filepath.Join(ctxt.Libdir[i], name+".shlibname")
......
...@@ -230,6 +230,9 @@ type Link struct { ...@@ -230,6 +230,9 @@ type Link struct {
Filesyms []*Symbol Filesyms []*Symbol
Moduledata *Symbol Moduledata *Symbol
PackageFile map[string]string
PackageShlib map[string]string
tramps []*Symbol // trampolines tramps []*Symbol // trampolines
} }
......
...@@ -122,6 +122,7 @@ func Main() { ...@@ -122,6 +122,7 @@ func Main() {
objabi.Flagfn0("V", "print version and exit", doversion) objabi.Flagfn0("V", "print version and exit", doversion)
objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) }) objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog) objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog)
objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg)
objabi.Flagparse(usage) objabi.Flagparse(usage)
......
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