Skip to content

Commit 4f2269e

Browse files
committed
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 <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 4d6b08d commit 4f2269e

File tree

4 files changed

+87
-13
lines changed

4 files changed

+87
-13
lines changed

src/cmd/link/internal/ld/ld.go

+70-13
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,59 @@ package ld
3333

3434
import (
3535
"io/ioutil"
36+
"log"
3637
"os"
3738
"path"
3839
"path/filepath"
3940
"strconv"
4041
"strings"
4142
)
4243

44+
func (ctxt *Link) readImportCfg(file string) {
45+
ctxt.PackageFile = make(map[string]string)
46+
ctxt.PackageShlib = make(map[string]string)
47+
data, err := ioutil.ReadFile(file)
48+
if err != nil {
49+
log.Fatalf("-importcfg: %v", err)
50+
}
51+
52+
for lineNum, line := range strings.Split(string(data), "\n") {
53+
lineNum++ // 1-based
54+
line = strings.TrimSpace(line)
55+
if line == "" {
56+
continue
57+
}
58+
if line == "" || strings.HasPrefix(line, "#") {
59+
continue
60+
}
61+
62+
var verb, args string
63+
if i := strings.Index(line, " "); i < 0 {
64+
verb = line
65+
} else {
66+
verb, args = line[:i], strings.TrimSpace(line[i+1:])
67+
}
68+
var before, after string
69+
if i := strings.Index(args, "="); i >= 0 {
70+
before, after = args[:i], args[i+1:]
71+
}
72+
switch verb {
73+
default:
74+
log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
75+
case "packagefile":
76+
if before == "" || after == "" {
77+
log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
78+
}
79+
ctxt.PackageFile[before] = after
80+
case "packageshlib":
81+
if before == "" || after == "" {
82+
log.Fatalf(`%s:%d: invalid packageshlib: syntax is "packageshlib path=filename"`, file, lineNum)
83+
}
84+
ctxt.PackageShlib[before] = after
85+
}
86+
}
87+
}
88+
4389
func addlib(ctxt *Link, src string, obj string, pathname string) *Library {
4490
name := path.Clean(pathname)
4591

@@ -56,27 +102,38 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library {
56102

57103
var pname string
58104
isshlib := false
59-
if filepath.IsAbs(name) {
60-
pname = name
105+
106+
if *FlagLinkshared && ctxt.PackageShlib[name] != "" {
107+
pname = ctxt.PackageShlib[name]
108+
isshlib = true
109+
} else if ctxt.PackageFile != nil {
110+
pname = ctxt.PackageFile[name]
111+
if pname == "" {
112+
ctxt.Logf("cannot find package %s (using -importcfg)\n", name)
113+
return nil
114+
}
61115
} else {
62-
// try dot, -L "libdir", and then goroot.
63-
for _, dir := range ctxt.Libdir {
64-
if *FlagLinkshared {
65-
pname = dir + "/" + pkg + ".shlibname"
116+
if filepath.IsAbs(name) {
117+
pname = name
118+
} else {
119+
// try dot, -L "libdir", and then goroot.
120+
for _, dir := range ctxt.Libdir {
121+
if *FlagLinkshared {
122+
pname = dir + "/" + pkg + ".shlibname"
123+
if _, err := os.Stat(pname); err == nil {
124+
isshlib = true
125+
break
126+
}
127+
}
128+
pname = dir + "/" + name
66129
if _, err := os.Stat(pname); err == nil {
67-
isshlib = true
68130
break
69131
}
70132
}
71-
pname = dir + "/" + name
72-
if _, err := os.Stat(pname); err == nil {
73-
break
74-
}
75133
}
134+
pname = path.Clean(pname)
76135
}
77136

78-
pname = path.Clean(pname)
79-
80137
if ctxt.Debugvlog > 1 {
81138
ctxt.Logf("%5.2f addlib: %s %s pulls in %s isshlib %v\n", elapsed(), obj, src, pname, isshlib)
82139
}

src/cmd/link/internal/ld/lib.go

+13
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,19 @@ func errorexit() {
333333
}
334334

335335
func loadinternal(ctxt *Link, name string) *Library {
336+
if *FlagLinkshared && ctxt.PackageShlib != nil {
337+
if shlibname := ctxt.PackageShlib[name]; shlibname != "" {
338+
return addlibpath(ctxt, "internal", "internal", "", name, shlibname)
339+
}
340+
}
341+
if ctxt.PackageFile != nil {
342+
if pname := ctxt.PackageFile[name]; pname != "" {
343+
return addlibpath(ctxt, "internal", "internal", pname, name, "")
344+
}
345+
ctxt.Logf("loadinternal: cannot find %s\n", name)
346+
return nil
347+
}
348+
336349
for i := 0; i < len(ctxt.Libdir); i++ {
337350
if *FlagLinkshared {
338351
shlibname := filepath.Join(ctxt.Libdir[i], name+".shlibname")

src/cmd/link/internal/ld/link.go

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ type Link struct {
230230
Filesyms []*Symbol
231231
Moduledata *Symbol
232232

233+
PackageFile map[string]string
234+
PackageShlib map[string]string
235+
233236
tramps []*Symbol // trampolines
234237
}
235238

src/cmd/link/internal/ld/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ func Main() {
122122
objabi.Flagfn0("V", "print version and exit", doversion)
123123
objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
124124
objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog)
125+
objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg)
125126

126127
objabi.Flagparse(usage)
127128

0 commit comments

Comments
 (0)