golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.98k stars 17.67k forks source link

cmd/go: GOOS=js GOARCH=wasm go build -o [non-empty parent dir] ./... fails on Windows host #37472

Closed Gregory-Ledray closed 4 years ago

Gregory-Ledray commented 4 years ago

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

$ go version
go version go1.14 windows/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
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\gledr\AppData\Local\go-build
set GOENV=C:\Users\gledr\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\gledr\Polyapp_Apps\gocode
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=C:\Users\gledr\Polyapp_Apps\gocode\src\gitlab.com\polyapp-open-source\poly\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\gledr\AppData\Local\Temp\go-build442293962=/tmp/go-build -gno-record-gcc-switches

What did you do?

I was checking out the changes in #14295 and they work great most of the time, but I might have found an edge case where they fail.

The changes in #14295 work great with regular GOOS and GOARCH on non-empty directories (nice work!): ``` gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ go list ./... gitlab.com/polyapp-open-source/poly/testdata/cmd gitlab.com/polyapp-open-source/poly/testdata/cmd/hello gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ ls ./cmd hello main.go wasm1 wasm2 wasm3 gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ go build -o ./cmd ./... gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ ls ./cmd cmd.exe hello hello.exe main.go wasm1 wasm2 wasm3 ```

But doesn't work with GOOS=js GOARCH=wasm

gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion)
$ GOOS=js GOARCH=wasm go list ./...
gitlab.com/polyapp-open-source/poly/testdata/cmd
gitlab.com/polyapp-open-source/poly/testdata/cmd/hello
gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm1
gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm2
gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm3

gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion)
$ ls ./cmd
hello  main.go  wasm1  wasm2  wasm3

gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion)
$ GOOS=js GOARCH=wasm go build -o ./cmd ./...
go build gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm1: build output "cmd\\wasm1" already exists and is a directory
go build gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm2: build output "cmd\\wasm2" already exists and is a directory
go build gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm3: build output "cmd\\wasm3" already exists and is a directory
go build gitlab.com/polyapp-open-source/poly/testdata/cmd/hello: build output "cmd\\hello" already exists and is a directory
It works great with GOOS=js GOARCH=wasm if I make a new directory: ``` gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ ls ./cmd hello main.go wasm1 wasm2 wasm3 gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ ls ./bin ls: cannot access './bin': No such file or directory gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ GOOS=js GOARCH=wasm go list ./... gitlab.com/polyapp-open-source/poly/testdata/cmd gitlab.com/polyapp-open-source/poly/testdata/cmd/hello gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm1 gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm2 gitlab.com/polyapp-open-source/poly/testdata/cmd/wasm3 gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ mkdir ./bin gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ GOOS=js GOARCH=wasm go build -o ./bin ./... gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ ls ./bin cmd hello wasm1 wasm2 wasm3 ```
And it works great if I rebuild into the bin directory: ``` gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ GOOS=js GOARCH=wasm go build -o ./bin ./... gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ rm ./bin/cmd ./bin/hello ./bin/wasm2 gledr@LAPTOP-AH6IAHBO MINGW64 ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata (CI-expansion) $ GOOS=js GOARCH=wasm go build -o ./bin ./... ```

Is this intended to work with non-empty parent directories of the binaries? Why does it work with GOOS=windows GOARCH=amd64 but not GOOS=js GOARCH=wasm?

My directory structure lives inside $GOPATH at ~/Polyapp_Apps/gocode/src/gitlab.com/polyapp-open-source/poly/testdata because, setting the exact issue aside, I'm writing some tools to make linting, testing, building, and running my multi-arch. programs a bit easier. ``` testdata/ cmd/ hello/ main.go main_test.go wasm1/ main_js_wasm.go wasm2/ main_js_wasm.go wasm3/ main.go main.go ```
Here are my test files in order of the directory structure. Some files have perhaps changed a bit since I ran the commands above - I don't recall if the test file existed before testdata/cmd/hello/main.go ``` package main import ( "fmt" "os" ) func main() { fmt.Println("Hello from poly/testdata/cmd/hello/main.go") osCheck() } // osCheck returns true for success using syscalls and false otherwise func osCheck() bool { _, err := os.Stat(".") if err != nil { fmt.Println("os.Stat failed: " + err.Error()) return false } return true } ``` testdata/cmd/hello/main_test.go ``` package main import "testing" func TestOsCheck(t *testing.T) { chk := osCheck() if chk == false { t.Fatal("couldn't stat") } } ``` testdata/cmd/wasm1/main_js_wasm.go ``` // +build js package main import "fmt" func main() { fmt.Println("hello from testdata/cmd/wasm1/main_js_wasm.go") } ``` testdata/cmd/wasm2/main_js_wasm.go ``` // +build js package main import "fmt" func main() { fmt.Println("hello from testdata/cmd/wasm2/main_js_wasm.go") } ``` testdata/cmd/wasm3/main.go ``` // +build js package main import "fmt" func main() { fmt.Println("Hello from testdata/cmd/wasm3/main.go") } ``` testdata/cmd/main.go ``` package main import "fmt" func main() { fmt.Println("Hello from poly/testdata/cmd/main.go") } ```
bcmills commented 4 years ago

CC @jayconrod @matloob @neelance @cherrymui

bcmills commented 4 years ago

Looking at your go env output, you appear to be running the go build command on a Windows host? That's probably a relevant detail.

cherrymui commented 4 years ago

$ GOOS=js GOARCH=wasm go build -o ./cmd ./...

You're trying to write output files cmd/wasm1, cmd/wasm2, etc., but these paths already exist and are directories, so it cannot overwrite it, as the error message clearly stated.

Writing to any other directories where there aren't such paths should work.

Why does it work with GOOS=windows GOARCH=amd64 but not GOOS=js GOARCH=wasm?

Because cmd/wasm1, etc. are build-tagged for wasm. It doesn't build on windows.

cherrymui commented 4 years ago

Closing as this works as intended.

bcmills commented 4 years ago

Oh! The outputs for the default GOOS=windows have a .exe suffix.

That's what avoids the collision with the existing directories for non-build-tagged binaries.