Golangで作ったプロダクトを公開・配布するとき、課題となるのが利用するモジュールのライセンスです。 MITライセンスであれ、MPLライセンスであれ、利用するモジュールのLICENSEやNOTICEファイルを同梱することになるでしょう。
goxzとgo-licensesを使うと、クロスビルドした実行バイナリと利用モジュールのLICENSE等を含め頒布物を作成できるようになります。
最終イメージ
最終イメージですが、以下のようなMakefileを用意しました。
プロダクトに設定したライセンスで利用できないモジュールがあるかどうかをlicense-check
で確認した後、cross-build.sh
を呼び出します。
.PHONY: license-check license-check: go-licenses check . .PHONY: build build: go build -ldflags=$(LDFLAGS) -o $(NAME) . .PHONY: cross-build cross-build: license-check build NAME=$(NAME) VERSION=$(VERSION) LDFLAGS=$(LDFLAGS) ./build/package/cross-build.sh
cross-build.sh
はおおよそ以下のようなシェルスクリプトになります。
go-licenses
の挙動に戸惑ったりもしましたが、現状はこれでうまくいっています。
#!/bin/bash -eu # workdir=$(mktemp -d) とすると goxz でエラーが発生してしまう workdir=dist-licenses rm -rf ${workdir} mkdir -p ${workdir} go-licenses save . --force --save_path ${workdir} --alsologtostderr # go-licenses でソースをダウンロードすることになる場合、当該ファイルのパーミッションが # 0666 になっており、結果として再実行ができなくなるというバグがある。 # see: https://github.com/google/go-licenses/issues/11 # 暫定対応として、強制的に書き込み権限を付与する chmod +w -R ${workdir} goxz \ -d dist \ -n ${NAME} \ -pv ${VERSION} \ -build-ldflags \'"${LDFLAGS}"\' \ -include "$(find ${workdir} -type f)"
同梱されていることの確認
$ unzip -l /Users/kiririmode/src/gitlab.com/myorgs/my-product/dist/my-product_v0.0.1_darwin_amd64.zip Archive: /Users/kiririmode/src/gitlab.com/myorgs/my-product/dist/my-product_v0.0.1_darwin_amd64.zip Length Date Time Name --------- ---------- ----- ---- 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/ 11338 02-11-2021 15:22 my-product_v0.0.1_darwin_amd64/LICENSE 210 02-11-2021 14:26 my-product_v0.0.1_darwin_amd64/README.md 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/ 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gitlab.com/ 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gitlab.com/myorgs/ 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gitlab.com/myorgs/my-product/ 11338 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gitlab.com/myorgs/my-product/LICENSE 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gopkg.in/ 0 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gopkg.in/yaml.v2/ 11357 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gopkg.in/yaml.v2/LICENSE 560 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/dist-licenses/gopkg.in/yaml.v2/NOTICE 4716008 02-11-2021 18:51 my-product_v0.0.1_darwin_amd64/my-product --------- ------- 4750811 13 files
go-licenses
go-licensesはGoogle謹製のプロダクトで、パッケージや実行バイナリから依存モジュールを解析し、 各モジュールのライセンスを取得してくれます。
いくつかサブコマンドがあるのですが、save
を使うと依存モジュールのLICENSE
やNOTICE
をかき集めてくれます。かき集めるディレクトリは--save_path
で指定しましょう。
$ go-licenses save . --force --save_path dist-licenses --alsologtostderr $ find dist-licenses -type f dist-licenses/gopkg.in/yaml.v2/LICENSE dist-licenses/gopkg.in/yaml.v2/NOTICE dist-licenses/gitlab.com/myorgs/my-product/LICENSE
ハマりポイント
じつは、このsave
コマンドでかき集めたファイルのパーミッションはread-only(0666
)になります。
make clean
で消すこともできず、なかなか扱いづらい。
$ find dist-licenses -type f -ls 30520975 12 -r--r--r-- 1 kiririmode staff 11357 2 11 19:18 dist-licenses/gopkg.in/yaml.v2/LICENSE 30520976 4 -r--r--r-- 1 kiririmode staff 560 2 11 19:18 dist-licenses/gopkg.in/yaml.v2/NOTICE 30520972 12 -rw-r--r-- 1 kiririmode staff 11338 2 11 19:18 dist-licenses/gitlab.com/myorg/my-product/LICENSE
これはissueとして登録されているのですが、対応されていません。
このため、強制的に書き込みbitを付与する対応をします。
$ chmod +w -R dist-licenses
goxz
goxzは、クロスビルドとパッケージングのための軽量なツールです。
各プラットフォーム用にクロスビルドを行い、README
等を含めた形でパッケージングしてくれます。
goxzには-include
オプションがあり、ここにはパッケージング時に同梱するファイルを指定できます。
複数指定するときにはどうするのだろうとソースを見ると、空白区切りで指定できるようです。
このため、ファイルをぶちこむようにしました。 シェルの解釈できる長さが気になるところですが、当面はこれでなんとかなるでしょう。
-include "$(find dist-licenses -type f)"
まとめ
ライセンス等の同梱を行わない配布はライセンス違反の可能性が高くなります。 一方で、たくさんのモジュールに依存したときはライセンスファイルの扱いは煩雑です。
様々なツールを使うことで、このあたりの煩雑さを解消していけると良いですね。