LoginSignup
5
4

More than 1 year has passed since last update.

パッケージ名を指定してgo buildしよう

Last updated at Posted at 2021-12-30

はじめに

フューチャー Advent Calendar 2021の7日目です。

本記事では go build main.gogo build {パッケージ名} としてビルドしたときの微妙な違いについて説明します。Goのバージョンは go1.18beta1 で確認しています。

Go 1.18から runtime/debug パッケージの ReadBuildInfo() を使って、ビルドしたときのVCSのハッシュを取得できるようになりますが、このビルドしたときの微妙な違いが影響するようになります。1
https://tip.golang.org/doc/go1.18#go-command

go build の引数による違い

go build でGoのソースをビルドして、実行バイナリが生成されることはよく知られています。

Usageにあるように

go build [-o output] [build flags] [packages]

パッケージ名 (packages) を指定してビルドしますが、Goの1つあるいは複数のソースファイルを go build の引数に渡すこともできます。go build a.go b.go c.go といったものです。

簡単のために以下のようなディレクトリ、ファイル構成を考えてみます。

ディレクトリ構成
.
├── go.mod
└── main.go
go.mod
module sample

go 1.18
main.go
package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, 世界")
}

go build ${パッケージ名} としてビルドしたとき

go build ${パッケージ名} としてビルドします。本例ではパッケージ名は sample です。

go version -m sample で確認すると以下のようになります。path の値が sample のパッケージ名になっており、また mod の値として sample のパッケージ名が含まれていることが分かります。VCS(ここではGit)のハッシュが含まれていることも分かります。便利ですね。

$ go build sample
$ go version -m sample
sample: go1.18beta1
        path    sample
        mod     sample  (devel)
        build   -compiler=gc
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=amd64
        build   GOOS=linux
        build   GOAMD64=v1
        build   vcs=git
        build   vcs.revision=sample0123456789012345678901234567sample
        build   vcs.time=2021-12-27T04:24:55Z
        build   vcs.modified=true

go build main.go としてビルドしたとき

go build main.go としてGoのソースファイルを指定してビルドするとコマンドライン引数(command-line-arguments)としてビルドされます。

go version -m main で確認すると以下のようになります。pathcommand-line-arguments となっていることが分かります。mod の値はありません。VCSのハッシュも含まれていません。

$ go build main.go
$ go version -m main
main: go1.18beta1
        path    command-line-arguments
        build   -compiler=gc
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=amd64
        build   GOOS=linux
        build   GOAMD64=v1

より詳細を知りたい方へ

Goの標準ライブラリも多くはGoで書かれています。上記の go build コマンドへの引数による違いは cmd/go/internal/work/build.gocmd/go/internal/load/pkg.go のソースを読んでみると参考になります。cmd/go/internal/load/pkg.go の中で .go のファイルが引数として渡されたときは引数がコマンドライン引数として渡されたものとしてフラグ(pkg.Internal.CmdlineFiles)がセットされます。

cmd/go/internal/load/pkg.go
func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package {

    // ...

    bp, err := ctxt.ImportDir(dir, 0)
    pkg := new(Package)
    pkg.Internal.Local = true
    pkg.Internal.CmdlineFiles = true
    pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
    if !cfg.ModulesEnabled {
        pkg.Internal.LocalPrefix = dirToImportPath(dir)
    }
    pkg.ImportPath = "command-line-arguments"
    pkg.Target = ""
    pkg.Match = gofiles

    // ...
}

まとめ

  • go build の引数にファイル名を渡すか、パッケージ名を渡すかで、ビルドの方法が異なります。
  • ファイル名を渡してビルドした場合は、VCSのハッシュがビルドに含まれません。
  • ビルドするときはパッケージ名を指定してビルドしましょう。

  1. go version -m でも確認できます。https://pkg.go.dev/cmd/go#hdr-Print_Go_version 

5
4
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
5
4