]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: add -importcfg to specify import resolution
authorRuss Cox <rsc@golang.org>
Wed, 31 May 2017 15:35:29 +0000 (11:35 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 6 Jun 2017 19:49:58 +0000 (19:49 +0000)
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: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/ld.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/link.go
src/cmd/link/internal/ld/main.go

index c6cad49f26bc14c2c9f30ac1101c1f2b6e64c8cb..fc4137213f160728289befd4f7548529410f737a 100644 (file)
@@ -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)
        }
index 8906d2f91a7fcb4b0d7e7e46baf8eff7aae8020b..625287112cdbbc431f3f210877fe2720a8ca3009 100644 (file)
@@ -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")
index 45ce20a7000d5f6a9f702638af913c0208e34734..302364c299366125085c1517eb1a2f5c25d83a7d 100644 (file)
@@ -230,6 +230,9 @@ type Link struct {
        Filesyms     []*Symbol
        Moduledata   *Symbol
 
+       PackageFile  map[string]string
+       PackageShlib map[string]string
+
        tramps []*Symbol // trampolines
 }
 
index 0078064f28c9470c4c803ec86180814976e22352..f03460d2b45f89804ec33f92c5454600c5eed7d0 100644 (file)
@@ -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)