Commit 4e2ef7f7 authored by David Crawshaw's avatar David Crawshaw

cmd/go: add source file contents to plugin hash

It is common to have multiple plugins built from ephemeral
source files all with the same name:

	# generate main.go
	go build -buildmode=plugin -o=p1.so main.go
	# rm main.go, generate new main.go
	go build -buildmode=plugin -o=p2.so main.go
	...

These different plugins currently have the same build ID,
and hence the same package path. This means only one can be
loaded.

To remove this restriction, this commit adds the contents of the
main package source files to the plugin hash.

Fixes #19358

Change-Id: Icd42024b085feb29c09c2771aaecb85f8b528dd3
Reviewed-on: https://go-review.googlesource.com/61170
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 3d7042fb
...@@ -27,8 +27,8 @@ GOPATH=$(pwd) go build -buildmode=plugin plugin1 ...@@ -27,8 +27,8 @@ GOPATH=$(pwd) go build -buildmode=plugin plugin1
GOPATH=$(pwd) go build -buildmode=plugin plugin2 GOPATH=$(pwd) go build -buildmode=plugin plugin2
GOPATH=$(pwd)/altpath go build -buildmode=plugin plugin-mismatch GOPATH=$(pwd)/altpath go build -buildmode=plugin plugin-mismatch
GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1 GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
GOPATH=$(pwd) go build -buildmode=plugin unnamed1.go GOPATH=$(pwd) go build -buildmode=plugin -o=unnamed1.so unnamed1/main.go
GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go GOPATH=$(pwd) go build -buildmode=plugin -o=unnamed2.so unnamed2/main.go
GOPATH=$(pwd) go build host GOPATH=$(pwd) go build host
LD_LIBRARY_PATH=$(pwd) ./host LD_LIBRARY_PATH=$(pwd) ./host
......
...@@ -1671,15 +1671,8 @@ func isStale(p *Package) (bool, string) { ...@@ -1671,15 +1671,8 @@ func isStale(p *Package) (bool, string) {
return false, "" return false, ""
} }
// computeBuildID computes the build ID for p, leaving it in p.Internal.BuildID. func pkgInputFiles(p *Package) []string {
// Build ID is a hash of the information we want to detect changes in. return str.StringList(
// See the long comment in isStale for details.
func computeBuildID(p *Package) {
h := sha1.New()
// Include the list of files compiled as part of the package.
// This lets us detect removed files. See issue 3895.
inputFiles := str.StringList(
p.GoFiles, p.GoFiles,
p.CgoFiles, p.CgoFiles,
p.CFiles, p.CFiles,
...@@ -1692,6 +1685,40 @@ func computeBuildID(p *Package) { ...@@ -1692,6 +1685,40 @@ func computeBuildID(p *Package) {
p.SwigFiles, p.SwigFiles,
p.SwigCXXFiles, p.SwigCXXFiles,
) )
}
// PluginPath computes the package path for a plugin main package.
//
// This is typically the import path of the main package p, unless the
// plugin is being built directly from source files. In that case we
// combine the package build ID with the contents of the main package
// source files. This allows us to identify two different plugins
// built from two source files with the same name.
func PluginPath(p *Package) string {
if p.ImportPath != "command-line-arguments" {
return p.ImportPath
}
h := sha1.New()
fmt.Fprintf(h, "build ID: %s\n", p.Internal.BuildID)
for _, file := range str.StringList(p.GoFiles, p.CgoFiles, p.SFiles) {
data, err := ioutil.ReadFile(filepath.Join(p.Dir, file))
if err != nil {
base.Fatalf("go: %s", err)
}
h.Write(data)
}
return fmt.Sprintf("plugin/unnamed-%x", h.Sum(nil))
}
// computeBuildID computes the build ID for p, leaving it in p.Internal.BuildID.
// Build ID is a hash of the information we want to detect changes in.
// See the long comment in isStale for details.
func computeBuildID(p *Package) {
h := sha1.New()
// Include the list of files compiled as part of the package.
// This lets us detect removed files. See issue 3895.
inputFiles := pkgInputFiles(p)
for _, file := range inputFiles { for _, file := range inputFiles {
fmt.Fprintf(h, "file %s\n", file) fmt.Fprintf(h, "file %s\n", file)
} }
......
...@@ -2200,9 +2200,7 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhd ...@@ -2200,9 +2200,7 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, asmhd
pkgpath := p.ImportPath pkgpath := p.ImportPath
if cfg.BuildBuildmode == "plugin" { if cfg.BuildBuildmode == "plugin" {
if pkgpath == "command-line-arguments" { pkgpath = load.PluginPath(p)
pkgpath = "plugin/unnamed-" + p.Internal.BuildID
}
} else if p.Name == "main" { } else if p.Name == "main" {
pkgpath = "main" pkgpath = "main"
} }
...@@ -2536,11 +2534,7 @@ func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action ...@@ -2536,11 +2534,7 @@ func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action
ldflags = append(ldflags, "-s", "-w") ldflags = append(ldflags, "-s", "-w")
} }
if cfg.BuildBuildmode == "plugin" { if cfg.BuildBuildmode == "plugin" {
pluginpath := root.Package.ImportPath ldflags = append(ldflags, "-pluginpath", load.PluginPath(root.Package))
if pluginpath == "command-line-arguments" {
pluginpath = "plugin/unnamed-" + root.Package.Internal.BuildID
}
ldflags = append(ldflags, "-pluginpath", pluginpath)
} }
// If the user has not specified the -extld option, then specify the // If the user has not specified the -extld option, then specify the
......
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