3
0

More than 1 year has passed since last update.

go toolが何をしてるのか知りたかったら-x -workを使うと良い

Posted at

はじめに

どうもナレッジワークtenntennです。

この記事では、go buildgo rungo testを実行する際のちょっとしたテクニックを紹介します。

-xオプション

Goのツールチェインの内部では、コンパイラやリンカは$GOROOT/pkg/tool/$GOOS_$GOARCHにある別コマンドを実行しています。

$ ls `go env GOROOT`/pkg/tool/`go env GOOS`_`go env GOARCH`
addr2line	compile		fix		pack		vet
asm		cover		link		pprof
buildid		dist		nm		test2json
cgo		doc		objdump		trace

これらのコマンドをどういう風に実行しているのか確かめたい場合は-xオプションを使うと良いでしょう。

たとえば、次のようなGoファイルをビルドして実行してみます。

package main

import "fmt"

func main() {
	fmt.Println("hello")
}

実行にはgo runコマンドを用います。-xオプションをつけてみましょう。

$ go run -x main.go
WORK=/var/folders/wg/6bn75hvs4sv6tvd2h67k3z440000gp/T/go-build4263583053
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_arm64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_arm64/runtime.a
EOF
cd /Users/tenntenn/repos/tenntenn/scrap/x-work
/usr/local/go/pkg/tool/darwin_arm64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid ulGFIZNq9utit_V8LK54/ulGFIZNq9utit_V8LK54 -dwarf=false -goversion go1.19.3 -shared -c=4 -nolocalimports -importcfg $WORK/b001/importcfg -pack ./main.go
/usr/local/go/pkg/tool/darwin_arm64/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /Users/tenntenn/Library/Caches/go-build/b8/b8a3a8e8808474a9885f6d08e80f7b16d3b30d78c3d6a476e678bc6888d506a6-d # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
packagefile fmt=/usr/local/go/pkg/darwin_arm64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_arm64/runtime.a
packagefile errors=/usr/local/go/pkg/darwin_arm64/errors.a
packagefile internal/fmtsort=/usr/local/go/pkg/darwin_arm64/internal/fmtsort.a
packagefile io=/usr/local/go/pkg/darwin_arm64/io.a
packagefile math=/usr/local/go/pkg/darwin_arm64/math.a
packagefile os=/usr/local/go/pkg/darwin_arm64/os.a
packagefile reflect=/usr/local/go/pkg/darwin_arm64/reflect.a
packagefile strconv=/usr/local/go/pkg/darwin_arm64/strconv.a
packagefile sync=/usr/local/go/pkg/darwin_arm64/sync.a
packagefile unicode/utf8=/usr/local/go/pkg/darwin_arm64/unicode/utf8.a
packagefile internal/abi=/usr/local/go/pkg/darwin_arm64/internal/abi.a
packagefile internal/bytealg=/usr/local/go/pkg/darwin_arm64/internal/bytealg.a
packagefile internal/cpu=/usr/local/go/pkg/darwin_arm64/internal/cpu.a
packagefile internal/goarch=/usr/local/go/pkg/darwin_arm64/internal/goarch.a
packagefile internal/goexperiment=/usr/local/go/pkg/darwin_arm64/internal/goexperiment.a
packagefile internal/goos=/usr/local/go/pkg/darwin_arm64/internal/goos.a
packagefile runtime/internal/atomic=/usr/local/go/pkg/darwin_arm64/runtime/internal/atomic.a
packagefile runtime/internal/math=/usr/local/go/pkg/darwin_arm64/runtime/internal/math.a
packagefile runtime/internal/sys=/usr/local/go/pkg/darwin_arm64/runtime/internal/sys.a
packagefile internal/reflectlite=/usr/local/go/pkg/darwin_arm64/internal/reflectlite.a
packagefile sort=/usr/local/go/pkg/darwin_arm64/sort.a
packagefile math/bits=/usr/local/go/pkg/darwin_arm64/math/bits.a
packagefile internal/itoa=/usr/local/go/pkg/darwin_arm64/internal/itoa.a
packagefile internal/oserror=/usr/local/go/pkg/darwin_arm64/internal/oserror.a
packagefile internal/poll=/usr/local/go/pkg/darwin_arm64/internal/poll.a
packagefile internal/syscall/execenv=/usr/local/go/pkg/darwin_arm64/internal/syscall/execenv.a
packagefile internal/syscall/unix=/usr/local/go/pkg/darwin_arm64/internal/syscall/unix.a
packagefile internal/testlog=/usr/local/go/pkg/darwin_arm64/internal/testlog.a
packagefile internal/unsafeheader=/usr/local/go/pkg/darwin_arm64/internal/unsafeheader.a
packagefile io/fs=/usr/local/go/pkg/darwin_arm64/io/fs.a
packagefile sync/atomic=/usr/local/go/pkg/darwin_arm64/sync/atomic.a
packagefile syscall=/usr/local/go/pkg/darwin_arm64/syscall.a
packagefile time=/usr/local/go/pkg/darwin_arm64/time.a
packagefile unicode=/usr/local/go/pkg/darwin_arm64/unicode.a
packagefile internal/race=/usr/local/go/pkg/darwin_arm64/internal/race.a
packagefile path=/usr/local/go/pkg/darwin_arm64/path.a
modinfo "0w\xaf\f\x92t\b\x02A\xe1\xc1\a\xe6\xd6\x18\xe6path\tcommand-line-arguments\nbuild\t-compiler=gc\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=arm64\nbuild\tGOOS=darwin\n\xf92C1\x86\x18 r\x00\x82B\x10A\x16\xd8\xf2"
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_arm64/link -o $WORK/b001/exe/main -importcfg $WORK/b001/importcfg.link -s -w -buildmode=exe -buildid=_mLUCLIz1uIg5o5PxsyQ/ulGFIZNq9utit_V8LK54/QwDWNGpEATLsyzIrn0bj/_mLUCLIz1uIg5o5PxsyQ -extld=clang $WORK/b001/_pkg_.a
$WORK/b001/exe/main
hello

