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 clean doesn't remove binaries installed by go install module@version #65687

Open
Rican7 opened this issue Feb 13, 2024 · 10 comments
Open
Labels
GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@Rican7
Copy link

Rican7 commented Feb 13, 2024

Go version

go version go1.21.7 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/tnsuarez/Library/Caches/go-build'
GOENV='/Users/tnsuarez/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/tnsuarez/Development/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/tnsuarez/Development/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.21.7/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.21.7/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.21.7'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/gd/n720k8816r7c0bnv44nb9crw0000gp/T/go-build4251940867=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

I installed a binary via go install and then was unable to use the same tool to uninstall/clean the installed package binary.

I had to manually remove the binary via rm.

What did you see happen?

~ $ go install github.com/Rican7/define@latest
~ $ which define
/Users/tnsuarez/Development/go/bin/define
~ $ go clean github.com/Rican7/define@latest
package github.com/Rican7/define@latest: can only use path@version syntax with 'go get' and 'go install' in module-aware mode
~ $ go clean github.com/Rican7/define
no required module provides package github.com/Rican7/define: go.mod file not found in current directory or any parent directory; see 'go help modules'
~ $ go clean -i github.com/Rican7/define
no required module provides package github.com/Rican7/define: go.mod file not found in current directory or any parent directory; see 'go help modules'
~ $ go clean -i github.com/Rican7/define@latest
package github.com/Rican7/define@latest: can only use path@version syntax with 'go get' and 'go install' in module-aware mode

What did you expect to see?

I expected that a go clean github.com/Rican7/define would remove the package binary that it had installed.

It would likely make sense to have the command maybe be go clean -i github.com/Rican7/define@latest, but maybe the version suffix is awkward?

The version suffix is what changes the behavior of go install to no longer consider the current module (go.mod) defined version, so there would be symmetry there, but also having to specify the version to uninstall might be awkward.

I couldn't find anything related to this, beyond maybe #50261.

Also, a quick search shows that there seems to be a lot of confusion around this very (lack of?) behavior:

@gophun
Copy link

gophun commented Feb 13, 2024

It's just a binary file. Why insist in invoking a special command when you can just rm it?

@Rican7
Copy link
Author

Rican7 commented Feb 13, 2024

@gophun For the same reason go clean -i even exists in the first place.

The fact that it doesn't work seemed like a bug to me.

In a practical sense:

  1. Because the install location of the binary is dependent on numerous environmental factors and it's install location (which isn't reported at install time) is otherwise not known to the user. So manually performing the deletion could be non-obvious to a user.
  2. For completeness. Allowing the install, but not the deletion, is asymmetric.
  3. Having the same environment that determines that location to install and remove allows for easier scripting and automation via the same defined environmental controls.
  4. Again, because the command already exists, and just doesn't seem to be working for this case.

@rittneje
Copy link

rittneje commented Feb 13, 2024

The docs for go install say:

Executables (main packages) are installed to the directory named by the GOBIN environment variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH environment variable is not set.

And the docs for go clean say:

Clean removes object files from package source directories. The go command builds most objects in a temporary directory, so go clean is mainly concerned with object files left by other tools or by manual invocations of go build.

If a package argument is given or the -i or -r flag is set, clean removes the following files from each of the source directories corresponding to the import paths:

_obj/ old object directory, left from Makefiles
_test/ old test directory, left from Makefiles
_testmain.go old gotest file, left from Makefiles
test.out old test log, left from Makefiles
build.out old test log, left from Makefiles
*.[568ao] object files, left from Makefiles

DIR(.exe) from go build
DIR.test(.exe) from go test -c
MAINFILE(.exe) from go build MAINFILE.go
*.so from SWIG

So it would seem that go clean is functioning properly, since the executable is not in the source directory.

Also, I don't think something like go clean github.com/Rican7/define@latest should work, given that go install doesn't seem to record the version it installed anywhere, and I think it would be confusing if go clean github.com/Rican7/define@v1.0.0 were to delete what go install github.com/Rican7/define@v1.0.1 installs.

I can see the argument for go clean github.com/Rican7/define working, but then the lack of symmetry could be confusing.

@thanm thanm added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. GoCommand cmd/go labels Feb 13, 2024
@thanm
Copy link
Contributor

thanm commented Feb 13, 2024

@bcmills @matloob per owners.

@matloob
Copy link
Contributor

matloob commented Feb 13, 2024

I think this might be a documentation issue. The words (what 'go install' would create) applied to what go install created before the new go install module@version functionality was added. We should maybe remove that phrase.

@meling
Copy link

meling commented Feb 14, 2024

I guess it would not hurt if go install reported the path in which the binary was installed. Users new to Go often don’t know about GOPATH/bin.

@Rican7
Copy link
Author

Rican7 commented Feb 14, 2024

I guess it would not hurt if go install reported the path in which the binary was installed.

That could be helpful, yea.

Users new to Go often don’t know about GOPATH/bin.

Especially since setting GOPATH is no longer required with module mode.

@thanm
Copy link
Contributor

thanm commented Feb 15, 2024

I guess it would not hurt if go install reported the path in which the binary was installed.

One easy but slightly hacky way to do this: install it, then immediately run install -n:

$ go install golang.org/x/debug/cmd/viewcore@latest
$ go install -n golang.org/x/debug/cmd/viewcore@latest
touch /Users/thanm/go1/bin/viewcore
$ 

@bcmills
Copy link
Contributor

bcmills commented Feb 15, 2024

I don't think something like go clean github.com/Rican7/define@latest should work, given that go install doesn't seem to record the version it installed anywhere, and I think it would be confusing if go clean github.com/Rican7/define@v1.0.0 were to delete what go install github.com/Rican7/define@v1.0.1 installs.

The installed version should be recorded in a metadata block in the binary (compare go version -m). So I think it would actually be feasible to make go clean -i github.com/Rican7/define@v1.0.1 only clean v1.0.1 — but I also think that would be a confusing UX.

That said, I do think it would be reasonable for go clean -i github.com/Rican7/define@v1.0.1 to unconditionally remove the binary at the location that would be installed by go install github.com/Rican7/define@v1.0.1, even if the version doesn't match. That's not fundamentally different from what should happen if, say, you were to run go install github.com/Rican7/define@v1.0.1 before that call to go clean -i.

@bcmills
Copy link
Contributor

bcmills commented Feb 15, 2024

I guess it would not hurt if go install reported the path in which the binary was installed. Users new to Go often don’t know about GOPATH/bin.

See:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GoCommand cmd/go 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

7 participants