[インデックス 12937] ファイルの概要
このコミットは、Go言語のディストリビューションツール (misc/dist
) におけるmacOS (OS X) 向けパッケージ (.pkg) の生成方法を改善するものです。具体的には、従来の PackageMaker
ユーティリティの使用を廃止し、macOSのネイティブツールである pkgbuild
と productbuild
を採用することで、より堅牢で柔軟なパッケージ作成プロセスを実現しています。これにより、OS X 10.6以降のバージョンを必須とするようになり、古いOSバージョンでインストールしようとした際に、よりユーザーフレンドリーなエラーメッセージを表示できるようになりました。また、postinstall
スクリプトのいくつかの問題も修正されています。
コミット
commit c17d09a65774e03376fc1a7fd536646297f408cb
Author: Mikkel Krautz <mikkel@krautz.dk>
Date: Mon Apr 23 14:56:03 2012 -0700
misc/dist: require 10.6 or later for OS X .pkgs
This changes the misc/dist program to generate OS X
packages using pkgbuild and productbuild.
The productbuild utility makes it easy to generate
packages with a custom Distribution file. This allows
us to add an installcheck script that presents a
friendly message to users who are running on an old
version of Mac OS X.
The change also fixes a few issues with the
postinstall script:
- In-repo version of the script has been made
executable. Installers generated using the new
tools couldn't execute it otherwise.
- It now uses -d for checking for the existence
of the Xcode specs directory.
- The call to sudo.bash has been dropped since cov
and prof aren't bundled with the binary
distributions.
Fixes #3455.
Tested on 10.5.8, 10.6.0, 10.6.8 and 10.7.3.
R=adg, golang-dev
CC=golang-dev
https://golang.org/cl/5987044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c17d09a65774e03376fc1a7fd536646297f408cb
元コミット内容
misc/dist: require 10.6 or later for OS X .pkgs
This changes the misc/dist program to generate OS X
packages using pkgbuild and productbuild.
The productbuild utility makes it easy to generate
packages with a custom Distribution file. This allows
us to add an installcheck script that presents a
friendly message to users who are running on an old
version of Mac OS X.
The change also fixes a few issues with the
postinstall script:
- In-repo version of the script has been made
executable. Installers generated using the new
tools couldn't execute it otherwise.
- It now uses -d for checking for the existence
of the Xcode specs directory.
- The call to sudo.bash has been dropped since cov
and prof aren't bundled with the binary
distributions.
Fixes #3455.
Tested on 10.5.8, 10.6.0, 10.6.8 and 10.7.3.
R=adg, golang-dev
CC=golang-dev
https://golang.org/cl/5987044
変更の背景
この変更の主な背景には、macOS (旧称 OS X) 向けのGoバイナリディストリビューションのインストール体験の向上と、パッケージ作成プロセスの近代化があります。
-
OSバージョンの要件明確化とユーザー体験の改善: 以前のGoディストリビューションは、古いOS Xバージョンでもインストールを試みることができましたが、Goの特定の機能やビルド環境が新しいOSバージョンに依存している場合、インストール後に問題が発生する可能性がありました。このコミットでは、GoのmacOSパッケージがOS X 10.6 (Snow Leopard) 以降を必要とすることを明確にし、それ以前のバージョンでインストールしようとしたユーザーに対して、より親切で明確なエラーメッセージを表示することを目的としています。これにより、ユーザーは無駄なインストール作業を避け、互換性の問題を事前に把握できるようになります。
-
パッケージ作成ツールの移行: 従来のmacOSパッケージ作成には
PackageMaker
というツールが使用されていました。しかし、PackageMaker
はAppleによって非推奨とされ、より新しいpkgbuild
およびproductbuild
コマンドラインツールが推奨されるようになりました。これらの新しいツールは、より柔軟なパッケージ作成オプションを提供し、特にproductbuild
はカスタムのDistribution
ファイルを組み込むことで、インストールの事前チェックやUIのカスタマイズを容易にします。このコミットは、Goのビルドプロセスを最新のmacOS開発ツールチェーンに合わせるための重要なステップでした。 -
postinstall
スクリプトの堅牢化: インストール後に実行されるpostinstall
スクリプトにはいくつかの問題がありました。- 実行権限の問題: リポジトリ内のスクリプトが実行可能になっていなかったため、新しいパッケージツールで生成されたインストーラが正しく実行できない可能性がありました。
- Xcode関連パスのチェック方法の改善: Xcodeの仕様ディレクトリの存在チェックがファイル (
-f
) ではなくディレクトリ (-d
) として行われるべきでした。 - 不要な処理の削除: バイナリディストリビューションには
cov
(カバレッジツール) やprof
(プロファイリングツール) がバンドルされていないため、それらに関連するsudo.bash
の呼び出しは不要であり、削除することでスクリプトの簡素化とセキュリティの向上を図りました。
これらの変更は、GoのmacOSユーザーにとって、よりスムーズで信頼性の高いインストールプロセスを提供することを目的としています。
前提知識の解説
このコミットを理解するためには、以下のmacOSパッケージングとシェルスクリプトに関する知識が役立ちます。
-
macOSインストーラパッケージ (.pkg):
- macOSアプリケーションやシステムコンポーネメントを配布・インストールするための標準的な形式です。
- 通常、インストーラアプリケーション (
Installer.app
) を介して実行されます。 - 内部的には、ペイロード(インストールされるファイル群)、スクリプト(インストール前後に実行される処理)、メタデータ(パッケージ情報、インストール要件など)を含んでいます。
-
PackageMaker
:- かつてmacOSでインストーラパッケージを作成するために広く使われていたGUIツールおよびコマンドラインツールです。
- Xcodeの一部として提供されていましたが、後に非推奨となりました。
- このコミット以前のGoのビルドプロセスで利用されていました。
-
pkgbuild
:- macOSのコマンドラインツールで、コンポーネントパッケージ(Component Package)を作成するために使用されます。
- コンポーネントパッケージは、特定のファイルセット(ペイロード)と、それに関連するスクリプト(preinstall, postinstallなど)をまとめたものです。
pkgbuild
は、インストールされる実際のファイル群と、それらをどこに配置するか、どのようなスクリプトを実行するかといった基本的な情報をカプセル化します。
-
productbuild
:- macOSのコマンドラインツールで、配布パッケージ(Distribution Package)を作成するために使用されます。
- 複数のコンポーネントパッケージを一つにまとめたり、インストーラのUIや動作をカスタマイズするための
Distribution
ファイルを組み込んだりする際に使用されます。 productbuild
は、インストーラの全体的なフロー、表示される情報、インストール条件(OSバージョンチェックなど)を制御する能力を提供します。
-
Distribution
ファイル:productbuild
で使用されるXML形式のファイルです。- インストーラのタイトル、オプション、ドメイン、そして最も重要な
installation-check
スクリプトを定義します。 installation-check
スクリプトはJavaScriptで記述され、インストールの開始前に実行され、システムがインストール要件を満たしているかを確認します。このスクリプトがfalse
を返すと、インストールは中止され、指定されたエラーメッセージが表示されます。
-
postinstall
スクリプト:- macOSインストーラパッケージに含まれるシェルスクリプトの一つで、パッケージのファイルがターゲットシステムにコピーされた後に実行されます。
- インストール後のクリーンアップ、パーミッションの調整、環境変数の設定、追加の構成など、様々なタスクを実行するために使用されます。
- このコミットでは、このスクリプトの実行権限と内部ロジックが修正されています。
-
シェルスクリプトの条件式:
[ -f path ]
:path
が通常のファイルとして存在するかどうかをチェックします。[ -d path ]
:path
がディレクトリとして存在するかどうかをチェックします。- このコミットでは、
postinstall
スクリプト内でXcode関連のディレクトリの存在チェックが-f
から-d
に変更されています。
これらのツールと概念を理解することで、GoのmacOSパッケージングプロセスがどのように進化し、なぜこれらの変更が行われたのかを深く把握できます。
技術的詳細
このコミットにおける技術的な変更は、主にGoのビルドスクリプト (misc/dist/bindist.go
) とmacOSインストーラ関連ファイル (misc/dist/darwin/Distribution
, misc/dist/darwin/scripts/postinstall
) に集中しています。
-
PackageMaker
からpkgbuild
/productbuild
への移行:misc/dist/bindist.go
内で、PackageMaker
へのパスを定義していた定数packageMaker
が削除されました。- パッケージ作成ロジックが大幅に変更され、
b.run
関数(シェルコマンドを実行するGoのヘルパー関数)を使ってpkgbuild
とproductbuild
が呼び出されるようになりました。 pkgbuild
の使用:- まず、
ioutil.TempDir
で一時ディレクトリ (pkgdest
) を作成し、そこに中間的なコンポーネントパッケージを生成します。 pkgbuild
コマンドは、--identifier
(パッケージの識別子)、--version
、--scripts
(postinstallスクリプトの場所)、--root
(インストールされるファイルのルートディレクトリ)、そして出力パス (filepath.Join(pkgdest, "com.googlecode.go.pkg")
) を引数に取ります。これにより、Goのバイナリと関連ファイルを含む基本的なパッケージが作成されます。
- まず、
productbuild
の使用:- 次に、
productbuild
コマンドが呼び出され、最終的な配布パッケージが生成されます。 --distribution
引数には、新しく追加されたmisc/dist/darwin/Distribution
ファイルのパスが指定されます。このファイルはインストーラの動作とUIを制御します。--package-path
引数には、pkgbuild
で生成された中間パッケージが格納されている一時ディレクトリ (pkgdest
) が指定されます。- 最後の引数
targ
は、最終的な.pkg
ファイルの出力パスです。
- 次に、
- これにより、Goのインストーラは、より現代的なmacOSのパッケージング標準に準拠し、
Distribution
ファイルによる高度な制御が可能になりました。
-
Distribution
ファイルの導入 (misc/dist/darwin/Distribution
):- このコミットで新規に追加されたXMLファイルです。
installer-script
ルート要素を持ち、インストーラのメタデータと動作を定義します。- OSバージョンチェック: 最も重要な変更は、
installation-check
スクリプトの導入です。
このJavaScript関数<installation-check script="installCheck();"/> <script> function installCheck() { if(!(system.compareVersions(system.version.ProductVersion, '10.6.0') >= 0)) { my.result.title = 'Unable to install'; my.result.message = 'Go requires Mac OS X 10.6 or later.'; my.result.type = 'Fatal'; return false; } return true; } </script>
installCheck()
は、インストーラが起動する前に実行されます。system.compareVersions
を使用して現在のOSのバージョン (system.version.ProductVersion
) が10.6.0
以上であるかをチェックします。もし条件を満たさない場合、my.result
オブジェクトにエラーメッセージとタイトルを設定し、Fatal
タイプとしてインストールを中止します。これにより、ユーザーはインストールを開始する前に互換性の問題を明確に知ることができます。
-
postinstall
スクリプトの修正 (misc/dist/darwin/scripts/postinstall
):- 実行権限の変更: ファイルのパーミッションが
100644
(rw-r--r--) から100755
(rwxr-xr-x) に変更されました。これにより、スクリプトがインストーラによって正しく実行可能になります。 sudo.bash
の削除:
Goのバイナリディストリビューションには、デバッガに関連する-echo "Fixing debuggers via sudo.bash" -# setgrp procmod the debuggers (sudo.bash) -cd $GOROOT/src -./sudo.bash
cov
やprof
といったツールがバンドルされていないため、それらの設定を行うsudo.bash
の呼び出しは不要となり、削除されました。これはスクリプトの簡素化と、不要な特権操作の回避に貢献します。- Xcodeディレクトリチェックの修正:
Xcodeの仕様ディレクトリ (-if [ -f $XCODE_MISC_DIR ]; then +if [ -d "$XCODE_MISC_DIR" ]; then
/Library/Application Support/Developer/Shared/Xcode/Specifications/
) の存在チェックが、ファイル (-f
) ではなくディレクトリ (-d
) として行われるように修正されました。これは、パスがディレクトリを指している場合に正しいチェックを行うための重要な修正です。
- 実行権限の変更: ファイルのパーミッションが
これらの技術的な変更により、GoのmacOSパッケージはより現代的で、ユーザーフレンドリーなインストール体験を提供できるようになりました。
コアとなるコードの変更箇所
misc/dist/bindist.go
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -13,7 +13,6 @@ import (
"bytes"
"compress/gzip"
"encoding/base64"
- "errors"
"flag"
"fmt"
"io"
@@ -41,8 +40,7 @@ var (
)
const (
- packageMaker = "/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
- uploadURL = "https://go.googlecode.com/files"
+ uploadURL = "https://go.googlecode.com/files"
)
var preBuildCleanFiles = []string{
@@ -231,7 +229,7 @@ func (b *Build) Do() error {
return err
}
localDir := filepath.Join(work, "usr/local")
- err = os.MkdirAll(localDir, 0744)
+ err = os.MkdirAll(localDir, 0755)
if err != nil {
return err
}
@@ -240,27 +238,29 @@ func (b *Build) Do() error {
return err
}
// build package
- pkginfo, err := createPackageInfo(work)
+ pkgdest, err := ioutil.TempDir("", "pkgdest")
if err != nil {
return err
}
- defer os.Remove(pkginfo)
- pm := packageMaker
- if !exists(pm) {
- pm = "/Developer" + pm
- if !exists(pm) {
- return errors.New("couldn't find PackageMaker")
- }
+ defer os.RemoveAll(pkgdest)
+ dist := filepath.Join(runtime.GOROOT(), "misc/dist")
+ _, err = b.run("", "pkgbuild",
+ "--identifier", "com.googlecode.go",
+ "--version", "1.0",
+ "--scripts", filepath.Join(dist, "darwin/scripts"),
+ "--root", work,
+ filepath.Join(pkgdest, "com.googlecode.go.pkg"))
+ if err != nil {
+ return err
}
targ := base + ".pkg"
- scripts := filepath.Join(work, "usr/local/go/misc/dist/darwin/scripts")
- _, err = b.run("", pm, "-v",
- "-r", work,
- "-o", targ,
- "--info", pkginfo,
- "--scripts", scripts,
- "--title", "Go",
- "--target", "10.5")
+ _, err = b.run("", "productbuild",
+ "--distribution", filepath.Join(dist, "darwin/Distribution"),
+ "--package-path", pkgdest,
+ targ)
+ if err != nil {
+ return err
+ }
targs = append(targs, targ)
case "windows":
// Create ZIP file.
@@ -806,30 +806,3 @@ 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"+
- "\\t<payload installKBytes=\"%v\" numberOfFiles=\"%v\"/>\\n"+
- "</pkg-info>\\n", size/1024, nfiles)
- if err != nil {
- return "", err
- }
- return pi.Name(), nil
-}
misc/dist/darwin/Distribution
(新規ファイル)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-script minSpecVersion="1.000000">
<title>Go</title>
<options customize="never" allow-external-scripts="no"/>
<domains enable_localSystem="true" />
<installation-check script="installCheck();"/>
<script>
function installCheck() {
if(!(system.compareVersions(system.version.ProductVersion, '10.6.0') >= 0)) {
my.result.title = 'Unable to install';
my.result.message = 'Go requires Mac OS X 10.6 or later.';
my.result.type = 'Fatal';
return false;
}
return true;
}
</script>
<choices-outline>
<line choice="com.googlecode.go.choice"/>
</choices-outline>
<choice id="com.googlecode.go.choice" title="Go">
<pkg-ref id="com.googlecode.go.pkg"/>
</choice>
<pkg-ref id="com.googlecode.go.pkg" auth="Root">com.googlecode.go.pkg</pkg-ref>
</installer-script>
misc/dist/darwin/scripts/postinstall
--- a/misc/dist/darwin/scripts/postinstall
+++ b/misc/dist/darwin/scripts/postinstall
@@ -9,14 +9,9 @@ find bin -exec chmod ugo+rx \\{\\} \\;\n find . -type d -exec chmod ugo+rx \\{\\} \\;\n chmod o-w .\n \n-echo "Fixing debuggers via sudo.bash"\n-# setgrp procmod the debuggers (sudo.bash)\n-cd $GOROOT/src\n-./sudo.bash
-\n echo "Installing miscellaneous files:"\n XCODE_MISC_DIR="/Library/Application Support/Developer/Shared/Xcode/Specifications/"\n-if [ -f $XCODE_MISC_DIR ]; then
-+if [ -d "$XCODE_MISC_DIR" ]; then
\techo " XCode"\n \tcp $GOROOT/misc/xcode/* $XCODE_MISC_DIR\n fi
コアとなるコードの解説
misc/dist/bindist.go
の変更点
PackageMaker
関連の削除:packageMaker
定数とcreatePackageInfo
関数が削除されました。これは、GoのmacOSパッケージ作成プロセスがPackageMaker
から完全に移行したことを意味します。- ディレクトリパーミッションの変更:
os.MkdirAll(localDir, 0744)
がos.MkdirAll(localDir, 0755)
に変更されました。0744
は所有者に読み書き実行、グループとその他に読み取りのみを許可しますが、0755
は所有者に読み書き実行、グループとその他に読み取りと実行を許可します。これは、インストールされるディレクトリの実行権限をより適切に設定するための変更と考えられます。 pkgbuild
とproductbuild
の導入:ioutil.TempDir("", "pkgdest")
で一時ディレクトリを作成し、pkgbuild
コマンドの出力先として利用しています。b.run("", "pkgbuild", ...)
:pkgbuild
を呼び出し、Goのインストールルート (work
) をペイロードとして、misc/dist/darwin/scripts
をスクリプトディレクトリとして指定し、中間パッケージ (com.googlecode.go.pkg
) を生成します。b.run("", "productbuild", ...)
:productbuild
を呼び出し、misc/dist/darwin/Distribution
ファイルを配布設定として、pkgbuild
で生成された中間パッケージ (pkgdest
) をソースとして、最終的な.pkg
ファイルを生成します。このDistribution
ファイルが、OSバージョンチェックなどのインストーラ動作を定義します。
- エラーハンドリングの改善:
errors
パッケージのインポートが不要になったのは、createPackageInfo
関数が削除されたためです。
misc/dist/darwin/Distribution
の新規追加
このXMLファイルは、macOSインストーラの振る舞いを定義する中心的な役割を担います。
title
: インストーラのウィンドウに表示されるタイトルを「Go」と設定します。options
: インストーラのカスタマイズを許可しない (customize="never"
)、外部スクリプトを許可しない (allow-external-scripts="no"
) といったオプションを設定します。installation-check
: ここが最も重要な部分で、installCheck()
というJavaScript関数をインストールの事前チェックとして指定しています。script
ブロック:installCheck()
関数の実装が含まれています。system.compareVersions(system.version.ProductVersion, '10.6.0') >= 0
は、現在のmacOSのバージョンが10.6.0以上であるかを比較します。- もしバージョンが要件を満たさない場合、
my.result.title
、my.result.message
、my.result.type
を設定し、Fatal
タイプのエラーとしてインストールを中止します。これにより、ユーザーは「Go requires Mac OS X 10.6 or later.」という明確なメッセージを受け取ります。
choices-outline
とchoice
: インストールするパッケージの選択肢を定義します。ここでは「Go」という単一の選択肢が提供され、com.googlecode.go.pkg
というパッケージを参照しています。pkg-ref
: 実際にインストールされるパッケージの参照を定義します。
misc/dist/darwin/scripts/postinstall
の変更点
- 実行権限の変更: ファイルモードが
100644
から100755
に変更されました。これは、このスクリプトがインストーラによって実行される際に、適切な実行権限を持つことを保証します。 sudo.bash
関連コードの削除:echo "Fixing debuggers via sudo.bash"
やcd $GOROOT/src; ./sudo.bash
といった行が削除されました。- これは、Goのバイナリディストリビューションには
cov
やprof
といったデバッガ関連ツールがバンドルされていないため、それらの設定を行うためのsudo.bash
の呼び出しが不要になったためです。これにより、スクリプトが簡素化され、不要な特権操作が回避されます。
- Xcodeディレクトリチェックの修正:
if [ -f $XCODE_MISC_DIR ]; then
がif [ -d "$XCODE_MISC_DIR" ]; then
に変更されました。XCODE_MISC_DIR
は/Library/Application Support/Developer/Shared/Xcode/Specifications/
を指しており、これはディレクトリです。[ -f ... ]
はファイルが存在するかをチェックするのに対し、[ -d ... ]
はディレクトリが存在するかをチェックします。この修正により、Xcode関連のファイルのコピーが、正しい条件で実行されるようになりました。
これらの変更は、GoのmacOSパッケージのビルドとインストールプロセスを、より現代的で堅牢、かつユーザーフレンドリーなものにするための重要なステップです。
関連リンク
- GitHub上のコミットページ
- Gerrit Change-ID: 5987044
- Go Issue #3455: misc/dist: require 10.6 or later for OS X .pkgs