compileコマンドやlinkコマンドが実行されていることが分かります。
これで各コマンドの引数がどのようなものが渡されているのか調べれます。

-workオプション

Goのツールチェインは、複数のコマンドを組み合わせて動いているため、途中の状態をファイルとして書き出すことが多いです。ツールチェインの挙動を追いたい場合、生成物を見てみるとわかることが多いでしょう。

次のように-workオプションをつけると、コマンド実行後に一時ファイルが消されないため、生成物を確認できます。

$ go run -work main.go
WORK=/var/folders/wg/6bn75hvs4sv6tvd2h67k3z440000gp/T/go-build1954475371
hello

この場合、一時ファイルは/var/folders/wg/6bn75hvs4sv6tvd2h67k3z440000gp/T/go-build1954475371にあるため、確認してみましょう。

$ tree /var/folders/wg/6bn75hvs4sv6tvd2h67k3z440000gp/T/go-build1954475371
/var/folders/wg/6bn75hvs4sv6tvd2h67k3z440000gp/T/go-build1954475371
└── b001
    ├── _pkg_.a
    ├── exe
    │   └── main
    ├── importcfg
    └── importcfg.link

2 directories, 4 files

ビルドされた実行可能ファイルなどが入ってることが分かります。

キャッシュの削除

ビルドキャッシュを消したい場合は、次のようにコマンドを実行しておくと良いでしょう。
キャッシュが残っていると、生成物が減ったり、実行するコマンドが減ったりするので、挙動を追いづらくなります。

$ go clean -cache

おわりに

本記事では、Goのツールチェインの-xオプションや-workオプションについて解説しました。

他にもオプションはたくさんあるので、一度はgo help buildコマンドを実行してオプションの一覧を眺めてみると良いでしょう。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0