Commit ae8e5586 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/go: special case shared library name when passed "$prefix/..."

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/18114Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 7f96e266
...@@ -520,11 +520,14 @@ func isMetaPackage(name string) bool { ...@@ -520,11 +520,14 @@ func isMetaPackage(name string) bool {
// Use arguments for special 'meta' packages: // Use arguments for special 'meta' packages:
// std --> libstd.so // std --> libstd.so
// std cmd --> libstd,cmd.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 '-': // Use import paths for other cases, changing '/' to '-':
// somelib --> libsubdir-somelib.so // somelib --> libsubdir-somelib.so
// ./ or ../ --> libsubdir-somelib.so // ./ or ../ --> libsubdir-somelib.so
// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.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 ','. // Name parts are joined with ','.
func libname(args []string, pkgs []*Package) (string, error) { func libname(args []string, pkgs []*Package) (string, error) {
var libname string var libname string
...@@ -544,8 +547,21 @@ func libname(args []string, pkgs []*Package) (string, error) { ...@@ -544,8 +547,21 @@ func libname(args []string, pkgs []*Package) (string, error) {
} }
} }
if len(libname) == 0 { // non-meta packages only. use import paths if len(libname) == 0 { // non-meta packages only. use import paths
for _, pkg := range pkgs { if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
appendName(strings.Replace(pkg.ImportPath, "/", "-", -1)) // 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 } 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") return "", errors.New("mixing of meta and non-meta packages is not allowed")
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
package main package main
import ( import (
"io/ioutil"
"os"
"path/filepath"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
...@@ -90,85 +93,99 @@ func TestSharedLibName(t *testing.T) { ...@@ -90,85 +93,99 @@ func TestSharedLibName(t *testing.T) {
pkgs []*Package pkgs []*Package
expected string expected string
expectErr bool expectErr bool
rootedAt string
}{ }{
{ {
[]string{"std"}, args: []string{"std"},
[]*Package{}, pkgs: []*Package{},
"std", expected: "std",
false,
}, },
{ {
[]string{"std", "cmd"}, args: []string{"std", "cmd"},
[]*Package{}, pkgs: []*Package{},
"std,cmd", expected: "std,cmd",
false,
}, },
{ {
[]string{}, args: []string{},
[]*Package{&Package{ImportPath: "gopkg.in/somelib"}}, pkgs: []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
"gopkg.in-somelib", expected: "gopkg.in-somelib",
false,
}, },
{ {
[]string{"./..."}, args: []string{"./..."},
[]*Package{&Package{ImportPath: "somelib"}}, pkgs: []*Package{&Package{ImportPath: "somelib"}},
"somelib", expected: "somelib",
false, rootedAt: "somelib",
}, },
{ {
[]string{"../somelib", "../somelib"}, args: []string{"../somelib", "../somelib"},
[]*Package{&Package{ImportPath: "somelib"}}, pkgs: []*Package{&Package{ImportPath: "somelib"}},
"somelib", expected: "somelib",
false,
}, },
{ {
[]string{"../lib1", "../lib2"}, args: []string{"../lib1", "../lib2"},
[]*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}}, pkgs: []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
"gopkg.in-lib1,gopkg.in-lib2", expected: "gopkg.in-lib1,gopkg.in-lib2",
false,
}, },
{ {
[]string{"./..."}, args: []string{"./..."},
[]*Package{ pkgs: []*Package{
&Package{ImportPath: "gopkg.in/dir/lib1"}, &Package{ImportPath: "gopkg.in/dir/lib1"},
&Package{ImportPath: "gopkg.in/lib2"}, &Package{ImportPath: "gopkg.in/lib2"},
&Package{ImportPath: "gopkg.in/lib3"}, &Package{ImportPath: "gopkg.in/lib3"},
}, },
"gopkg.in-dir-lib1,gopkg.in-lib2,gopkg.in-lib3", expected: "gopkg.in",
false, rootedAt: "gopkg.in",
}, },
{ {
[]string{"std", "../lib2"}, args: []string{"std", "../lib2"},
[]*Package{}, pkgs: []*Package{},
"", expectErr: true,
true,
}, },
{ {
[]string{"all", "./"}, args: []string{"all", "./"},
[]*Package{}, pkgs: []*Package{},
"", expectErr: true,
true,
}, },
{ {
[]string{"cmd", "fmt"}, args: []string{"cmd", "fmt"},
[]*Package{}, pkgs: []*Package{},
"", expectErr: true,
true,
}, },
} }
for _, data := range testData { for _, data := range testData {
computed, err := libname(data.args, data.pkgs) func() {
if err != nil { if data.rootedAt != "" {
if !data.expectErr { tmpGopath, err := ioutil.TempDir("", "gopath")
t.Errorf("libname returned an error %q, expected a name", err.Error()) 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 { computed, err := libname(data.args, data.pkgs)
t.Errorf("libname returned %q, expected an error", computed) if err != nil {
} else { if !data.expectErr {
expected := prefix + data.expected + suffix t.Errorf("libname returned an error %q, expected a name", err.Error())
if expected != computed { }
t.Errorf("libname returned %q, expected %q", computed, expected) } 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)
}
} }
} }()
} }
} }
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