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

x/tools/gopls: improve handling for build tags #29202

Open
stamblerre opened this issue Dec 12, 2018 · 47 comments
Open

x/tools/gopls: improve handling for build tags #29202

stamblerre opened this issue Dec 12, 2018 · 47 comments

Comments

@stamblerre
Copy link
Contributor

@stamblerre stamblerre commented Dec 12, 2018

We need to handle build tags correctly in the LSP. If a user is on Linux, they should still see completions, diagnostics, etc. for files tagged with any other OS.

@glerchundi
Copy link

@glerchundi glerchundi commented Apr 24, 2019

Bitten by this also, lost an hour trying to figure out why after migrating to gopls basic functionalities didn't work...no import-organize, no format, no nothing. Afterwards I found that it's was working properly for everything except for files with build tags as mentioned in #31286.

@myitcv
Copy link
Member

@myitcv myitcv commented Apr 28, 2019

I'm wondering whether this is the right issue to become the umbrella issue for our long-running discussion about context?

@sjdweb
Copy link

@sjdweb sjdweb commented May 1, 2019

This is killing me with integration tests that have build tags. Any workarounds known?

@christiankiely
Copy link

@christiankiely christiankiely commented May 1, 2019

@sjdweb current workaround I'm using is to set the GOFLAGS environment variable. This is the configuration I'm using in VS Code:

"gopls.env": {
        "GOFLAGS": "-tags=test"
    },

@myitcv
Copy link
Member

@myitcv myitcv commented May 2, 2019

This was brought up on Tuesday's golang-tools call.

@christiankiely - the "editor level" GOFLAGS approach your describe works in some cases, but not all. Because setting the flag in that way sets the flag for all modules and packages, i.e. for the gopls instance used by the editor.

In discussions we've had thus far it seems for a complete solution we need to be able to define the sets of valid build flags at various levels:

  • Editor level (i.e. throughout editor)
  • Module level
  • Package (tree) level
  • File level

We also need:

  • the ability to specify, from within the editor, which build flags are in operation, because for a given file/package/module there might be multiple valid options
  • the ability to then pass this choice on a per request basis to gopls

The conclusion on Tuesday's call was broadly that there are other higher priority issues right now; add to that, a solution that doesn't involve LSP spec changes isn't exactly jumping out at us.

cc @ianthehat @dominikh

@breml
Copy link
Contributor

@breml breml commented May 11, 2019

Bitten by this as well. I use build tags to distinguish between normal builds and debug builds. Now VSCode reports logError redeclared in this block error and the file is constantly marked as having errors.

@gracenoah
Copy link

@gracenoah gracenoah commented May 15, 2019

Another populate use case: when using wire, there are two copies of the initializers:

  1. The template in a file with a build tag that never gets compiled
  2. The real one generated by wire with no build tags

gopls highlights them as duplicate definitions because it ignores build tags.

Is there a short term workaround in this simpler use case? Some way to make gopls ignore files with the wireinject build tag?

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented May 15, 2019

Thank you for sharing this info. We realize that this is an issue that affects a lot of people, so we're trying to come up with a viable solution. It's a complicated problem, but to start, I think we can try to disable diagnostics on files that would be excluded given your GOOS/GOARCH.

@evanphx
Copy link
Contributor

@evanphx evanphx commented May 25, 2019

As a data point, I'm experiencing this today in any package that picks up os/user because it uses build tags to decide how to wire in OS user lookup. In my case, it's that analysis fails because cgoLookupHost isn't defined as files aren't being evaluated.

I understand that you'd like for gopls to allow for reading and analysis of files intended for a different GOOS that the one that the editor is on, but given how packages are structured, you'd having to perform analysis on the matrix of build tags. That seems.... time consuming at best. Plumbing through a default tag set seems like an easy way to at least get folks moving again.

I'm happy to look into how to do that if need be! Please just let me know.

@evanphx
Copy link
Contributor

@evanphx evanphx commented May 25, 2019

Looks like it's also firing from net looking like:

/usr/local/Cellar/go/1.12/libexec/src/net/lookup_unix.go:81:24: undeclared name: cgoLookupHost

@zchee
Copy link
Contributor

@zchee zchee commented May 26, 2019

@evanphx I also found this issue.
The workaround is launch gopls use CGO_ENABLED=0 or something. Note that might be vscode can't that workaround AFAIK. Also not solved if set CGO_ENABLED=0 to env. Because it is late to place.
#29202 (comment)

Now I develop the client side for IDE written in Go, it's implemented set some env to launch gopls binary using set to exec.Command.Env. I did solve the use it.
Anyway, We should including CGO_ENABLED=0 to gopls send Build info.

@evanphx
Copy link
Contributor

