TinyGo + Vim + gopls
Tags: go, tinygo, vim, lsp
Published: 2020-05-09 07:19:14


In the following GIF, gopls works well with the PyPortal (atsamd51j20a) configuration.
You can confirm that you are jump correctly to board_pyportal.go etc.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0ygbdj7he426dslsu4n7.gif)

# Introduction

Gopls does not work well on tinygo for the following reasons.

* TinyGo has its own built-in package
    * machine, device, ...
* buildtag

In this article, I will fix these problems by the following three items.
In the end, you will be able to use LSP with TinyGo.

1. Add replace directives to go.mod
2. Add go.mod to each package folder in tinygo
3. Set environment variables (GOOS + GOARCH + GOFLAGS)

## Environment

* Windows 10
* Go version go1.14.1 windows/amd64
* tinygo version 0.13.1 windows/amd64 (using go version go1.14.1 and LLVM version 10.0.1)
* gopls ead0a569305d87def8dc4ad3899a7d78432b12c6
* Vim 8.2.147
* vim-go 13af5df6a1b3bc4bdfd03e3c05fa600d1dd16de6

note: Maybe it will work the same way on non-Windows and non-Vim.

## 1. Add replace directives to go.mod

Add directives for things like machine packages that are special to tinygo.
For example, it might look something like this

```gomod
module tinygo.org/x/drivers

go 1.14

replace (
    device/sam => C:\tinygo\src\device/sam
    internal/reflectlite => C:\tinygo\src\internal/reflectlite
    internal/task => C:\tinygo\src\internal/task
    machine => C:\tinygo\src\machine
    os => C:\tinygo\src\os
    reflect => C:\tinygo\src\reflect
    runtime => C:\tinygo\src\runtime
    runtime/interrupt => C:\tinygo\src\runtime/interrupt
    runtime/volatile => C:\tinygo\src\runtime/volatile
    sync => C:\tinygo\src\sync
    testing => C:\tinygo\src\testing
)
```

## 2. Add go.mod to each package folder in tinygo

> Note: if the right-hand side of a replace directive is a filesystem path, then the target must have a go.mod file at that location. If the go.mod file is not present, you can create one with go mod init.
https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive

go.mod can be an empty file.
So, for example, in bash, you can create a go.mod like this

```
touch C:/tinygo/src/device/sam/go.mod
touch C:/tinygo/src/internal/reflectlite/go.mod
touch C:/tinygo/src/internal/task/go.mod
touch C:/tinygo/src/machine/go.mod
touch C:/tinygo/src/os/go.mod
touch C:/tinygo/src/reflect/go.mod
touch C:/tinygo/src/runtime/go.mod
touch C:/tinygo/src/runtime/interrupt/go.mod
touch C:/tinygo/src/runtime/volatile/go.mod
touch C:/tinygo/src/sync/go.mod
touch C:/tinygo/src/testing/go.mod
```

## 3. Set environment variables (GOOS + GOARCH + GOFLAGS)

When your target is a PyPortal, you can find out which environment variables to set with the following commands.

```
$ tinygo info -target pyportal
LLVM triple:       armv7em-none-eabi
GOOS:              linux
GOARCH:            arm
build tags:        cortexm baremetal linux arm sam atsamd51 atsamd51j20 atsamd51j20a pyportal tinygo gc.conservative scheduler.tasks
garbage collector: conservative
scheduler:         tasks
```

The following three things are required.

```
set GOOS=linux
set GOARCH=arm
set GOFLAGS=-tags=cortexm,baremetal,linux,arm,sam,atsamd51,atsamd51j20,atsamd51j20a,pyportal,tinygo,gc.conservative,scheduler.tasks
```

In bash, I think you can configure it as follows.

```
export GOOS=linux
export GOARCH=arm
export GOFLAGS=-tags=cortexm,baremetal,linux,arm,sam,atsamd51,atsamd51j20,atsamd51j20a,pyportal,tinygo,gc.conservative,scheduler.tasks
```

# Conclusion

* Add replace directives to go.mod
* Add go.mod to each package folder in tinygo
* Set environment variables (GOOS + GOARCH + GOFLAGS)