mirror of
https://github.com/golang/go
synced 2024-09-29 22:14:29 -06:00
cmd/go: fix bad shared lib name with buildmode=shared
Use import paths of packages to build a shared lib name. Use arguments for meta-packages 'std', 'cmd', and 'all'. Fixes #12236 Change-Id: If274d63301686ef34e198287eb012f9062541ea0 Reviewed-on: https://go-review.googlesource.com/13921 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
148b13c3bb
commit
c5aa53c8c5
@ -480,7 +480,12 @@ func runBuild(cmd *Command, args []string) {
|
|||||||
|
|
||||||
var a *action
|
var a *action
|
||||||
if buildBuildmode == "shared" {
|
if buildBuildmode == "shared" {
|
||||||
a = b.libaction(libname(args), pkgsFilter(packages(args)), modeBuild, depMode)
|
pkgs := pkgsFilter(packages(args))
|
||||||
|
if libName, err := libname(args, pkgs); err != nil {
|
||||||
|
fatalf("%s", err.Error())
|
||||||
|
} else {
|
||||||
|
a = b.libaction(libName, pkgs, modeBuild, depMode)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
a = &action{}
|
a = &action{}
|
||||||
for _, p := range pkgsFilter(packages(args)) {
|
for _, p := range pkgsFilter(packages(args)) {
|
||||||
@ -504,28 +509,49 @@ See also: go build, go get, go clean.
|
|||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isMetaPackage checks if name is a reserved package name that expands to multiple packages
|
||||||
|
func isMetaPackage(name string) bool {
|
||||||
|
return name == "std" || name == "cmd" || name == "all"
|
||||||
|
}
|
||||||
|
|
||||||
// libname returns the filename to use for the shared library when using
|
// libname returns the filename to use for the shared library when using
|
||||||
// -buildmode=shared. The rules we use are:
|
// -buildmode=shared. The rules we use are:
|
||||||
// 1) Drop any trailing "/..."s if present
|
// Use arguments for special 'meta' packages:
|
||||||
// 2) Change / to -
|
// std --> libstd.so
|
||||||
// 3) Join arguments with ,
|
// std cmd --> libstd,cmd.so
|
||||||
// So std -> libstd.so
|
// Use import paths for other cases, changing '/' to '-':
|
||||||
// a b/... -> liba,b.so
|
// somelib --> libsubdir-somelib.so
|
||||||
// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
|
// ./ or ../ --> libsubdir-somelib.so
|
||||||
func libname(args []string) string {
|
// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
|
||||||
|
// ./... ---> libpkg1,pkg2.so - subset of all import paths
|
||||||
|
// Name parts are joined with ','.
|
||||||
|
func libname(args []string, pkgs []*Package) (string, error) {
|
||||||
var libname string
|
var libname string
|
||||||
for _, arg := range args {
|
appendName := func(arg string) {
|
||||||
arg = strings.TrimSuffix(arg, "/...")
|
|
||||||
arg = strings.Replace(arg, "/", "-", -1)
|
|
||||||
if libname == "" {
|
if libname == "" {
|
||||||
libname = arg
|
libname = arg
|
||||||
} else {
|
} else {
|
||||||
libname += "," + arg
|
libname += "," + arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var haveNonMeta bool
|
||||||
|
for _, arg := range args {
|
||||||
|
if isMetaPackage(arg) {
|
||||||
|
appendName(arg)
|
||||||
|
} else {
|
||||||
|
haveNonMeta = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(libname) == 0 { // non-meta packages only. use import paths
|
||||||
|
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")
|
||||||
|
}
|
||||||
// TODO(mwhudson): Needs to change for platforms that use different naming
|
// TODO(mwhudson): Needs to change for platforms that use different naming
|
||||||
// conventions...
|
// conventions...
|
||||||
return "lib" + libname + ".so"
|
return "lib" + libname + ".so", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runInstall(cmd *Command, args []string) {
|
func runInstall(cmd *Command, args []string) {
|
||||||
@ -558,7 +584,11 @@ func runInstall(cmd *Command, args []string) {
|
|||||||
b.init()
|
b.init()
|
||||||
var a *action
|
var a *action
|
||||||
if buildBuildmode == "shared" {
|
if buildBuildmode == "shared" {
|
||||||
a = b.libaction(libname(args), pkgs, modeInstall, modeInstall)
|
if libName, err := libname(args, pkgs); err != nil {
|
||||||
|
fatalf("%s", err.Error())
|
||||||
|
} else {
|
||||||
|
a = b.libaction(libName, pkgs, modeInstall, modeInstall)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
a = &action{}
|
a = &action{}
|
||||||
var tools []*action
|
var tools []*action
|
||||||
|
@ -353,7 +353,7 @@ func importPathsNoDotExpansion(args []string) []string {
|
|||||||
} else {
|
} else {
|
||||||
a = path.Clean(a)
|
a = path.Clean(a)
|
||||||
}
|
}
|
||||||
if a == "all" || a == "std" || a == "cmd" {
|
if isMetaPackage(a) {
|
||||||
out = append(out, allPackages(a)...)
|
out = append(out, allPackages(a)...)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -554,7 +554,7 @@ func allPackages(pattern string) []string {
|
|||||||
func matchPackages(pattern string) []string {
|
func matchPackages(pattern string) []string {
|
||||||
match := func(string) bool { return true }
|
match := func(string) bool { return true }
|
||||||
treeCanMatch := func(string) bool { return true }
|
treeCanMatch := func(string) bool { return true }
|
||||||
if pattern != "all" && pattern != "std" && pattern != "cmd" {
|
if !isMetaPackage(pattern) {
|
||||||
match = matchPattern(pattern)
|
match = matchPattern(pattern)
|
||||||
treeCanMatch = treeCanMatchPattern(pattern)
|
treeCanMatch = treeCanMatchPattern(pattern)
|
||||||
}
|
}
|
||||||
|
@ -71,3 +71,95 @@ func TestParseMetaGoImports(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSharedLibName(t *testing.T) {
|
||||||
|
// TODO(avdva) - make these values platform-specific
|
||||||
|
prefix := "lib"
|
||||||
|
suffix := ".so"
|
||||||
|
testData := []struct {
|
||||||
|
args []string
|
||||||
|
pkgs []*Package
|
||||||
|
expected string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
[]string{"std"},
|
||||||
|
[]*Package{},
|
||||||
|
"std",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"std", "cmd"},
|
||||||
|
[]*Package{},
|
||||||
|
"std,cmd",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{},
|
||||||
|
[]*Package{&Package{ImportPath: "gopkg.in/somelib"}},
|
||||||
|
"gopkg.in-somelib",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"./..."},
|
||||||
|
[]*Package{&Package{ImportPath: "somelib"}},
|
||||||
|
"somelib",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"../somelib", "../somelib"},
|
||||||
|
[]*Package{&Package{ImportPath: "somelib"}},
|
||||||
|
"somelib",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"../lib1", "../lib2"},
|
||||||
|
[]*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
|
||||||
|
"gopkg.in-lib1,gopkg.in-lib2",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"./..."},
|
||||||
|
[]*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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"std", "../lib2"},
|
||||||
|
[]*Package{},
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"all", "./"},
|
||||||
|
[]*Package{},
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"cmd", "fmt"},
|
||||||
|
[]*Package{},
|
||||||
|
"",
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user