@evanphx evanphx commented May 26, 2019

@zchee Ah! That makes a lot of sense, I'll start it with CGO_ENABLED=0 and see how it works.

@zchee
Copy link
Contributor

@zchee zchee commented May 27, 2019

@evanphx
Also, I was send CL (but I think still not user friendly) for support build tags.
https://go-review.googlesource.com/c/tools/+/178782
It solved if your code needs any build tags such as purego, static.

@zchee
Copy link
Contributor

@zchee zchee commented May 27, 2019

@evanphx
FYI, ref for your issue root cause:
#31705

@zchee
Copy link
Contributor

@zchee zchee commented Jun 4, 2019

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Jun 5, 2019

I think we will still need special handling for build tags so that users don't need special configurations to get gopls features in files tagged for different build systems.

@cyberbeast
Copy link

@cyberbeast cyberbeast commented Aug 6, 2020

@stamblerre What's the exact property that needs to be set in settings.json (vscode) to switch build tags?

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Aug 6, 2020

I would suggest the work-around described in this comment: #29202 (comment).

@ericwq
Copy link

@ericwq ericwq commented Sep 9, 2020

for a variable being overwritten based on build constraints, I tried every suggested config in this thread. it doesn't work.

here is the overwritten case:

  • when edit a file, such as internal/lsp/lsprpc/lsprpc.go ,
  • you see a statement in line 289, (in func connectToRemote): "network, address = autoNetworkAddress(goplsPath, inAddr)",
  • now, to find the autoNetworkAddress func, you send a 'definition' query to the gopls server.
  • in current implementation, 'definition' query will return the internal/lsp/lsprpc/autostart_default.go result. and the editor jump to that file directly. this implementation will mislead the developer. i checked the code several times and finally notice the 'build tags'

the propose is to return the internal/lsp/lsprpc/autostart_posix.go , the behavior of 'definition' query should consider the 'build tags', in this case, it is "// +build darwin dragonfly freebsd linux netbsd openbsd solaris".

any suggestion on this case? @stamblerre

@clouedoc
Copy link

@clouedoc clouedoc commented Oct 22, 2020

To be able to edit windows-specific golang code ("xxx_windows.go") requiring windows-only golang packages on my OSX machine, I had to add this to my VSCode settings:

"go.toolsEnvVars": {
    "GOOS": "windows"
 }

@Merrit
Copy link

@Merrit Merrit commented Nov 14, 2020

"gopls.env": {
        "GOFLAGS": "-tags=test"
    },

Where does this go? I tried settings.json and I get:

Unknown Configuration Setting

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Nov 14, 2020

@Merrit: That's correct--the unknown configuration setting message is a warning, but it will still work.

@Merrit
Copy link

@Merrit Merrit commented Nov 14, 2020

I see. Am I misunderstanding the purpose then?

For example in one of my _linux.go files I am still getting No packages found for open file, unable to access functions from this file, etc.

If I add // +build windows everything works as expected.

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Nov 16, 2020

Are you working on Windows / adding the Windows tag to the Linux file? OS-specific tags are detected based on your OS, so unless you set GOFLAGS to -tags=linux, you won't get editor features working for the _linux.go files.

@Merrit
Copy link

@Merrit Merrit commented Nov 16, 2020

Yes, currently working on Windows & having issues working with *_linux.go files. Not sure why I would want to be unable to reference or work on Linux files just because I am on Windows, or vice versa.

Setting this in settings.json seems to have it working, so far:

  "gopls.env": {
    "GOFLAGS": "-tags=linux"
  },

Thank you!

@Merrit
Copy link

@Merrit Merrit commented Nov 16, 2020

Spoke too soon.

Editor features work fine, but it then fails to run / debug.

undefined: funcFromLinuxFile

I tried adding "buildFlags": "-tags=linux" to launch.json, but that makes it try to compile the linux version which fails quite spectacularly. :)

Also tried "buildFlags": "-tags=test", "buildFlags": "-tags=!linux" and "buildFlags": "-tags '!linux test'".

Only solution so far is to just stop naming things with the *_os.go scheme, which I was given to understand was the preference for conditional compilation. FYI, naming the files featureLinux.go and leaving it be works just fine. Adding // +build linux to that same file breaks things the same as using the *_linux.go naming scheme.

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Nov 16, 2020

Not sure why I would want to be unable to reference or work on Linux files just because I am on Windows, or vice versa.

This is a current limitation of gopls, and this issue is tracking improving that behavior.

I tried adding "buildFlags": "-tags=linux" to launch.json, but that makes it try to compile the linux version which fails quite spectacularly. :)

You won't actually be able to run code meant for Linux on Windows--my suggestion was just to get editor features for development purposes.

