]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: special case shared library name when passed "$prefix/..."
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 23 Dec 2015 02:33:55 +0000 (15:33 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 6 Jan 2016 01:46:39 +0000 (01:46 +0000)
Before golang.org/cl/13921, "go install -buildmode=shared prefix/..." created a
file called "libprefix.so", which was obviously a problem when prefix was
something like "." or "../".  However, now it expands the ... into all the
matched packages, joins them with -, which can clearly be a very long name
indeed. Because I plan to build shared libraries for Ubuntu by running commands
exactly like "go install -buildmode=shared prefix/...", this special cases this
to produce the old behaviour (but de-relativises prefix first).

Fixes #13714

Change-Id: I4fd8d4934279f9a18cc70a13e4ef3e23f6abcb6e
Reviewed-on: https://go-review.googlesource.com/18114
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/go/build.go
src/cmd/go/pkg_test.go

index b7cfc87dc7dec654a67d6e2a372e8ce1bb5307cc..6c6d551e795f3ed5e94365977787c18eba29cb1d 100644 (file)
@@ -520,11 +520,14 @@ func isMetaPackage(name string) bool {
 // Use arguments for special 'meta' packages:
 //     std --> libstd.so
 //     std cmd --> libstd,cmd.so
+// A single non-meta argument with trailing "/..." is special cased:
+//     foo/... --> libfoo.so
+//     (A relative path like "./..."  expands the "." first)
 // Use import paths for other cases, changing '/' to '-':
 //     somelib --> libsubdir-somelib.so
 //     ./ or ../ --> libsubdir-somelib.so
 //     gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
-//     ./... ---> libpkg1,pkg2.so - subset of all import paths
+//     a/... b/... ---> liba/c,b/d.so - all matching import paths
 // Name parts are joined with ','.
 func libname(args []string, pkgs []*Package) (string, error) {
        var libname string
@@ -544,8 +547,21 @@ func libname(args []string, pkgs []*Package) (string, error) {
                }
        }
        if len(libname) == 0 { // non-meta packages only. use import paths
-               for _, pkg := range pkgs {
-                       appendName(strings.Replace(pkg.ImportPath, "/", "-", -1))
+               if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
+                       // Special case of "foo/..." as mentioned above.
+                       arg := strings.TrimSuffix(args[0], "/...")
+                       if build.IsLocalImport(arg) {
+                               cwd, _ := os.Getwd()
+                               bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+                               if bp.ImportPath != "" && bp.ImportPath != "." {
+                                       arg = bp.ImportPath
+                               }
+                       }
+                       appendName(strings.Replace(arg, "/", "-", -1))
+               } else {
+                       for _, pkg := range pkgs {
+                               appendName(strings.Replace(pkg.ImportPath, "/", "-", -1))
+                       }
                }
        } else if haveNonMeta { // have both meta package and a non-meta one
                return "", errors.New("mixing of meta and non-meta packages is not allowed")
index 90a92582e73883dfced2296f93894c9ca094d7ec..1e7ca2c6fe0f08c0f5c8260f58634780934fee00 100644 (file)
@@ -5,6 +5,9 @@
 package main
 
 import (
+       "io/ioutil"
+       "os"
+       "path/filepath"
        "reflect"
        "strings"
        "testing"
@@ -90,85 +93,99 @@ func TestSharedLibName(t *testing.T) {
                pkgs      []*Package
                expected  string
                expectErr bool
+               rootedAt  string
        }{
                {
-                       []string{"std"},
-                       []*Package{},
-                       "std",
-                       false,
+                       args:     []string{"std"},
+                       pkgs:     []*Package{},
+                       expected: "std",
                },
                {
-                       []string{"std", "cmd"},
-                       []*Package{},
-                       "std,cmd",
-                       false,
+                       args:     []string{"std", "cmd"},
+                       pkgs:     []*Package{},
+                       expected: "std,cmd",
                },
                {
-                       []string{},
-                       []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
-                       "gopkg.in-somelib",
-                       false,
+                       args:     []string{},
+                       pkgs:     []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
+                       expected: "gopkg.in-somelib",
                },
                {
-                       []string{"./..."},
-                       []*Package{&Package{ImportPath: "somelib"}},
-                       "somelib",
-                       false,
+                       args:     []string{"./..."},
+                       pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+                       expected: "somelib",
+                       rootedAt: "somelib",
                },
                {
-                       []string{"../somelib", "../somelib"},
-                       []*Package{&Package{ImportPath: "somelib"}},
-                       "somelib",
-                       false,
+                       args:     []string{"../somelib", "../somelib"},
+                       pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+                       expected: "somelib",
                },
                {
-                       []string{"../lib1", "../lib2"},
-                       []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
-                       "gopkg.in-lib1,gopkg.in-lib2",
-                       false,
+                       args:     []string{"../lib1", "../lib2"},
+                       pkgs:     []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
+                       expected: "gopkg.in-lib1,gopkg.in-lib2",
                },
                {
-                       []string{"./..."},
-                       []*Package{
+                       args: []string{"./..."},
+                       pkgs: []*Package{
                                &Package{ImportPath: "gopkg.in/dir/lib1"},
                                &Package{ImportPath: "gopkg.in/lib2"},
                                &Package{ImportPath: "gopkg.in/lib3"},
                        },
-                       "gopkg.in-dir-lib1,gopkg.in-lib2,gopkg.in-lib3",
-                       false,
+                       expected: "gopkg.in",
+                       rootedAt: "gopkg.in",
                },
                {
-                       []string{"std", "../lib2"},
-                       []*Package{},
-                       "",
-                       true,
+                       args:      []string{"std", "../lib2"},
+                       pkgs:      []*Package{},
+                       expectErr: true,
                },
                {
-                       []string{"all", "./"},
-                       []*Package{},
-                       "",
-                       true,
+                       args:      []string{"all", "./"},
+                       pkgs:      []*Package{},
+                       expectErr: true,
                },
                {
-                       []string{"cmd", "fmt"},
-                       []*Package{},
-                       "",
-                       true,
+                       args:      []string{"cmd", "fmt"},
+                       pkgs:      []*Package{},
+                       expectErr: true,
                },
        }
        for _, data := range testData {
-               computed, err := libname(data.args, data.pkgs)
-               if err != nil {
-                       if !data.expectErr {
-                               t.Errorf("libname returned an error %q, expected a name", err.Error())
+               func() {
+                       if data.rootedAt != "" {
+                               tmpGopath, err := ioutil.TempDir("", "gopath")
+                               if err != nil {
+                                       t.Fatal(err)
+                               }
+                               oldGopath := buildContext.GOPATH
+                               defer func() {
+                                       os.RemoveAll(tmpGopath)
+                                       buildContext.GOPATH = oldGopath
+                                       os.Chdir(cwd)
+                               }()
+                               root := filepath.Join(tmpGopath, "src", data.rootedAt)
+                               err = os.MkdirAll(root, 0755)
+                               if err != nil {
+                                       t.Fatal(err)
+                               }
+                               buildContext.GOPATH = tmpGopath
+                               os.Chdir(root)
                        }
-               } else if data.expectErr {
-                       t.Errorf("libname returned %q, expected an error", computed)
-               } else {
-                       expected := prefix + data.expected + suffix
-                       if expected != computed {
-                               t.Errorf("libname returned %q, expected %q", computed, expected)
+                       computed, err := libname(data.args, data.pkgs)
+                       if err != nil {
+                               if !data.expectErr {
+                                       t.Errorf("libname returned an error %q, expected a name", err.Error())
+                               }
+                       } else if data.expectErr {
+                               t.Errorf("libname returned %q, expected an error", computed)
+                       } else {
+                               expected := prefix + data.expected + suffix
+                               if expected != computed {
+                                       t.Errorf("libname returned %q, expected %q", computed, expected)
+                               }
                        }
-               }
+               }()
        }
 }