Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16766] ファイルの概要

このコミットは、Go言語のディストリビューションにおけるmacOS (Darwin) 向けのpostinstallスクリプトの修正に関するものです。具体的には、misc/dist/darwin/scripts/postinstallファイルが変更されており、Goのインストール後にXcode関連のファイルを正しく配置するための処理が改善されています。

コミット

このコミットは、macOS環境におけるGoのpostinstallスクリプトが、Xcode関連ファイルのコピーに失敗する問題を修正します。主な原因は、パスにスペースが含まれる場合のcpコマンドの引用符の欠如と、Xcodeのバージョンに応じた適切なソースディレクトリの選択ができていなかった点です。この修正により、Xcode 3またはXcode 4のどちらがインストールされているかに応じて、適切なGoのXcodeサポートファイルが正しくコピーされるようになります。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/bbb51ae3a9dc8da80d9f48c122d8a75aead69c09

元コミット内容

commit bbb51ae3a9dc8da80d9f48c122d8a75aead69c09
Author: Alexandre Normand <alexandre.normand@gmail.com>
Date:   Mon Jul 15 10:52:38 2013 +1000

    dist: fix postinstall script for Darwin
    
    The postinstall script causes the installation to fail because the last
    step that copies files for Xcode is broken. Two details can cause the
    command to fail:
      1. The XCODE_MISC_DIR value has a space. Without quotes in the cp
         command, cp will just complain that this is an invalid syntax.
      2. The source of the cp is a directory with two subdirectories.
         We actually want the files for either Xcode 3 or Xcode 4 to be copied.
         Using xcodebuild -version, we check for the Xcode version and
         select which of xcode/3/* or xcode/4/* should be the source
         of the copy.
    
    Fixes #5874.
    
    R=golang-dev, minux.ma, adg
    CC=golang-dev
    https://golang.org/cl/10893044

変更の背景

この変更は、Goのインストールプロセスにおける既知のバグ、Issue 5874 (Fixes #5874) を解決するために行われました。報告された問題は、macOS環境でGoをインストールする際に実行されるpostinstallスクリプトが、Xcode関連のファイルをコピーする最終ステップで失敗するというものでした。

失敗の具体的な原因は以下の2点でした。

  1. パス内のスペースの問題: Xcodeのサポートファイルをコピーする先のディレクトリパス (/Library/Application Support/Developer/Shared/Xcode/Specifications/) にはスペースが含まれています。シェルスクリプトにおいて、スペースを含むパスを引用符で囲まないと、シェルはそれを複数の引数として解釈してしまい、cpコマンドが不正な構文エラーを発生させます。
  2. Xcodeバージョンの特定とソース選択の不備: 以前のスクリプトでは、$GOROOT/misc/xcode/*という形で、xcodeディレクトリ直下の全てのファイルをコピーしようとしていました。しかし、xcodeディレクトリには34というサブディレクトリがあり、それぞれXcode 3とXcode 4に対応するファイルが含まれていました。スクリプトは、インストールされているXcodeのバージョンに応じて、xcode/3/*またはxcode/4/*のどちらか一方のファイルをコピーする必要がありました。この選択が行われていなかったため、適切なファイルがコピーされず、インストールが不完全になる可能性がありました。

これらの問題により、Goのインストールが正常に完了せず、ユーザーエクスペリエンスが損なわれていました。このコミットは、これらの問題を修正し、macOSユーザーがGoをスムーズにインストールできるようにすることを目的としています。

前提知識の解説

このコミットを理解するためには、以下の前提知識が必要です。

  • postinstallスクリプト: ソフトウェアのインストールプロセスにおいて、主要なファイルの配置が完了した後に実行されるスクリプトです。追加の設定、ファイルの移動、キャッシュのクリアなど、インストール後の最終処理を行います。Goのディストリビューションでは、Xcodeとの連携に必要なファイルを配置するために使用されていました。
  • Xcode: Appleが提供するmacOSおよびiOSアプリケーション開発のための統合開発環境 (IDE) です。Go言語で開発されたツールがXcodeと連携する場合、特定のディレクトリにファイルを配置する必要があります。
  • xcodebuildコマンド: Xcodeに付属するコマンドラインツールで、プロジェクトのビルド、テスト、アーカイブなど、Xcode関連の様々な操作を行うことができます。特に、xcodebuild -versionはインストールされているXcodeのバージョン情報を取得するために使用されます。
  • cpコマンド: Unix系OSでファイルやディレクトリをコピーするためのコマンドです。
    • cp source destination: sourcedestinationにコピーします。
    • cp -r source_dir destination_dir: source_dirとその内容を再帰的にdestination_dirにコピーします。
    • ワイルドカード (*): シェルにおいて、ファイル名の一部を任意の文字列にマッチさせるために使用されます。例えば、*.txtは拡張子が.txtの全てのファイルにマッチします。
  • シェルスクリプトの引用符: シェルスクリプトでは、スペースや特殊文字を含む文字列を一つの引数として扱うために、ダブルクォーテーション (") またはシングルクォーテーション (') で囲む必要があります。ダブルクォーテーション内では変数展開 ($VAR) が行われますが、シングルクォーテーション内では行われません。
  • if [ -d "path" ]: シェルスクリプトの条件分岐で、指定されたpathがディレクトリとして存在するかどうかをチェックします。
  • mkdir -p: ディレクトリを作成するコマンドです。-pオプションを付けると、親ディレクトリが存在しない場合でも、それらも同時に作成します。既にディレクトリが存在してもエラーになりません。
  • sedコマンド: ストリームエディタ (Stream EDitor) で、テキストの変換や置換を行うために使用されます。
    • sed -n -E 's/pattern/replacement/p': -nは通常出力を抑制し、pフラグが付いた行のみを出力します。-Eは拡張正規表現を使用可能にします。s/pattern/replacement/patternにマッチした部分をreplacementに置換します。
  • grepコマンド: テキストファイルから特定のパターンにマッチする行を検索して表示するコマンドです。
  • $? (終了ステータス): シェルスクリプトにおいて、直前に実行されたコマンドの終了ステータスを保持する特殊変数です。通常、0は成功を意味し、0以外は失敗を意味します。
  • [[ ... ]]: Bashなどのシェルで使われる条件式です。[ ... ]よりも高機能で、正規表現マッチング (=~) やより複雑な条件式をサポートします。

技術的詳細

このコミットの技術的詳細は、macOSのファイルシステム構造、Xcodeのバージョン管理、および堅牢なシェルスクリプトの記述に焦点を当てています。

  1. Xcode関連ファイルの配置パス: GoのXcodeサポートファイルは、XcodeがGo言語を認識し、Goプロジェクトを適切に扱えるようにするために、特定のディレクトリに配置される必要があります。このパスは/Library/Application Support/Developer/Shared/Xcode/Specifications/であり、このパスにはスペースが含まれています。以前のスクリプトでは、このパスをcpコマンドの引数として渡す際に引用符で囲んでいなかったため、シェルがパスを複数の単語として解釈し、cpコマンドがエラーを発生させていました。

  2. Xcodeバージョンの動的な検出: GoのXcodeサポートファイルは、Xcode 3とXcode 4で異なる構造を持っていました。以前のスクリプトは、単純に$GOROOT/misc/xcode/*をコピーしようとしていましたが、これはxcode/3xcode/4の両方の内容をコピーしようとするか、あるいは意図しない動作を引き起こす可能性がありました。 この修正では、/usr/bin/xcodebuild -versionコマンドを使用して、現在インストールされているXcodeのバージョンを動的に検出します。

    • xcodebuild -versionの出力例: Xcode 4.6.3
    • sed -n -E 's/^Xcode ([0-9]+)\..*$/\1/p'は、この出力からメジャーバージョン番号(例: 4)を抽出します。
      • ^Xcode : 行頭の"Xcode "にマッチ。
      • ([0-9]+): 1つ以上の数字にマッチし、それをキャプチャグループ1として記憶。これがXcodeのメジャーバージョン番号になります。
      • \.: ドット文字にマッチ(エスケープが必要)。
      • .*$: 残りの任意の文字にマッチし、行末まで。
      • \1: キャプチャグループ1の内容(メジャーバージョン番号)に置換。
      • p: マッチした行をプリント。
    • この抽出されたバージョン番号 (version変数) を使用して、$GOROOT/misc/xcode/$version/*というパスを構築し、適切なバージョンのファイルのみをコピーするようにします。
  3. xcodebuild -versionの失敗時のフォールバック: コミットメッセージにもあるように、Xcode 4ではコマンドラインツールがオプションであったため、xcodebuild -versionコマンドが失敗する可能性がありました。スクリプトは、このコマンドの終了ステータス ($?) をチェックし、失敗 ($? -ne 0) した場合には、デフォルトでXcode 4が使用されていると解釈し、version=4を設定するフォールバックロジックが追加されました。これにより、コマンドラインツールがインストールされていない環境でも、スクリプトが適切に動作するようになります。

  4. ディレクトリの存在確認と作成: XCODE_SHARED_DIR (/Library/Application Support/Developer/Shared/Xcode) が存在するかどうかを確認し、存在しない場合はmkdir -p "$XCODE_MISC_DIR"で必要なディレクトリ構造を再帰的に作成するように変更されました。これにより、ターゲットディレクトリが存在しない場合でもスクリプトが失敗することなく、必要なディレクトリが自動的に作成されます。

これらの変更により、スクリプトはより堅牢になり、様々なmacOS環境およびXcodeのバージョンに対応できるようになりました。

コアとなるコードの変更箇所

--- a/misc/dist/darwin/scripts/postinstall
+++ b/misc/dist/darwin/scripts/postinstall
@@ -10,9 +10,22 @@ find . -type d -exec chmod ugo+rx \\{\\} \\;\n chmod o-w .\n \n echo "Installing miscellaneous files:"\n-XCODE_MISC_DIR="/Library/Application Support/Developer/Shared/Xcode/Specifications/"\n-if [ -d "$XCODE_MISC_DIR" ]; then\n-\techo "  XCode"\n-\tcp $GOROOT/misc/xcode/* $XCODE_MISC_DIR
+XCODE_SHARED_DIR="/Library/Application Support/Developer/Shared/Xcode"\n+XCODE_MISC_DIR="$XCODE_SHARED_DIR/Specifications/"\n+if [ -d "$XCODE_SHARED_DIR" ]; then
+\t# Create the XCODE_MISC_DIR if it doesn\'t exist already
+\tmkdir -p "$XCODE_MISC_DIR"\n+\n+\tversion=`/usr/bin/xcodebuild -version | sed -n -E \'s/^Xcode ([0-9]+)\\..*$/\\1/p\'`\n+        \n+        # Since command line tools are optional with Xcode 4, a failure of the \n+\t# xcodebuild -version command is interpreted as meaning Xcode 4 is the \n+\t# version used.\n+\tif [[ $? -ne 0 ]]; then\n+\t\tversion=4\n+\tfi\n+\n+        echo "  Xcode $version"\n+\tcp $GOROOT/misc/xcode/$version/* "$XCODE_MISC_DIR"\n fi

コアとなるコードの解説

変更されたコードブロックは、Goのインストール後にXcode関連のファイルを正しく配置するためのロジックを含んでいます。

  1. XCODE_SHARED_DIRXCODE_MISC_DIRの定義:

    XCODE_SHARED_DIR="/Library/Application Support/Developer/Shared/Xcode"
    XCODE_MISC_DIR="$XCODE_SHARED_DIR/Specifications/"
    

    XCODE_SHARED_DIRはXcodeの共有サポートファイルのルートディレクトリを定義します。XCODE_MISC_DIRは、その中に含まれるSpecificationsディレクトリを指し、GoのXcodeサポートファイルが最終的にコピーされる場所です。以前のバージョンではXCODE_MISC_DIRが直接定義されていましたが、XCODE_SHARED_DIRを導入することで、パスの構造がより明確になり、後のmkdir -pでの使用が容易になります。

  2. XCODE_SHARED_DIRの存在チェック:

    if [ -d "$XCODE_SHARED_DIR" ]; then
    

    XCODE_SHARED_DIRが存在するかどうかを確認します。このディレクトリが存在しない場合、Xcodeがインストールされていないか、異なるパスにインストールされている可能性があり、Xcode関連ファイルのコピーは意味がありません。

  3. XCODE_MISC_DIRの作成:

    # Create the XCODE_MISC_DIR if it doesn\'t exist already
    mkdir -p "$XCODE_MISC_DIR"
    

    XCODE_MISC_DIRが存在しない場合に、mkdir -pコマンドを使用してそのディレクトリを作成します。-pオプションにより、必要な親ディレクトリも同時に作成されるため、スクリプトの堅牢性が向上します。また、パスがダブルクォーテーションで囲まれているため、パスにスペースが含まれていても正しく処理されます。

  4. Xcodeバージョンの検出:

    version=`/usr/bin/xcodebuild -version | sed -n -E \'s/^Xcode ([0-9]+)\\..*$/\\1/p\'`
    

    /usr/bin/xcodebuild -versionを実行し、その出力からXcodeのメジャーバージョン番号を抽出します。sedコマンドが正規表現を使用してバージョン番号をパースし、結果をversion変数に格納します。

  5. xcodebuildコマンド失敗時のフォールバック:

    # Since command line tools are optional with Xcode 4, a failure of the 
    # xcodebuild -version command is interpreted as meaning Xcode 4 is the 
    # version used.
    if [[ $? -ne 0 ]]; then
    	version=4
    fi
    

    直前のxcodebuildコマンドの終了ステータス ($?) をチェックします。もし0以外(失敗)であれば、Xcode 4のコマンドラインツールがインストールされていない可能性を考慮し、version変数を4に設定します。これにより、コマンドラインツールが不足している環境でも、スクリプトがXcode 4用のファイルをコピーしようとします。

  6. Xcodeバージョンに応じたファイルのコピー:

    echo "  Xcode $version"
    cp $GOROOT/misc/xcode/$version/* "$XCODE_MISC_DIR"
    

    検出された(またはフォールバックされた)Xcodeバージョン ($version) を使用して、$GOROOT/misc/xcode/$version/ディレクトリから、XcodeのサポートファイルをXCODE_MISC_DIRにコピーします。ここでも、XCODE_MISC_DIRがダブルクォーテーションで囲まれているため、スペースを含むパスが正しく扱われます。以前のcp $GOROOT/misc/xcode/* $XCODE_MISC_DIRという行と比較すると、$versionが追加されたことで、Xcodeのバージョンに応じた適切なサブディレクトリからファイルがコピーされるようになり、問題が解決されています。

これらの変更により、postinstallスクリプトはより堅牢で、Xcodeのバージョンやコマンドラインツールの有無といった様々なmacOS環境のバリエーションに対応できるようになりました。

関連リンク

参考にした情報源リンク