@Merrit
Copy link

@Merrit Merrit commented Nov 16, 2020

Right, I don't want to run or compile anything meant for a different OS. Just mentioning what I had tried to resolve my issue.

Ideally what I would like is:

  1. Name files by OS to take advantage of conditional compilation, ie feature_windows.go & feature_linux.go
  2. Editor features still work, eg it recognizes the packages, doesn't complain about undeclared variables or functions, etc just because those variables/functions are in a feature_linux.go when I am on Windows, or vice versa.
  3. Still be able to use VSCode's run/debug features (for the code related to the OS I am on).

Currently I can only get 2 & 3 on my list by not naming files by OS nor using the // +build _____ -- which I understand means no conditional compilation.

@FrankReh
Copy link

@FrankReh FrankReh commented Nov 27, 2020

Wanted to be able to use go generate in a directory to get a go run gen.go called and found gopls doesn't seem to work on the gen.go file because of a mix of build flags in other local files. Can I work around this by invoking vim on gen.go with an environment variable set to something for the benefit of gopls or is moving the gen.go into its own directory my best option?

gopls definition does work from a file that has an ignore build tag, but not if a plain go file in the same directory exists.

$ cat -n gen.go 
     1	// +build ignore
     2	
     3	package main
     4	
     5	import (
     6		"fmt"
     7	)
     8	
     9	func main() {
    10		fmt.Println("Hello world!")
    11	}
$ gopls definition gen.go:10:10
gopls: /<snip>/gen.go:10:10: no packages returned: packages.Load error
$ rm config.go
$ gopls definition gen.go:10:10
/<snip>/go1.15.5/src/fmt/print.go:273:6-13: defined here as func fmt.Println<snip>

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Dec 1, 2020

The command line doesn't really give you much configurability, but you can set the GOFLAGS environment variable before running the gopls command. Otherwise, you can configure gopls.buildFlags or GOFLAGS as described in the examples above.

@VikingPingvin
Copy link

@VikingPingvin VikingPingvin commented Dec 17, 2020

I am facing this issue as well, appending settings.json with "gopls.env": { "GOFLAGS": "-tags=debug" },does not resolve the issue for me.

In my case I have two files thermal.go and thermal_mock.go, with build tags // +build !debug and // +build debug respectively, so I can mock target HW specific functions.

My biggest issue is that Intellisense completely stopped working in the _mock version (as in, worked the other day, next day poof) , and the gopls.env in settings.json didn't help either.

Go 1.15.5, gopls v0.6.0

Any follow up on the issue?

Edit: Loss of intellisense can be temporarily fixed by removing the build tag instruction, saving and readding it.

@stamblerre
Copy link
Contributor Author

@stamblerre stamblerre commented Dec 18, 2020

In my case I have two files thermal.go and thermal_mock.go, with build tags // +build !debug and // +build debug respectively, so I can mock target HW specific functions.

My biggest issue is that Intellisense completely stopped working in the _mock version (as in, worked the other day, next day poof) , and the gopls.env in settings.json didn't help either.

Would be happy to help investigate this, but please file a new issue with the following information: https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md.

@dylankb
Copy link

@dylankb dylankb commented Jan 9, 2021

Note for VSCode settings.json in case it's helpful. A bit after upgrading gopls to 0.6.2 I noticed some No packages found for open file... errors. I was using GOFLAGS to list build tags.

"gopls": {
  "env": {
    "GOFLAGS": "-tags=<tag1>,<tag2>"
  },
},

Switching to the go.buildFlags configuration below seemed to solve the problem. I no longer use GOFLAGS.

go.buildFlags: "<tag1>,<tag2>",

There might have also been a vscode-go release around the time I bumped my gopls version, but not sure.

@kevlar700
Copy link

@kevlar700 kevlar700 commented Feb 4, 2021

The workarounds here didn't work for me.

I found
env GOOS="openbsd" code

Worked for me at the editor instance level

P.s. Irrelevant tip: if you also set HISTFILE and open a module folder after "code" then you can have dedicated terminal history and a project folder opened together.

@serezlan
Copy link

@serezlan serezlan commented Jul 8, 2021

Hello,

I'm facing this issue on linux using emacs. Have tried suggestions above and the one that is working is to delete and re-adding build tag line.
I also tried using VS Code with the same result.

@jalseth
Copy link

@jalseth jalseth commented Jul 17, 2021

I was finally able to get this working in VS Code by using the following and restarting VS Code.

{
    "go.buildTags": "tag1,tag2"
}

@laeo
Copy link

@laeo laeo commented Aug 14, 2021

I think gopls shouldn't care about build constraints, or it only cares about the file I'm editing, which I call "constraint aware".

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