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: build -o dir ./... should build (and discard) non main packages #37378

Open
perillo opened this issue Feb 22, 2020 · 11 comments
Open

cmd/go: build -o dir ./... should build (and discard) non main packages #37378

perillo opened this issue Feb 22, 2020 · 11 comments
Labels
Milestone

Comments

@perillo
Copy link

@perillo perillo commented Feb 22, 2020

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

$ go version
go version go1.14rc1 linux/amd64

Does this issue reproduce with the latest release?

Yes.

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

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/home/manlio/.local/bin"
GOCACHE="/home/manlio/.cache/go-build"
GOENV="/home/manlio/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/manlio/.local/lib/go:/home/manlio/src/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/manlio/sdk/go1.14rc1"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/manlio/sdk/go1.14rc1/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build397314077=/tmp/go-build -gno-record-gcc-switches"
GOROOT/bin/go version: go version go1.14rc1 linux/amd64
GOROOT/bin/go tool compile -V: compile version go1.14rc1
uname -sr: Linux 5.5.4-arch1-1
/usr/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.31.
gdb --version: GNU gdb (GDB) 9.1

What did you do?

I have a module, with a main package in the module root directory and another package in a subdirectory.
A .go file in the nested package has a syntax error.

I ran the following commands

go build ./...
go build -o build/ ./...

What did you expect to see?

Both commands to report an error

# github.com/perillo/go-init/internal/data
internal/data/data.go:12:25: syntax error: unexpected { after top level declaration

What did you see instead?

Only the first command reports the syntax error.

@perillo perillo changed the title cmd/go: build -o dir ./... does not build (and discard) packages in subdirectories cmd/go: build -o dir ./... should build (and discard) non main packages Feb 22, 2020
@perillo

This comment has been minimized.

Copy link
Author

@perillo perillo commented Feb 22, 2020

A similar problem is that when there are no main packages, go build -o build/ reports an error

go build: no main packages to build

It is questionable if this is the right thing to do, but I think it is incovenient.

@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Feb 26, 2020

@bcmills bcmills added this to the Backlog milestone Feb 26, 2020
@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Feb 26, 2020

I think at least building the matching packages makes sense, although it would make the use-case in #14295 arbitrarily slower in some cases.

Jay, Michael: any thoughts?

@jayconrod

This comment has been minimized.

Copy link
Contributor

@jayconrod jayconrod commented Feb 26, 2020

No strong opinion, but I think we should keep the current behavior.

go build -o dir ./... is the simplest way to write executables to a directory. Let's not slow it down.

If the intent is to check whether packages build, there are a few ways to do that, most precisely go build -o /dev/null ./....

@perillo

This comment has been minimized.

Copy link
Author

@perillo perillo commented Feb 26, 2020

go build -o /dev/null ./... works. But why?

@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Feb 26, 2020

But why?

Because of the other bug you observed: we are failing to detect collisions when building multiple executables with the same binary name.

@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Feb 26, 2020

Hmm... The obvious workaround is to run go build ./... && go build -o dir ./..., but that will also be suboptimally slow due to #31629.

@perillo

This comment has been minimized.

Copy link
Author

@perillo perillo commented Feb 26, 2020

I asked why because, on the same module with several main packages and several non main packages, go build -o file ./... reports an error:

go build: cannot write multiple packages to non-directory file

but go build -o /dev/null ./... works fine.

Both file and /dev/null are files, so, unless I'm missing something, why go build behave differently?

@perillo

This comment has been minimized.

Copy link
Author

@perillo perillo commented Feb 27, 2020

@jayconrod I have read again the documentation of go build, for go1.14. It says:

When compiling multiple packages or a single non-main package,
build compiles the packages but discards the resulting object,
serving only as a check that the packages can be built.

I'm not sure to understand why to explicitly add or a single non-main package, but the documentation indirectly says that go build ./... can be used as a check that all the packages can be build.

Now, without the -o dir flag, executables are written in the current directory and with the -o dir flag they are written to the specified directory. So I have to disagree when you say is the simplest way to write executables to a directory. Let's not slow it down. They should have the same behavior.

$ go build -o build ./...                                                                                                                               
go build: no main packages to build
$ go build  ./...

To reduce build time, it is always possible to use -o file for each main package.

@jayconrod

This comment has been minimized.

Copy link
Contributor

@jayconrod jayconrod commented Feb 27, 2020

Both file and /dev/null are files, so, unless I'm missing something, why go build behave differently?

It's a special case. If the -o flag is os.DevNull, go build will build the packages but won't produce output files.

I think I misunderstood the reason for its existence though. I've always used it to test whether packages build without writing them anywhere. However, it's not documented. It looks like it was added as a fix for #16811, where go build -o /dev/null would actually replace /dev/null if it had permission to do so.

So nevermind, let's not rely on -o /dev/null.

(Sorry for the slow response, I typed this a few hours ago, but GitHub comments were down)

@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Feb 27, 2020

Thinking about this some more. In most repos that mix main packages and other packages, I would expect the vast majority of packages to be imported by the main ones. So, while it's true that go build -o dir ./... would possibly become slower, I don't think it would be much slower in practice.

And, for the few cases that do matter, users can always select only the main packages explicitly, using something like go build -o dir $(go list -f '{{if eq .Name "main"}}{{.ImportPath}}{{end}}' ./...).

I think it makes sense for the -o flag to be orthogonal to the package pattern. Right now it is not: -o changes the meaning of ./... to select only main packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.