メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

新機能

リンカに -macos / -macsdk フラグを追加し、内部リンクモードでも LC_BUILD_VERSION の OS/SDK バージョンを指定可能にした

Linker

この項目の注釈は AI により生成されており、誤りを含む場合があります。

概要

macOSをターゲットにする際、リンカが新たに -macos-macsdk というコマンドラインオプションを受け付けるようになった。これらはMach-Oバイナリの LC_BUILD_VERSION ロードコマンドに書き込むOSバージョンとSDKバージョンをそれぞれ指定する。デフォルトでは、サポートされる最も古いmacOSバージョン(現時点で13.0.0)と、比較的新しいSDKバージョン(現時点で26.2.0)が選択される。いずれのフラグも内部リンクモード(internal linking)でのみ有効である。

導入経緯

golang/go#58722 では、リンカが LC_BUILD_VERSION の最小SDKバージョンをamd64向けに10.13.0、arm64向けに11.0にハードコードしていることが報告された。報告者はLinuxホストからmacOS向けにクロスコンパイルしつつターゲットの最小macOS SDKバージョンを指定したいというユースケースを持っており、外部リンクモードでは -extldflags=-mmacosx-version-min=... を使えば対応できるものの、クロスコンパイル時に必要な内部リンカには同等の指定手段がなかった。

背景として、macOSカーネル側で LC_BUILD_VERSIONsdk フィールドの値に応じて /System/Library/CoreServices/SystemVersion.plist の内容が変化するという挙動が挙げられており(sdk が11.0未満だと ProductVersion が10.16に偽装される)、amd64とarm64でデフォルトのSDKバージョンが異なっていたため、universal binaryのスライス間で挙動が変わってしまう問題が報告されていた。バイナリの LC_BUILD_VERSION を後処理で書き換えるワークアラウンドも提示されたが、最終的には CL 751260 によりリンカ側に -macos/-macsdk フラグが追加された。

議論のハイライト

  • フラグ追加に対しては「フラグが増えるとテストすべき組み合わせの数が増える」という慎重な意見があった。
  • 外部リンクモードでは -extldflags=-mmacosx-version-min=... で同等のことができるが、クロスコンパイル時に内部リンカを使う場合はこの手段が使えない点が課題として挙げられた。
  • バイナリの LC_BUILD_VERSION を後処理(post-process)で直接書き換えるワークアラウンドも提示されたが、根本解決としてリンカへのフラグ追加が採用された。

実装解説

-macos-macsdk はいずれもmain.goの該当箇所flag.Var により登録され、値はmacho.goで定義された macVersionFlag([3]byteX.Y.Z 形式をパースする flag.Value 実装)型のパッケージ変数 macOS/macSDK に格納される。デフォルト値macOS = {13, 0, 0}macSDK = {26, 2, 0} である。これらの値は内部リンクモードのMach-Oヘッダ生成処理 domacho 内で、LC_BUILD_VERSION ロードコマンドの minos/sdk フィールド(該当行)として書き込まれる。

関連リンク