High Sierraへのアップグレードでkisielk/errcheckがエラー吐いた件

かなり久々に記事書きます。[yukinasu](https://twitter.com/yukinasu715)です。
今更ですが、macOSをSierraからHigh Sierraにアップグレードしました。
アップグレード後、ほとんどのものはそのまま正常に動作したのですが、一部エラー吐いた子がいたので調査の内容と解決法を共有します。

## TL;DR

- macOSをHigh Sierraにしたら、kisielk/errcheckがエラー吐いた
- 根本原因はHomebrewにあった
- `brew doctor` でWarningを解決したら治った

## 今回エラー吐いた子

**[kisielk/errcheck](https://github.com/kisielk/errcheck)**

errcheckはGoのソースコードを静的解析してerror型の返り値をハンドリングしていないところをチェックしてくれるライブラリです。
エラーハンドリング漏れを抑制し、コード品質を保つために利用しています。

## どんなエラーを吐いたの？

下記のようなエラーを吐きました（長い）
あまりにも長かったので `In file included from XXX` で同じファイルが出力されていた部分は `〜 中略 〜` としています。

```
$ errcheck ./...
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/net/cgo_bsd.go:11:
In file included from /usr/include/netdb.h:90:
In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:

　　〜 中略 〜

In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:
/usr/local/include/stdint.h:2:10: error: #include nested too deeply
#include <stddef.h>
         ^
/usr/local/include/stdint.h:59:11: error: #include nested too deeply
# include <stdint.h>
          ^
/usr/local/include/stdint.h:72:11: error: #include nested too deeply
# include <sys/types.h>
          ^
/usr/local/include/stdint.h:76:10: error: #include nested too deeply
#include <limits.h>
         ^
/usr/local/include/stdint.h:82:11: error: #include nested too deeply
# include <inttypes.h>
          ^
5 errors generated.
cgo failed: [go tool cgo -objdir /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/net_C781050488 -- -I /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/net_C781050488 cgo_bsd.go cgo_resnew.go cgo_sockold.go cgo_unix.go]: exit status 1
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:14:
In file included from /usr/include/sys/sysctl.h:83:
In file included from /usr/include/sys/ucred.h:76:
In file included from /usr/include/bsm/audit.h:338:
In file included from /usr/include/mach/port.h:90:
In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:

　　〜 中略 〜

In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:
/usr/local/include/stdint.h:2:10: error: #include nested too deeply
#include <stddef.h>
         ^
/usr/local/include/stdint.h:59:11: error: #include nested too deeply
# include <stdint.h>
          ^
/usr/local/include/stdint.h:72:11: error: #include nested too deeply
# include <sys/types.h>
          ^
/usr/local/include/stdint.h:76:10: error: #include nested too deeply
#include <limits.h>
         ^
/usr/local/include/stdint.h:82:11: error: #include nested too deeply
# include <inttypes.h>
          ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:16:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:36:
In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:

　　〜 中略 〜

In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:
/usr/local/include/stdbool.h:4:10: error: #include nested too deeply
#include <stdbool.h>
         ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:16:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:43:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:68:
In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:

　　〜 中略 〜

In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:
/usr/local/include/stdbool.h:4:10: error: #include nested too deeply
#include <stdbool.h>
         ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:16:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:43:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:72:
/usr/local/include/Block.h:16:3: error: Never include this file directly. Use <lzma.h> instead.
#       error Never include this file directly. Use <lzma.h> instead.
        ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:16:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:43:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:77:
In file included from /usr/include/MacTypes.h:44:
In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:

　　〜 中略 〜

In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:
/usr/local/include/stdbool.h:4:10: error: #include nested too deeply
#include <stdbool.h>
         ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:16:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:60:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFPropertyList.h:17:
In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFStream.h:20:
In file included from /usr/include/dispatch/dispatch.h:36:
In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:

　　〜 中略 〜

In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:
/usr/local/include/stdbool.h:4:10: error: #include nested too deeply
#include <stdbool.h>
         ^
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root_cgo_darwin.go:17:
In file included from /System/Library/Frameworks/Security.framework/Headers/Security.h:35:
In file included from /System/Library/Frameworks/Security.framework/Headers/SecImportExport.h:41:
In file included from /System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:33:
In file included from /System/Library/Frameworks/Security.framework/Headers/cssmapple.h:37:
In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:

　　〜 中略 〜

In file included from /usr/local/include/stdbool.h:4:
In file included from /usr/local/include/stdbool.h:4:
/usr/local/include/stdbool.h:4:10: error: #include nested too deeply
#include <stdbool.h>
         ^
11 errors generated.
cgo failed: [go tool cgo -objdir /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/crypto_x509_C275412343 -- -I /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/crypto_x509_C275412343 -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080 root_cgo_darwin.go]: exit status 1
In file included from /Users/yukinasu/.goenv/versions/1.10.3/src/os/user/cgo_lookup_unix.go:24:
In file included from /usr/include/stdlib.h:65:
In file included from /usr/include/sys/wait.h:110:
In file included from /usr/include/sys/resource.h:72:
In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:

　　〜 中略 〜

In file included from /usr/local/include/stdint.h:59:
In file included from /usr/local/include/stdint.h:59:
/usr/local/include/stdint.h:2:10: error: #include nested too deeply
#include <stddef.h>
         ^
/usr/local/include/stdint.h:59:11: error: #include nested too deeply
# include <stdint.h>
          ^
/usr/local/include/stdint.h:72:11: error: #include nested too deeply
# include <sys/types.h>
          ^
/usr/local/include/stdint.h:76:10: error: #include nested too deeply
#include <limits.h>
         ^
/usr/local/include/stdint.h:82:11: error: #include nested too deeply
# include <inttypes.h>
          ^
5 errors generated.
cgo failed: [go tool cgo -objdir /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/os_user_C488864362 -- -I /var/folders/xg/4rpkyn5x2nx2xj7vs8n7z1z40000gn/T/os_user_C488864362 cgo_lookup_unix.go getgrouplist_darwin.go listgroups_unix.go]: exit status 1
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:58:9: undeclared name: listGroups
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:11:41: undeclared name: current
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:32:9: undeclared name: lookupUser
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:41:9: undeclared name: lookupUserId
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:47:9: undeclared name: lookupGroup
/Users/yukinasu/.goenv/versions/1.10.3/src/os/user/lookup.go:53:9: undeclared name: lookupGroupId
/Users/yukinasu/.goenv/versions/1.10.3/src/net/lookup_unix.go:80:24: undeclared name: cgoLookupHost
/Users/yukinasu/.goenv/versions/1.10.3/src/net/lookup_unix.go:95:24: undeclared name: cgoLookupIP
/Users/yukinasu/.goenv/versions/1.10.3/src/net/lookup_unix.go:107:23: undeclared name: cgoLookupPort
/Users/yukinasu/.goenv/versions/1.10.3/src/net/lookup_unix.go:123:24: undeclared name: cgoLookupCNAME
/Users/yukinasu/.goenv/versions/1.10.3/src/net/lookup_unix.go:190:23: undeclared name: cgoLookupPTR
/Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/cert_pool.go:38:9: undeclared name: loadSystemRoots
/Users/yukinasu/.goenv/versions/1.10.3/src/crypto/x509/root.go:21:32: undeclared name: loadSystemRoots
error: failed to check packages: could not type check: couldn't load packages due to errors: crypto/x509, os/user, net
```

## 調査だ！

まずはエラーメッセージの内容をざっくりと見て、`cgo failed:` というエラーが頻出していたのでCgo関係のエラーかとあたりをつけました。  Cgoに関してはREADMEに下記の記述がありました。

https://github.com/kisielk/errcheck#cgo

> Cgo  
> Currently errcheck is unable to check packages that import "C" due to limitations in the importer.
>
> However, you can use errcheck on packages that depend on those which use cgo. In order for this to work you need to go install the cgo dependencies before running errcheck on the dependent packages.
>
> See https://github.com/kisielk/errcheck/issues/16 for more details.

詳細はIssueを見てねってことだったので、Issueのエラーとこっちで出てるエラーの内容違うなと思いながらも読み進めていくと下記のコメントを見つけました。
https://github.com/kisielk/errcheck/issues/16#issuecomment-160808162

> This may be obvious to some, but recording here for future searchers.
>
> I was getting many cgo related errors (when running errcheck inside an alpine linux docker container with no gcc). Fixed them by running:
>
> ```
> CGO_ENABLED=0 errcheck ./...
> ```
> (edit: set to 0 not 1)

`CGO_ENABLED=0` をつけて実行するとcgoを無効にすることができるとのことなので、やってみると......**エラー出ませんでした！**  
これで解決かとも思いましたが、High Sierraにアップグレード済みでもerrcheckが正常に動作している方もいたので、調査を継続。
上記はエラーの回避法にはなりましたが、根本解決にはなりませんでした。

## 根本解決を目指して

Google先生を頼りに調査を継続していくと下記のIssueが見つかりました。ライブラリは違いますが、私の環境で発生したエラーと同じようなエラーが出力されています。
https://github.com/SOHU-Co/kafka-node/issues/881

読み進めていくと
https://github.com/SOHU-Co/kafka-node/issues/881#issuecomment-377109841

> I had the same error in a different project. Problem was some header files in `/usr/local/include` that shouldn't be there. Easiest to fix is to run `brew doctor` and follow instructions.

最も簡単な解決方法は `brew doctor` で出力されるWarningを修正すること！ 
ということで、 `brew doctor` を実行します。

```
$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: The following directories are not writable:
/usr/local/var
/usr/local/Frameworks

This can happen if you "sudo make install" software that isn't managed
by Homebrew. If a formula tries to write a file to this directory, the
install will fail during the link step.

You should change the ownership of these directories to your account.
  sudo chown -R $(whoami) /usr/local/var /usr/local/Frameworks

Warning: Unbrewed header files were found in /usr/local/include.
If you didn't put them there on purpose they could cause problems when
building Homebrew formulae, and may need to be deleted.

Unexpected header files:
  /usr/local/include/base.h
  /usr/local/include/bcj.h
  /usr/local/include/block.h
  /usr/local/include/cdefs.h
  /usr/local/include/check.h
  /usr/local/include/container.h
  /usr/local/include/delta.h
  /usr/local/include/filter.h
  /usr/local/include/hardware.h
  /usr/local/include/iconveh.h
  /usr/local/include/index.h
  /usr/local/include/index_hash.h
  /usr/local/include/inline.h
  /usr/local/include/localcharset.h
  /usr/local/include/lzma12.h
  /usr/local/include/stdbool.h
  /usr/local/include/stdint.h
  /usr/local/include/stream_flags.h
  /usr/local/include/version.h
  /usr/local/include/vli.h
  /usr/local/include/woe32dll.h

Warning: Broken symlinks were found. Remove them with `brew prune`:
  /usr/local/opt/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages

Warning: Some installed formulae are missing dependencies.
You should `brew install` the missing dependencies:
  brew install ruby-build

Run `brew missing` for more details.
```

結構な数のWarningが出ました。errcheckのエラーに出力されていたファイルに関するWarningもあります。 `brew doctor` で示された解決方法に従って、Warningを解決した結果、**エラーが出なくなりました！**

## 結論

今回のエラーの原因は結果としてHomebrew周りにありました。Homebrewを利用している方はHigh Sierraにアップグレードした際には `brew doctor` を実行してWarningが発生していないかの確認をしたほうが良いと思います！