WSL で Apex を使って Go の Lambda を作ったらエラーになった件とその対策

最近仕事用のメインマシンを数年ぶりに Windows にしたので WSL を使っていろいろとハマっています。

この記事の件もそのうちの一つです。

表題の通り、WSL 環境で apex を使って Go の Lambda をデプロイしたところ、デプロイ自体は問題なくできたのですが、その Lambda を実行すると以下のようなエラーが起こるようになってしまいました。

  ⨯ Error: function response: fork/exec /var/task/main: no such file or directory

どうやらデプロイされた実行ファイル(/var/task/main)が見当たらないというエラーのようです。 しかし、apex build で生成された ZIP ファイルの中身を見てみるとちゃんとファイルが存在しています。

上記のエラーメッセージをもとにネットを検索してみたところ、どうやら dynamic link されたバイナリだと、ビルド時の環境によっては実行できないことがあるようです。

解決策としては、static link するようにするとよいということです。

apex を使っているとコンパイルオプションなど気にしたことがありませんでしたが、project.json (もしくは function.json)に以下のような設定を追加することで static link 用のコンパイルオプションを指定できます。

  "hooks": {
    "build": "GOOS=linux GOARCH=amd64 go build -a -tags netgo -installsuffix netgo -ldflags='-extldflags=\"-static\"' -o main",
    "clean": "rm -f main"
  }

go build の後ろの -a -tags netgo -installsuffix netgo -ldflags='-extldflags=\"-static\"' が全て static link のために必要なオプションです。

WSL に限らず、alpine などでビルドしたバイナリも同様の問題が起こるようですので、これで直るのではないかと思います。

なお、Mac など従来このオプション指定なしでビルドしても動いていたような環境で上記オプションをつけてビルドしても問題なく static link になるようなので、私の手元では全て上記オプション指定に変更しました。