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: go build produces binaries differently when package name has a trailing slash #24456

Closed
lrewega opened this issue Mar 20, 2018 · 9 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@lrewega
Copy link

lrewega commented Mar 20, 2018

What version of Go are you using (go version)?

go version go1.10 darwin/amd64

Does this issue reproduce with the latest release?

Yes. I cannot reproduce it with an older release.

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/lrewega/Library/Caches/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/lrewega/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.10/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.10/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/yl/x9t8hwnx75x8z9zhbywrq6cr0000gn/T/go-build673137632=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

$ cat $GOPATH/src/experiments/hello/main.go
package main

import "fmt"

var Subject string = "world"

func main() {
        fmt.Println("hello", Subject)
}

$ go build -o hello main.go
$ ./hello
hello world

$ go build -o hello -ldflags "-X main.Subject=universe" main.go
$ ./hello
hello universe
$ go tool nm hello | grep ' main.Subject'
 1135360 D main.Subject
 10d1670 R main.Subject.str

$ go build -o hello -ldflags "-X main.Subject=universe" experiments/hello
$ ./hello
hello universe
$ go tool nm hello | grep ' main.Subject'
 1135360 D main.Subject
 10d1670 R main.Subject.str

$ go build -o hello -ldflags "-X main.Subject=universe" experiments/hello/
$ ./hello
hello world
$ go tool nm hello | grep ' main.Subject'
 1135360 D main.Subject

Notice in the last case, when the package is specified with a trailing slash, the read-only data segment for main.Subject is no longer present, and the flags passed to the linker no longer apply.

What did you expect to see?

hello universe

What did you see instead?

hello world

I could not reproduce this with go1.9.1 or go1.9.2 -- everything works as expected with older versions.

@agnivade
Copy link
Contributor

Adding a '.' before your path fixes this.

go build -o hello -ldflags "-X main.Subject=universe" ./experiments/hello/

The compiler would have thrown a proper error if you would have done this inside a proper github.com/user/project path.

I get this when I try to compile without the '.' for funnel.

09:30:47-agniva-~/play/go/src/github.com/agnivade/funnel$go build -v -ldflags "-X main.Hello=universe" cmd/funnel/
can't load package: package cmd/funnel: cannot find package "." in:
	/usr/local/go/src/cmd/funnel

@lrewega
Copy link
Author

lrewega commented Mar 20, 2018

Thanks @agnivade. Indeed the issue reproduces with a "proper" package path:

Works as expected:

$ go build -v -o hello -ldflags "-X main.Subject=universe" github.com/lrewega/hello
$ ./hello
hello universe

Doesn't work with trailing slash:

$ go build -v -o hello -ldflags "-X main.Subject=universe" github.com/lrewega/hello/
$ ./hello
hello world

In my example, the import path was experiments/hello, so the source is located in $GOPATH/src/experiments/hello as usual.

The . prefix only works if the source is relative to your current working directory. Indeed, if I build from the folder above hello it works as you describe:

$ go build -v -o xhello -ldflags "-X main.Subject=universe" ./hello/
$ ./xhello
hello universe

but that remains an insufficient workaround.

I also noticed the issue can be reproduced with a trailing . path element:

$ go build -v -o hello -ldflags "-X main.Subject=universe" github.com/lrewega/hello/.
$ ./hello
hello world

but not with ...!

go build -v -o hello -ldflags "-X main.Subject=universe" github.com/lrewega/hello/...
$ ./hello
hello universe

The ... suffix only works if there is a single package found, of course.

@andybons
Copy link
Member

@lrewega in your original report, you said in response to “Does this issue reproduce with the latest release?”:

Yes. I cannot reproduce it with an older release.

The “Yes“ and “I cannot reproduce” contradict each other. Is this a regression from older releases?

@rsc @ianlancetaylor

@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 20, 2018
@andybons andybons added this to the Go1.11 milestone Mar 20, 2018
@lrewega
Copy link
Author

lrewega commented Mar 20, 2018

@andybons yes I believe it is a regression from older releases. I can only produce it with go1.10. Sorry for being unclear.

@andybons
Copy link
Member

No problem. Thank you for clarifying.

@0xmohit
Copy link
Contributor

0xmohit commented Mar 21, 2018

This appears to be a side-effect of 5993251.

@lrewega
Copy link
Author

lrewega commented Mar 21, 2018

@0xmohit indeed, it seems to be related to how package-specific flags are provided.

In the case where a canonical package name is provided (or has the /... suffix), then the flags apply correctly.

In the case where a path is provided which appears to be a relative path (such as a trailing / or . or .. path element), the flags are not provided as one would expect.

It seems you can work around this by using the facilities added in 5993251: use =pattern= to specify the package the flags are intended for. For example:

$ go build -v -o hello -ldflags="github.com/lrewega/hello=-X main.Subject=universe" github.com/lrewega/hello/.
$ ./hello
hello universe

Note that setting variables in dependency packages produces the same results.

Somewhat counterintuitively, setting a variable in a dependency package and specifying a pattern of that dependency package does not work:

$ go build -v -o hello -ldflags="github.com/lrewega/hello/version=-X github.com/lrewega/hello/version.Version=12345" github.com/lrewega/hello/.
$ ./hello
version:

but setting the pattern to that of the target command package does work:

$ go build -v -o hello -ldflags="github.com/lrewega/hello=-X github.com/lrewega/hello/version.Version=12345" github.com/lrewega/hello/.
$ ./hello
version: 12345

I can't tell if this is intentional or not.

@rsc
Copy link
Contributor

rsc commented Aug 10, 2018

Duplicate of #24750, #24232, and #25046, but all those were closed with the wrong fix (#25878) leaving this one open. Will send a fix that handles them all and roll back the fix from CL 109235.

@gopherbot
Copy link

Change https://golang.org/cl/129059 mentions this issue: cmd/go: fix -gcflags, -ldflags not applying to current directory

@golang golang locked and limited conversation to collaborators Aug 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

6 participants