[インデックス 12806] ファイルの概要
このコミットは、Go言語のディストリビューションツールの一部である misc/dist/bindist.go
ファイルに対する変更です。このファイルは、Goのバイナリディストリビューションパッケージ、特にmacOS向けのインストーラーパッケージ(.pkgファイル)を生成する役割を担っています。変更の目的は、macOSパッケージがインストール時にシンボリックリンクを正しく追跡するようにすることです。
コミット
dist: make sure OS X packages follow symlinks when installing
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/28ac033b2ec29a86cd6b7b0f804272abee6d5f94
元コミット内容
dist: make sure OS X packages follow symlinks when installing
R=adg
CC=golang-dev
https://golang.org/cl/5970061
変更の背景
この変更の背景には、macOS向けのGoバイナリディストリビューションパッケージが、インストール時に含まれるシンボリックリンク(symlinks)を適切に処理できていなかったという問題があります。通常、ソフトウェアパッケージには、実際のファイルへのショートカットとしてシンボリックリンクが含まれることがあります。例えば、あるディレクトリ内のファイルが、別の場所にある実際のファイルを参照している場合などです。
PackageMaker
はmacOSのインストーラーパッケージ(.pkg)を作成するためのツールですが、デフォルトの挙動では、パッケージ内のシンボリックリンクを「そのまま」コピーし、リンク先のファイルを追跡してインストール先に配置しない場合があります。これにより、インストールされたGo環境において、シンボリックリンクが正しく解決されず、特定のツールやライブラリが機能しないといった問題が発生する可能性がありました。
このコミットは、PackageMaker
に対して、パッケージ作成時にシンボリックリンクを追跡し、そのリンク先の実際のファイルをパッケージに含めるように指示することで、この問題を解決しようとしています。
前提知識の解説
シンボリックリンク (Symbolic Link / Symlink)
シンボリックリンクは、ファイルシステム上の別のファイルやディレクトリへの参照(ポインタ)として機能する特殊なファイルです。Windowsのショートカットに似ていますが、より低レベルでOSによって透過的に扱われることが多いです。シンボリックリンク自体は非常に小さく、参照先のパス情報のみを保持しています。
例えば、/usr/local/bin/go
が /usr/local/go/bin/go
へのシンボリックリンクである場合、ユーザーが /usr/local/bin/go
を実行すると、OSは自動的に /usr/local/go/bin/go
を見つけて実行します。
macOSのパッケージ (.pkg) と PackageMaker
macOSでは、アプリケーションやシステムコンポーネントのインストールに .pkg
形式のパッケージが広く利用されます。これらのパッケージは、インストーラーアプリケーションによって展開され、指定された場所にファイルを配置します。
PackageMaker
は、Appleが提供していた(現在は非推奨)開発者ツールの一部で、.pkg
ファイルを作成するためのコマンドラインツールです。これを使用することで、開発者はアプリケーションやライブラリを配布可能なインストーラーとしてバンドルできます。PackageMaker
は、パッケージに含めるファイル、インストール先、スクリプトなどを定義するための様々なオプションを提供します。
misc/dist/bindist.go
の役割
Go言語のソースコードリポジトリにおける misc/dist/bindist.go
ファイルは、Goの公式バイナリディストリビューションを構築するためのスクリプトの一部です。このファイルは、様々なオペレーティングシステム(macOS, Windows, Linuxなど)向けのGoバイナリパッケージを生成するロジックを含んでいます。具体的には、Goのコンパイル済みバイナリ、標準ライブラリ、ドキュメントなどを集約し、それぞれのOSに適した形式(macOSでは.pkg、Windowsでは.zipなど)で配布可能なアーカイブを作成します。
技術的詳細
このコミットの技術的な核心は、PackageMaker
コマンドに --info
オプションを導入し、PackageInfo
というXML形式のファイルを通じて、パッケージ作成時の挙動をより詳細に制御することにあります。
従来の PackageMaker
コマンドでは、--id
, --version
, --target
などのオプションを直接指定していましたが、これではシンボリックリンクの追跡に関する設定ができませんでした。
変更後では、PackageMaker
の実行前に createPackageInfo
という新しい関数が呼び出されます。この関数は、一時的な PackageInfo
XMLファイルを生成します。このXMLファイルには、以下の重要な属性が含まれています。
<pkg-info identifier="com.googlecode.go" version="1.0" followSymLinks="true">
<payload installKBytes="%v" numberOfFiles="%v"/>
</pkg-info>
ここで最も重要なのは followSymLinks="true"
属性です。この属性を true
に設定することで、PackageMaker
はパッケージに含めるファイルを収集する際に、シンボリックリンクを単なる参照としてコピーするのではなく、そのリンクが指し示す実際のファイルを追跡し、パッケージのペイロード(実際にインストールされる内容)に含めるようになります。これにより、インストール後にシンボリックリンクが正しく解決され、Go環境が期待通りに機能することが保証されます。
createPackageInfo
関数は、パッケージに含めるファイルの総サイズ(installKBytes
)とファイル数(numberOfFiles
)も計算し、payload
タグの属性としてXMLに埋め込みます。これらの情報は、インストーラーがユーザーに提供する情報(例: インストールに必要なディスク容量)として利用されます。
コアとなるコードの変更箇所
変更は misc/dist/bindist.go
ファイルの func (b *Build) Do() error
メソッド内のmacOSパッケージ作成ロジックに集中しています。
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -240,6 +240,11 @@ func (b *Build) Do() error {
return err
}
// build package
+ pkginfo, err := createPackageInfo(work)
+ if err != nil {
+ return err
+ }
+ defer os.Remove(pkginfo)
pm := packageMaker
if !exists(pm) {
pm = "/Developer" + pm
@@ -252,11 +257,10 @@ func (b *Build) Do() error {
_, err = b.run("", pm, "-v",
"-r", work,
"-o", targ,
+ "--info", pkginfo,
"--scripts", scripts,
- "--id", "com.googlecode.go",
"--title", "Go",
- "--version", "1.0",
- "--target", "10.6")
+ "--target", "10.5")
targs = append(targs, targ)
case "windows":
// Create ZIP file.
@@ -794,3 +798,30 @@ func tarFileInfoHeader(fi os.FileInfo, filename string) (*tar.Header, error) {
}
return h, nil
}
+
+// createPackageInfo creates a PackageInfo template file for use with PackageMaker.
+// The returned filename points to a file in a temporary directory on the filesystem,
+// and should be removed after use.
+func createPackageInfo(work string) (filename string, err error) {
+ var size, nfiles int64
+ err = filepath.Walk(work, func(path string, info os.FileInfo, err error) error {
+ nfiles++
+ size += info.Size()
+ return nil
+ })
+ if err != nil {
+ return "", err
+ }
+ pi, err := ioutil.TempFile("", "PackageInfo")
+ if err != nil {
+ return "", err
+ }
+ defer pi.Close()
+ _, err = fmt.Fprintf(pi, "<pkg-info identifier=\"com.googlecode.go\" version=\"1.0\" followSymLinks=\"true\">\\n\"+\n+\t\t\"\\t<payload installKBytes=\\\"%v\\\" numberOfFiles=\\\"%v\\\"/>\\n\"+\n+\t\t\"</pkg-info>\\n\", size/1024, nfiles)
+ if err != nil {
+ return "", err
+ }
+ return pi.Name(), nil
+}
コアとなるコードの解説
createPackageInfo
関数
このコミットで新しく追加された createPackageInfo
関数は、PackageMaker
が必要とする PackageInfo
XMLファイルを動的に生成する役割を担っています。
-
ディレクトリウォークと情報収集:
filepath.Walk(work, ...)
を使用して、パッケージ化されるディレクトリ(work
)内のすべてのファイルとディレクトリを再帰的に走査します。この際、nfiles
(ファイル数)とsize
(総バイトサイズ)を計算します。これらの情報は、PackageInfo
XMLのpayload
タグにnumberOfFiles
とinstallKBytes
として埋め込まれます。 -
一時ファイルの作成:
ioutil.TempFile("", "PackageInfo")
を呼び出して、一時的なファイルを作成します。このファイルに生成されたXMLコンテンツが書き込まれます。関数が終了する際にdefer os.Remove(pi)
でこの一時ファイルが削除されるように設定されています。 -
XMLコンテンツの書き込み:
fmt.Fprintf
を使用して、PackageInfo
XMLの構造を文字列として一時ファイルに書き込みます。 特に注目すべきは、<pkg-info ... followSymLinks="true">
の部分です。これにより、PackageMaker
はシンボリックリンクを追跡して、その実体をパッケージに含めるようになります。 -
ファイル名の返却: 生成された一時ファイルのパスを返します。このパスは、後続の
PackageMaker
コマンドの--info
オプションに渡されます。
Do()
メソッド内の変更
Do()
メソッドのmacOSパッケージ作成部分では、以下の変更が行われています。
-
createPackageInfo
の呼び出し:pkginfo, err := createPackageInfo(work)
が追加され、PackageInfo
XMLファイルが作成されます。エラーが発生した場合は、すぐに処理を中断します。 -
一時ファイルのクリーンアップ:
defer os.Remove(pkginfo)
が追加され、Do()
メソッドの実行が終了する際に、生成された一時的なPackageInfo
ファイルが確実に削除されるようにします。 -
PackageMaker
コマンドの変更:b.run
を介して実行されるPackageMaker
コマンドの引数が変更されました。--info
,pkginfo
が追加されました。これにより、PackageMaker
は生成されたPackageInfo
XMLファイルから設定を読み込むようになります。--id
,com.googlecode.go
および--version
,1.0
の直接指定が削除されました。これらの情報はPackageInfo
XMLファイル内で定義されるため、コマンドライン引数としては不要になりました。--target
,10.6
が10.5
に変更されていますが、これはこのコミットの主要な目的とは直接関係なく、おそらくmacOSのターゲットバージョンを少し古いものに広げたものと考えられます。
これらの変更により、GoのmacOSインストーラーは、シンボリックリンクを含むファイルを正しくパッケージ化し、インストール時にそれらのリンクが適切に解決されるようになります。
関連リンク
- Go言語公式サイト
- macOS PackageMaker (非推奨) (Apple Developer Documentation - 古い情報ですが、概念理解に役立つ可能性があります)
- macOS Installer Package (Wikipedia)
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/12806.txt
- GitHubコミットページ: https://github.com/golang/go/commit/28ac033b2ec29a86cd6b7b0f804272abee6d5f94
- Go言語のソースコード (
misc/dist/bindist.go
の当時のバージョン) PackageMaker
の挙動に関する一般的な知識 (Web検索を通じて得られた情報)- シンボリックリンクに関する一般的な知識 (Web検索を通じて得られた情報)
- XMLの基本構造に関する知識