50940


Go言語でコマンドラインのアプリをビルドする際、１つのリポジトリ内で複数バイナリを作成するにはどうすればいいでしょうか？  
もしくはそのようなビルド設定は非推奨ですか？


CC BY-SA 4.0
2018-12-05T11:06:27.967
50938
2018-12-05T12:45:05.437
4715
question
go
Go言語で１つのリポジトリで複数のバイナリファイルをビルドする方法


可能です。実際に複数のバイナリを1つのリポジトリで管理しているソフトウェアも存在します。

## 解決法

それぞれのアプリを別ディレクトリに格納すれば良いです。たとえば、以下のような形で管理します。

  * `cmd/app1`, `cmd/app2` というように、あるディレクトリ以下にそれぞれのアプリのソースコードを用意する。
  * 共通のライブラリは `pkg` や `internal` や `lib` など他のディレクトリで管理する。(あるいはルートディレクトリに置く場合もあります。)

こうすると以下のように使えます。

  * それぞれのアプリのビルドのためには、各アプリのディレクトリの中で `go build` する。一括で `go build` するための Makefile や build.go を書くこともある。
  * リポジトリのルートディレクトリで `go install ./...` すれば一括でインストールできる。

また、複数のバイナリを用意する代わりに、1つのバイナリの **サブコマンド**
として実装した方が便利な場合もあります。そのためのライブラリも[色々とあります](https://dave.cheney.net/2013/11/07/subcommand-
handling-in-go)。

## 具体例

具体例を挙げてみます。たとえば以下のようなディレクトリ構成で管理するとしましょう。

[code]

    .
    ├─cmd
    │  ├─app1
    │  └─app2
    └─lib
    
[/code]

全く役に立たないアプリですが、それぞれ以下のようなコードだとします。

cmd/app1/main.go

[code]

    package main
    
    import (
        "fmt"
    
        "github.com/nekketsuuu/multiexes/lib"
    )
    
    func main() {
        fmt.Println(lib.Prefix + " app1")
    }
    
[/code]

cmd/app2/main.go

[code]

    package main
    
    import (
        "fmt"
    
        "github.com/nekketsuuu/multiexes/lib"
    )
    
    func main() {
        fmt.Println(lib.Prefix + " app2")
    }
    
[/code]

lib/lib.go

[code]

    package lib
    
    const Prefix = "Hello!"
    
[/code]

こうすると2つのアプリ `app1` と `app2` を同じリポジトリで管理することができます。`cmd/app1` で `go build` すれば
`app1` がビルドできますし、ルートディレクトリで `go install ./...` すれば `app1` と `app2`
がインストールされます。

ルートディレクトリで `go build ./...` をしてもバイナリは作られないことに注意してください。このことは [`go build`
のドキュメント](https://golang.org/cmd/go/#hdr-
Compile_packages_and_dependencies)に書かれています。

> When compiling multiple packages or a single non-main package, build
> compiles the packages but discards the resulting object, serving only as a
> check that the packages can be built.

(場合によって将来的には `-o`
フラグが便利になるかもしれません。[golang/go#14295](https://github.com/golang/go/issues/14295)
を参照してください)

## 実際の例

  * <https://github.com/kubernetes/kubernetes>
  * <https://github.com/coreos/torus>
  * <https://github.com/perkeep/perkeep>
  * <https://github.com/grafana/grafana>


CC BY-SA 4.0
2018-12-05T12:07:13.850
50940
2018-12-05T12:45:05.437
2018-12-05T12:45:05.437
19110
19110
50938
answer