diff --git a/src/cmd/link/internal/ld/ld.go b/src/cmd/link/internal/ld/ld.go index c6cad49f26..fc4137213f 100644 --- a/src/cmd/link/internal/ld/ld.go +++ b/src/cmd/link/internal/ld/ld.go @@ -33,6 +33,7 @@ package ld import ( "io/ioutil" + "log" "os" "path" "path/filepath" @@ -40,6 +41,51 @@ import ( "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 { name := path.Clean(pathname) @@ -56,27 +102,38 @@ func addlib(ctxt *Link, src string, obj string, pathname string) *Library { var pname string isshlib := false - if filepath.IsAbs(name) { - pname = name + + 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 { - // try dot, -L "libdir", and then goroot. - for _, dir := range ctxt.Libdir { - if *FlagLinkshared { - pname = dir + "/" + pkg + ".shlibname" + if filepath.IsAbs(name) { + pname = name + } else { + // try dot, -L "libdir", and then goroot. + for _, dir := range ctxt.Libdir { + if *FlagLinkshared { + pname = dir + "/" + pkg + ".shlibname" + if _, err := os.Stat(pname); err == nil { + isshlib = true + break + } + } + pname = dir + "/" + name if _, err := os.Stat(pname); err == nil { - isshlib = true break } } - pname = dir + "/" + name - if _, err := os.Stat(pname); err == nil { - break - } } + pname = path.Clean(pname) } - pname = path.Clean(pname) - if ctxt.Debugvlog > 1 { ctxt.Logf("%5.2f addlib: %s %s pulls in %s isshlib %v\n", elapsed(), obj, src, pname, isshlib) } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 8906d2f91a..625287112c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -333,6 +333,19 @@ func errorexit() { } 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++ { if *FlagLinkshared { shlibname := filepath.Join(ctxt.Libdir[i], name+".shlibname") diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index 45ce20a700..302364c299 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -230,6 +230,9 @@ type Link struct { Filesyms []*Symbol Moduledata *Symbol + PackageFile map[string]string + PackageShlib map[string]string + tramps []*Symbol // trampolines } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 0078064f28..f03460d2b4 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -122,6 +122,7 @@ func Main() { 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.Flagcount("v", "print link trace", &ctxt.Debugvlog) + objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg) objabi.Flagparse(usage)