Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: can't link programs that depend on transitive binary only packages #23473

Closed
ianlancetaylor opened this issue Jan 18, 2018 · 1 comment
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@ianlancetaylor
Copy link
Contributor

At current tip (git revision 4b3a3bd) building a program that depends on a transitive link of binary only packages does not work, because importcfg.link does not represent all the dependencies.

Written in the form of a test in cmd/go/go_test.go:

func TestBinaryOnlyLink(t *testing.T) {
	tg := testgo(t)
	defer tg.cleanup()
	tg.parallel()
	tg.makeTempdir()
	tg.setenv("GOPATH", tg.path("."))

	// Build the packages to get the binaries,
	// then change them to be binary-only.
	tg.tempFile("src/p1/p1.go", `package p1; import "p2"; func F() { p2.G() }`)
	tg.tempFile("src/p2/p2.go", `package p2; func G() {}`)
	tg.run("install", "p1", "p2")
	tg.must(os.Remove(tg.path("src/p1/p1.go")))
	tg.must(os.Remove(tg.path("src/p2/p2.go")))
	tg.tempFile("src/p1/binary.go", `//go:binary-only-package

	package p1`)
	tg.tempFile("src/p2/binary.go", `//go:binary-only-package

	package p2`)

	tg.tempFile("src/main/main.go", `package main; import "p1"; func main() { p1.F() }`)
	tg.run("build", "-o", tg.path("main"), "main")
}

This fails with

--- FAIL: TestBinaryOnlyLink (0.07s)
	go_test.go:4059: running testgo [install p1 p2]
	go_test.go:4070: running testgo [build -o /tmp/gotest226647203/main main]
	go_test.go:4070: standard error:
	go_test.go:4070: # main
		cannot find package p2 (using -importcfg)
		/home/iant/go/pkg/tool/linux_amd64/link: cannot open file : open : no such file or directory
		
	go_test.go:4070: go [build -o /tmp/gotest226647203/main main] failed unexpectedly: exit status 2

The problem is that the importcfg.link file describes how to find p1.a, but not how to find p2.a. The internal Package struct built for p1 does not list p2 as a dep (since p1 is binary only) so (*Builder).addTransitiveLinkDeps does not add p2 as a Dep, so it is not added to importcfg.link.

CC @rsc

@ianlancetaylor ianlancetaylor added NeedsFix The path to resolution is known, but the work has not been done. release-blocker labels Jan 18, 2018
@ianlancetaylor ianlancetaylor added this to the Go1.10 milestone Jan 18, 2018
@rsc
Copy link
Contributor

rsc commented Jan 22, 2018

Unfortunate, but working as documented: https://tip.golang.org/doc/go1.10.

Many details of the go build implementation have changed to support these improvements. One new requirement implied by these changes is that binary-only packages must now declare accurate import blocks in their stub source code, so that those imports can be made available when linking a program using the binary-only package. For more details, see go help filetype.

And go help filetype:

Non-test Go source files can also include a //go:binary-only-package comment, indicating that the package sources are included for documentation only and must not be used to build the package binary. This enables distribution of Go packages in their compiled form alone. Even binary-only packages require accurate import blocks listing required dependencies, so that those dependencies can be supplied when linking the resulting command.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

3 participants