← すべての記事

Xcode 27でld64が削除され、モジュール名の一意性が必須に

Appleはリンカの引退を一文で告げました。「ld64リンカは削除され、-ld_classicオプションはサポートされなくなりました」1。消えたこのフラグは、ほかならぬApple自身が開発者に追加せよと指示したフラグです。Xcode 15のリリースノートは、2件のリンカ不具合の回避策として-Wl,-ld_classicを提示していました3

要点

  • Xcode 27はld64を削除し、-ld_classicを受け付けなくなります1。AppleはXcode 15のノートで、弱シンボル起因のクラッシュとLTOのインポート不具合に対してこのフラグを処方し、Xcode 16で非推奨とし、Xcode 26では何も述べませんでした3410
  • 2つ目の破壊的変更はSwiftコンパイラ側にあります。Appleは依存関係スキャンを1つの共有アクションにまとめたため、「単一のSwift依存関係スキャンアクションから到達可能なすべてのClangモジュールは、一意のモジュール名を持たなければならない」ことになりました2。Appleは2度にわたって断定を避けています。スキャンは「エラーを報告する場合があります」、そして以前のスキャナは「名前の重複を許容していた場合があります」という書き方です2
  • どちらもデプロイメントターゲットやSDKの選択ではなくツールチェーンの更新で発火し、実行時の要素はありません。影響を受けるのは、ベンダー提供のバイナリ、CocoaPods、あるいはSwift/Objective-C/C++が混在する大規模コードベースを抱えたプロジェクトです。
  • Appleの「場合があります」は編集上の慎重さではありません。Xcode 26.6で同一の名前を宣言する2つのモジュールマップを1つの検索パスに置き、スキャナを20回走らせたところ、9回はSIGSEGVでクラッシュ、5回はabort、6回は正常終了しました8
  • Appleが名指しするケース、つまりSDKのモジュールを再宣言するベンダー提供のモジュールマップは、現在のところ何も言わずにコンパイルが通り、本物のモジュールを覆い隠します。私が用意したSQLite3のベンダー版シムは終了コード0で型チェックを通過し、sqlite3_openは存在しないものになりました8
  • 監査した7プロジェクトの結果は、-ld_classicがゼロ、OTHER_LDFLAGSはどこでも未設定、391件のモジュールマップに重複名ゼロ。どのリポジトリにも手書きのモジュールマップが1つも無いからです9

いずれの記載もXcode 27 beta 4のリリースノートに、Swift 6.4および27系SDKと並んで掲載されています11。ベータ段階の文章として読んでください。

Appleが「追加せよ」と言ったフラグ

話はリンカの書き換えから始まります。Xcode 15は新しいリンカを発表し、「すべてのmacOS、iOS、tvOS、visionOSバイナリ」でこれを既定とし、引退の条件を一文で定めました。「クラシックリンカは-ld64で明示的に要求できますが、将来のリリースで削除されます」3

新リンカにはバグがあり、Appleは同じページで2度、脱出口を文書化しました。1つ目のKnown Issueはこうです。「弱定義シンボルを使うバイナリは、iOS 14/macOS 12以前で実行時にクラッシュします。弱シンボルを多用するため、主にC++プロジェクトに影響します」。Appleが示した回避策は、デプロイメントターゲットを引き上げるか「OTHER_LDFLAGSビルド設定に-Wl,-ld_classicを追加する」ことでした3。2つ目は、LTOオブジェクトファイルが弱シンボルのインポートを非弱としてリンクしてしまう問題で、同じ設定に「-Wl,-weak_reference_mismatches,weakまたは-Wl,-ld_classic」を追加せよというものです3

どちらの不具合もC++プロジェクトを最も強く直撃しました。今なおこのフラグを抱えているのが誰なのか、その理由はここにあります。クラッシュを止めた設定を、あとから見直す人はいないのです。

Xcode 16の予告も一文でした。「-ld_classicリンカオプションは非推奨であり、将来のリリースで削除されます」4。以降は沈黙です。Xcode 26のリリースノートをld_classicld64、クラシックリンカで検索しましたが、該当箇所はありませんでした10

現行のツールチェーンは今もフラグを受け付け、今も苦情を言います。Xcode 26.6で、ごく単純なCプログラムをこのフラグ付きでリンクしてみました7

xcrun clang hello.c -o hello -Wl,-ld_classic
ld: warning: -ld_classic is deprecated and will be removed in a future release

終了ステータスはゼロ。バイナリはリンクされます。-Wl,-ld64に置き換えても-ld_classicを名指しする同一の警告が出るので、Appleが用いた2つの綴りは現時点で同じコードパスに到達しています7。AppleのXcode 27のノートが名指ししているのは-ld_classicだけであり、-ld64が同様に失敗するかどうかは検証できませんでした。

「削除」という語を一筋縄ではいかなくする事実が1つあります。Xcode 26.6のリンカにxcrun ld -vで素性を尋ねると、どのアーキテクチャを委譲しているかを教えてくれます7

@(#)PROGRAM:ld PROJECT:ld-1267
BUILD 16:38:58 Jun  8 2026
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em armv8m.main armv8.1m.main
will use ld-classic for: armv6 armv7 armv7s i386 armv6m armv7k armv7m armv7em

ld-classicはツールチェーン内に実体のあるバイナリとして存在し、独自のmanページも持っていて、リンカは今も8つのアーキテクチャをそこへ回しています7。ただし、現行のアプリ向けSDKに生き残っているものは1つもありません。iPhoneOS 26.5が宣言するのはarm64earm64のみ、watchOSのSDKがこれにarm64_32を加えるだけです7。委譲先の一覧は32ビットARM、i386、Cortex-M組み込みターゲットです。SDKに存在しないことをもって、アプリ開発者にとって今回の削除は安全だと読むのは、Appleの主張ではなく私の推論です。

grepに頼らずフラグを見つける

-ld_classicが住むのはOTHER_LDFLAGSです。ですからファイルを文字列検索するのではなく、ビルドシステムに最終的な解決値を尋ねましょう。

xcodebuild -showBuildSettings \
  -project YourApp.xcodeproj \
  -configuration Release -sdk iphoneos 2>/dev/null \
  | grep -E "OTHER_LDFLAGS|SUPPORTED_PLATFORMS"

Repsプロジェクトに対して実行すると、返ってくるのは1行だけです9

    SUPPORTED_PLATFORMS = appletvos appletvsimulator iphoneos iphonesimulator macosx

OTHER_LDFLAGSはまったく現れません。それこそが答えです。設定が未設定であり、そこからリンク段階に渡るリンカフラグは存在しないという意味になります。解決済みビルド設定における不在は、テキスト検索での不在が持ち得ない情報を持っているのです。プラットフォームの確認にもSUPPORTED_PLATFORMSを読んでください。*_DEPLOYMENT_TARGETは、対象が実在するかどうかに関係なくXcodeが書き込むので使えません。

監査中、偽の「クリーン」を生んだ罠が3つありました。いずれも何も出力せず、正常終了します。まずtimeoutは素のmacOSに存在しないため、xcodebuildをこれで包むと終了コード127と空の出力が返り、リンカフラグの無いプロジェクトのように見えてしまいます。次にzshでは、クォートしない--include=*.pbxprojがgrepに届く前にグロブ展開され、ヒット0件の報告ではなく「no matches found」でコマンドが死にます。そしてfindは、起点として与えられたシンボリックリンクを辿りません。これはxcrun --sdk iphoneos --show-sdk-pathが返すのがまさにシンボリックリンクだから重要になります。find "$SDK" -name '*.modulemap'は何も見つけませんが、find -H "$SDK"なら266件を見つけます9。パターンはクォートし、-Hを渡し、ゼロを信じる前に「そこにあると分かっているもの」にコマンドがヒットするか確かめてください。

手で管理しているターゲットなら、フラグはproject.pbxproj.xcconfigに入っています。CocoaPodsプロジェクトの場合はpost_installフックから注入されることもあり、これは開発者が編集するどのファイルにも記録されません。私が監査した一群にはどちらも無いため、この最後の経路は未検証です9

モジュール名ルールと、Appleの2つの留保

2つ目の破壊的変更は、性能改善という装いで、Deprecationsではなく新機能の項に収められています。AppleのSwiftコンパイラの項目は全文でこうです。

Swiftの依存関係スキャナは、単一の依存関係スキャンアクション中にClangモジュールを検索する際、冗長なセットアップ作業とヘッダ検索を回避するよう最適化され、スキャン性能が大幅に向上しました。この変更の結果として、単一のSwift依存関係スキャンアクションから到達可能なすべてのClangモジュールは、一意のモジュール名を持たなければなりません。同一のスキャンから見える2つのモジュールマップが同じ名前のClangモジュールを宣言している場合、スキャンはエラーを報告する場合があります。以前のスキャナは、名前の重複を許容していた場合があります。最も多いのは、ヘッダ検索パス上の複数の場所から同じClangモジュール名を提供しているプロジェクトやSDK、そしてSDKのモジュールを再宣言するmodule.modulemapを同梱するベンダー提供のサードパーティソースです。2

ここには切り分けるべきものが4つあります。まずAppleは要件の範囲を、ディスク全体ではなく1回のスキャンが到達できる範囲に限定しています。次に帰結を「エラーを報告する場合があります」と述べ、従来の挙動についても同じ調子で留保しています。さらに発火する2つの形を名指ししています。ヘッダ検索パス上の2箇所から提供される1つのモジュール名と、SDKのモジュールを再宣言するベンダー提供のmodule.modulemapです。そして引き金はツールチェーンです。デプロイメントターゲットにもSDKのバージョンにも一切言及がないからです。

ルール自体は最適化より前から存在します。Clangのモジュールマップ言語の仕様は端的にこう述べています。「各モジュールは単一の定義を持たなければならない」6。文書がついぞ述べていないのは、このルールを破ったときに何が起きるかです。そしてその沈黙には十分な理由がありました。ツールチェーンの答えは1つの挙動ではなく、複数だったのです。

衝突は実際に何を引き起こすか

Appleの留保を読んで、その失敗を自分の目で見たくなりました。そこで最小構成を組みました。ディレクトリを2つ用意し、それぞれに同じモジュールを宣言するmodule.modulemapを置きます8

A/module.modulemap    B/module.modulemap
module Widget {       module Widget {
    header "widget.h"     header "widget.h"
    export *              export *
}                     }

両方のディレクトリを検索パスに載せた状態では、単純な型チェックは毎回まったく同じ形で失敗しました。20回中20回です8

B/module.modulemap:1:8: error: redefinition of module 'Widget'
1 | module Widget {
  |        `- error: redefinition of module 'Widget'
A/module.modulemap:1:8: note: previously defined here

ビルドログで探すべき文字列はredefinition of moduleであり、Xcode 26.6のclangはすでにこれを出力します。検索パスの片方を外すと同じコンパイルが成功することから、引き金はディスク上に存在することではなく、1回のコンパイルから見えることだと確認できました8

依存関係スキャナの振る舞いは異なります。そしてこの違いこそが、Appleが「場合があります」と書いた理由のすべてです。同じ2つのモジュールマップをswiftc -scan-dependenciesに20回通したところ、結果は3種類に分かれました。SIGSEGVによるクラッシュが9回、abortが5回、正常終了が6回です8。クラッシュした実行のスタックトレースはperformParallelClangModuleLookupを通過しており、これはAppleが置き換えたと述べている並列検索での競合と整合します。ただし、この非決定性をその競合に帰するのは、トレースに対する私の読みであってAppleの言明ではありません。

Appleが名指しした2つ目のケースは、静かなほうです。iPhoneOS SDKに実在するモジュールであるSQLite3を宣言するベンダー提供のモジュールマップを書き、検索パスに載せてコンパイルしてみました8

Vendor/module.modulemap
module SQLite3 {
    header "shim.h"
    export *
}

コンパイルは成功しました。終了コード0、警告なし、noteなし、いかなる診断も出ません。そこで同じ構成に対してsqlite3_openを求めてみます8

error: cannot find 'sqlite3_open' in scope

ベンダー用ディレクトリを検索パスから外せば、同一のファイルがコンパイルできます。ベンダー提供のモジュールマップはSDKのSQLite3を完全に覆い隠したのに、ツールチェーンは何も言いませんでした。つまり現時点では、ベンダーによる再宣言のケースは派手に失敗するのではなく、インポートしたつもりのモジュールからAPIが消えるという形で失敗します。AppleのノートはXcode 27のスキャンがそこで「エラーを報告する場合があります」と述べており、それが実現すれば、静かな覆い隠しはビルド失敗へと変わります。

私のビルド環境はXcode 26.6(ビルド17F113)なので、ここまでの診断はすべて1つ前のツールチェーンから出たものです78。Xcode 27のエラーテキストは報告できませんし、捏造もしていません。診断の仕組みも、grepすべき文字列も、Appleが引退させると述べている寛容さも、すべて今日すでに存在しています。

モジュール名の重複を監査する

宣言されたモジュール名の列挙は1行のgrepで済みそうに見えますが、モジュールマップ言語の2つの構文が誤った答えを生みます。

extern module Foo "Foo.modulemap"は前方参照であって定義ではありません。AppleのSDKは1つのモジュールマップの中でこれを79回使っています7。素朴なスキャンは、この参照と本物の定義をFooの2つの宣言として数えてしまいます。2つ目に、module Darwin.C { ... }はドット付きのmodule-idで、別の場所で宣言されたモジュールを拡張するものです。SDKのモジュールマップ13件がmodule Darwin.somethingを開いており、先頭要素をトップレベル宣言として読むと、この13件が本物のDarwin宣言と一緒くたにされ、14ファイルの衝突という誤報になります7。この2種類の偽陽性は、どちらも私の最初の草案に現れました。

これらを生き延びたコマンドは、コメント、波括弧の深さ(ネストしたexplicit moduleのサブモジュールを除外するため)、そして空白を含むパスに対応しています。

find -H "${1:-.}" \( -name '*.modulemap' -o -name 'module.map' \) \
  -not -path '*/build/*' -not -path '*/.build/*' \
  -not -path '*/DerivedData*/*' -print0 |
while IFS= read -r -d '' map; do
  awk -v f="$map" '
    { line = $0; sub(/\/\/.*/, "", line)
      if (depth == 0 && line !~ /extern[[:space:]]+module/ &&
          match(line, /(^|[[:space:]])module[[:space:]]+[A-Za-z_][A-Za-z0-9_.]*/)) {
        n = substr(line, RSTART, RLENGTH); sub(/.*module[[:space:]]+/, "", n)
        if (n !~ /\./) print n "\t" f
      }
      for (i = 1; i <= length(line); i++) {
        c = substr(line, i, 1)
        if (c == "{") depth++; else if (c == "}") depth--
      }
    }' "$map"
done | sort -u > /tmp/modnames.txt

cut -f1 /tmp/modnames.txt | uniq -d | while read -r n; do
  echo "duplicate: $n"
  awk -F'\t' -v n="$n" '$1==n {print "  " $2}' /tmp/modnames.txt
done

利用できる最強の陰性対照はApple自身のSDKです。ツールチェーンが動作している以上、これはルールを満たしているはずだからです。iPhoneOS 26.5のSDKに向けて実行すると、usr/include配下で1,099件、フレームワークのモジュールマップ全体で205件のトップレベル宣言が見つかり、いずれも重複はゼロでした7。衝突するよう作ったフィクスチャに向ければ、重複名と両方のファイルを名指しします8

除外指定は軽くありません。-not -path '*/build/*'.build/を除外しません。パターンにはディレクトリ名がそのまま必要だからです。しかもSwiftPMは生成したモジュールマップを.buildへ大量に書き込みます。.buildを残したまま実行したことが、7プロジェクトで唯一の「重複」を生みました。6ファイルのGrappleCoreと3ファイルのGrappleRenderで、すべてSwiftPMの出力、2つのSwiftターゲットが異なるビルドルートにまたがったものです9。この9件はバイト単位でも一致しておらず、その理由が示唆に富みます。それぞれが同じモジュール名で、自分のビルドルート内にある生成ヘッダへの絶対パスを包んでいるだけなので、1つの文字列だけが違い、意味のある差はどこにもありません。これらを衝突と呼ぶ監査は、本当の問題に到達する前に信用を使い果たします。

Xcodeは同じ偽陽性を、より紛れの無い形で製造します。1つのDerivedDataツリーの中で、各Swiftパッケージの生成モジュールマップを2度、GeneratedModuleMaps-iphonesimulator/とターゲット自身の中間生成物へ書き込みます。しかもヘッダのパスはどちらも相対です。あるプロジェクトのツリーでは15の名前がそれぞれ2回現れ、15組すべてがバイト単位で同一でした9。監査の対象はソースに限定し、ビルド成果物は外してください。

7プロジェクトに何があったか

Xcode 26.6上で、7つのXcodeプロジェクトに両方の監査をかけました。正直な結果は、きれいなゼロです9

プロジェクト Swiftファイル Objective-C / C++ / C 依存関係 -ld_classic ソース側モジュールマップ
Reps 77 0 ローカルSPM 2件 0 0
Return 57 0 なし 0 0
Banana List 55 0 なし 0 0
Ace Citizenship 26 0 外部依存なし 0 0
Water 34 0(.metal 2件) なし 0 0
ResumeGeni 71 0 リモートSPM 3件、pin 9件 0 0
Yawara 143 0 ローカルSPM 2件 0 0
合計 463 0 SPMのみ 0 0

OTHER_LDFLAGSは7プロジェクトすべてで未設定、.xcconfigファイルはどこにも存在せず、CocoaPodsもCarthageも、ベンダー提供の.framework.xcframeworkもありません9。モジュール名の監査では391件のモジュールマップを調べました。プロジェクトディレクトリ内が204件、XcodeのGUIビルドが着地する共有DerivedData内が187件で、そのすべてがビルド成果物です9。手書きのモジュールマップを持つリポジトリは1つもありません。

2つのゼロには同じ原因があり、持ち帰る価値があるのはそこです。影響を受けるのは複数言語が混在したプロジェクトであり、これらはそうではないということ。463件のSwiftファイルに対して、Objective-Cはゼロ、C++もゼロ、Cソースもゼロ。Swift以外でコンパイルされるコードは、WaterのMetalシェーダ2件だけです9。そもそも危険域に無いコードベースからの陰性結果は、危険そのものについては弱い証拠ですが、誰が監査すべきかについては強い証拠になります。

ゼロよりも重要な事実が2つあります。解決済みパッケージの中で唯一の手書きモジュールマップはswift-cryptoのもので、CCryptoBoringSSLCCryptoBoringSSLShimsCXKCPCXKCPShimsという4つのCシムを提供しており、いずれも名前は重複しません9。そして、この一群が宣言する名前は、SDKのClangモジュール名前空間のどこにも現れません。iPhoneOS 26.5のSDKでコマンドが見つけたトップレベル名1,318件すべてと照合済みです9。Supabase経由で入ってくる汎用的な名前ですら外れています。SDKが宣言するClangモジュールにはFoundationUIKitSQLite3はあっても、CryptoStorageAuthは存在しません。

足元で動くC++のデプロイメント下限

隣接する変更が1つ、-ld_classicを抱えているのと同じC++プロジェクトを直撃します。Appleは下限を引き上げ、macOSだけを名指ししました。「C++標準ライブラリがサポートするmacOSの最小デプロイメントターゲットは11.0に引き上げられました」5

同じ項目は脱出口を用意し、その次の一文で撤去の時期まで示しています。libc++は、狭義弱順序ではない比較子に対するstd::mapstd::setlower_boundupper_boundの結果を変更しました。_LIBCPP_ENABLE_LEGACY_TREE_LOWER_UPPER_BOUNDを定義すれば「これらの操作は従来の実装に戻ります」。続けてこうあります。「この脱出口は今後のリリース(おそらく次のリリース)で削除されます」5。関連する変更として、multimap::findmultiset::findが必ずしも最初の等価要素を返さなくなりました。Appleはこの挙動について「標準では保証されていなかった」がlibc++は常に提供していたと注記しており、こちらにはオプトアウトがありません5。このマクロは修正ではなく、移行のためのチケットとして扱ってください。

FAQ

なぜ自分のプロジェクトに-ld_classicが入っているのですか

ほぼ間違いなく、AppleのXcode 15リリースノートがそう処方したからです。そこにある2件のKnown Issueが、OTHER_LDFLAGSへの-Wl,-ld_classic追加を推奨していました。1件は弱定義シンボルを使うバイナリがiOS 14およびmacOS 12以前で実行時にクラッシュする問題で、Appleは「主にC++プロジェクトに影響する」と注記しています。もう1件はLTOオブジェクトファイルが弱シンボルのインポートを非弱としてリンクする問題です3。AppleはXcode 16でこのオプションを非推奨とし、Xcode 27でその背後のリンカを削除しました14。もしフラグが残っているなら、代替を探す前に、元の不具合が今も再現するかどうかを確かめてください。

プロジェクト内でClangモジュール名の重複を見つけるには

すべてのモジュールマップからトップレベルのモジュール宣言を列挙し、2つのファイルに現れる名前を探し、結果からビルドディレクトリを外します。この作業をgrep以上のものにしている要因は3つです。extern module Foo "path"は定義ではなく参照であること、module Foo.BarFooを宣言するのではなく別の場所で宣言されたモジュールを拡張すること、そしてネストしたexplicit moduleのサブモジュールはトップレベル名と衝突しないことです6.buildbuildDerivedDataは明示的に除外してください。-not -path '*/build/*'.buildを取りこぼしますし、SwiftPMもXcodeも生成モジュールマップを日常的に重複させるからです9

Xcode 27ではエラーはどう見えるのですか

私には言えませんし、Xcode 26でビルドしている人には誰にも言えません。私のマシンはXcode 26.6(ビルド17F113)で動いているので、Xcode 27の出力は一切報告しません78。同じ名前を宣言する2つのモジュールマップに対してXcode 26.6が出すのは、error: redefinition of module 'Widget'note: previously defined hereで、単純な型チェックでは毎回そうなります8。Xcode 27についてのAppleの表現はスキャンが「エラーを報告する場合があります」なので、誰かが推測した文字列ではなくredefinition of moduleをログから探してください。

モジュール名の一意性違反はデプロイメントターゲットに依存しますか

依存しません。Appleは要件を単一のSwift依存関係スキャンアクションに対して定めており、この項目ではOSバージョンもSDKもデプロイメントターゲットも名指ししていません2。リンカの変更も同じ読み方になり、ツールチェーンからの削除として書かれています1。どちらもXcode 27での最初のビルドで着地します。同じサイクルにあるSDK起因の要件ではなく、@Stateマクロと同じ側の変更です。

押さえておきたい点

iOS開発者向け: - -ld_classicをgrepするのではなく、xcodebuild -showBuildSettings -configuration Release -sdk iphoneosOTHER_LDFLAGSを問い合わせてください。解決済み設定に無ければ未設定という意味になりますが、テキスト検索に無くても何の意味もありません9。 - ビルドログで探すのはredefinition of moduleです。Xcode 26.6がすでに出している診断であり、捏造したXcode 27のエラーテキストではありません8

ベンダー提供のCまたはC++依存を抱えるチーム向け: - ベンダー提供のmodule.modulemapファイルを、まずSDKの名前空間と突き合わせて監査してください。Appleが名指ししているのがこのケースであり、しかも現在は静かに失敗します。私のベンダー版SQLite3シムは終了コード0でコンパイルが通り、sqlite3_openを消し去りました8。 - 監査対象はソースに絞り、.buildbuildDerivedDataを除外してください。391件のモジュールマップに現れた見かけ上の重複は、すべて単一のSwiftターゲット向けに生成されたビルド成果物でした9

リリース管理者向け: - どちらの変更もツールチェーン起因として扱い、SDK移行ではなくXcode 27での最初のビルドに合わせて計画してください。デプロイメントターゲットへの言及も、実行時の要素もありません12。 - Appleの留保はチケットに書き残しておきましょう。スキャンは「エラーを報告する場合があります」であり、1件の衝突を20回走らせて3種類の結果が出た以上、1度ビルドが通ったことは何の証明にもなりません28


27系のサイクルは、毎回違う場所で失敗し続けています。起動画面のキーは申請を止め、シーンライフサイクルの義務化は起動を止め、@Stateマクロはソースの段階でビルドを止めます。リンカの削除とモジュール名ルールが止めるのは、そのさらに一段下、誰も意図して設定しないツールチェーンの部分です。シリーズ全体のハブはApple エコシステムシリーズにあります。

参考文献


  1. Apple, Xcode 27 Release Notes, Linkingセクション、Deprecations in Xcode 27 Beta(radar 165165518)。削除の出典で、全文はこうです。「The ld64 linker has been removed and the -ld_classic option is no longer supported.」HTMLのページはJavaScript経由で内容を描画するため、2026年7月26日にAppleのドキュメントJSONに対して検証しました。同日時点のページタイトルは「Xcode 27 Beta 4 Release Notes」です。 

  2. Apple, Xcode 27 Release Notes, Swift Compilerセクション、New Features in Xcode 27 Beta(radar 136303612)。依存関係スキャナの項目の出典で、本文中に全文を逐語で引用しています。2つの留保(「the scan may report an error」および「Previously, the scanner may have tolerated duplicating names」)と、名指しされた2つのケースを含みます。2026年7月26日にAppleのドキュメントJSONに対して検証。DeprecationsやKnown Issuesではなく新機能として掲載されている点も記録しておきます。 

  3. Apple, Xcode 15 Release Notes, Linkingセクション。New Features(radar 108915312)が「A new linker has been written to significantly speed up static linking. It’s the default for all macOS, iOS, tvOS and visionOS binaries and anyone using the ‘Mergeable Libraries’ feature. The classic linker can still be explicitly requested using -ld64, and will be removed in a future release.」の出典です。Known Issuesは、フラグを推奨する2つの回避策の出典になります。radar 114813650(FB13097713)は「Binaries using symbols with a weak definition crash at runtime on iOS 14/macOS 12 or older. This impacts primarily C++ projects due to their extensive use of weak symbols.」で、回避策はデプロイメントターゲットの引き上げ、または「add -Wl,-ld_classic to the OTHER_LDFLAGS build setting」。radar 115521975(FB13171424)は「Weak symbol imports are linked as non-weak imports, when used from LTO object files.」で、回避策は「Add -Wl,-weak_reference_mismatches,weak or -Wl,-ld_classic options to the OTHER_LDFLAGS build setting.」です。2026年7月26日にAppleのドキュメントJSONに対して検証。 

  4. Apple, Xcode 16 Release Notes, Linkingセクション、Deprecations(radar 128502299)。「-ld_classic linker option is deprecated and will be removed in a future release.」2026年7月26日にAppleのドキュメントJSONに対して検証。 

  5. Apple, Xcode 27 Release Notes, C++ Standard Libraryセクション、Deprecations in Xcode 27 Beta。Appleはブロック全体に対してradarを1つ(178191050)だけ、各項目の横ではなく最後の項目の末尾に添えています。「The minimum supported deployment target on macOS for the C++ standard library has been increased to 11.0.」、multi{map,set}::findの変更(「code relying on the first element being returned from find will be broken, and lower_bound or equal_range should be used instead」)、そして脱出口とその期限の出典です。「Since this may be tricky to work around in some cases, an escape hatch is provided in this release: defining _LIBCPP_ENABLE_LEGACY_TREE_LOWER_UPPER_BOUND will revert to the historical implementation of these operations. That escape hatch will be removed in an upcoming release (likely in the next release).」2026年7月26日にAppleのドキュメントJSONに対して検証。 

  6. Clang team, Clang Modules documentation, Module Map Language。「Each module shall have a single definition.」、module-idのルールとextern module宣言、「The explicit qualifier can only be applied to a submodule, i.e., a module that is nested within another module.」、およびモジュールマップがファイル名module.modulemapで発見され、互換性のためにmodule.mapも検索されることの出典です。Apple開発者向け文書としてではなく、モジュールマップ言語に関するツールチェーン自身のリファレンスとして引用しています。Appleのclangはこの実装から派生しています。 

  7. 著者による検証。macOS 26.5.2(ビルド25F84)、Xcode 26.6(ビルド17F113)、Apple clang 21.0.0、2026年7月26日。コマンド出力は逐語で再現しています。xcrun clang hello.c -o hello -Wl,-ld_classicは「ld: warning: -ld_classic is deprecated and will be removed in a future release」を出力して0で終了し、-Wl,-ld64に置き換えても-ld_classicを名指しする同一の警告が出ます。xcrun ld -vPROJECT:ld-1267と本文に引用したアーキテクチャ一覧を報告します。ld-classic/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld-classicに存在し、manページも併置されています。SDKのアーキテクチャはSDKSettings.plistから取得しました。iPhoneOS 26.5はarm64earm64、WatchOS 26.5はarm64arm64earm64_32を宣言します。SDKのモジュールマップ集計(usr/include配下でトップレベル宣言1,099件、System/Library/Frameworks全体で205件、いずれも重複ゼロ)は、上掲のコマンドをiPhoneOS 26.5のSDKに対して実行した結果です。79件のextern module宣言はusr/include/module.modulemapにあり、同じディレクトリの13件のモジュールマップがドット付きのmodule Darwin.*を開いています(bankDarwin_CDarwin_MachDarwin_Mach_machineDarwin_machineDarwin_POSIXDarwin_sysdevicemach_debugnetnetinetnetinet6uuid)。先頭要素で読む方式では、これらがDarwin.modulemapにある本物のDarwin宣言とまとめられ、14ファイルの単一衝突として現れます。Xcode 27での挙動は未検証です。使用したマシンにXcode 27がインストールされていないためです。 

  8. 著者による再現。同一のマシンとツールチェーン、2026年7月26日。module Widgetを宣言するmodule.modulemapをそれぞれ含む2つのディレクトリを、両方とも検索パスに載せてswiftcでコンパイルしました。-typecheckは20回中20回、error: redefinition of module 'Widget'note: previously defined hereを出力して1で終了し、-Iパスを片方外すと同じファイルが0で終了してコンパイルされました。同じ入力に対する-scan-dependenciesは20回の実行でシグナル11(SIGSEGV)による終了が9回、シグナル6(SIGABRT)が5回、ステータス0での終了が6回となり、クラッシュした実行のスタックトレースはswift::ModuleDependencyScanner::performParallelClangModuleLookupを通過していました。別途、SQLite3(iPhoneOS 26.5のSDKにあるモジュール)を宣言するベンダー提供のモジュールマップを検索パスに置くと、診断なしで0で型チェックを通過しましたが、同じ構成でSDKのsqlite3_openを呼ぶファイルは「error: cannot find ‘sqlite3_open’ in scope」で失敗し、ベンダー用ディレクトリを検索パスから外すと問題なくコンパイルされました。フィクスチャには、公開したコマンドを検証するために空白を含むパスも含めています。このコマンドはファイル間で名前を比較するので、1つのモジュールマップ内で同じ名前が2度宣言されるケースは設計上その対象外です。この記事のどこにもXcode 27の出力は報告していません。 

  9. 著者による7つのXcodeプロジェクト(Reps、Return、Banana List、Ace Citizenship、Water、ResumeGeni、Yawara)の監査。macOS 26.5.2、Xcode 26.6(ビルド17F113)、2026年7月26日。-ld_classicld64はいずれの作業ツリーにも1件も現れず、OTHER_LDFLAGSは全プロジェクトで未設定、.xcconfigファイルもPodfileもCarthageも、ベンダー提供の.framework.xcframeworkも一群のどこにもありません。この検索が対象としたのは現在の作業ツリーのみで、gitの履歴やアーカイブされたビルドログは含まないため、結果は「一度も使われていない」ではなく「現時点で存在しない」です。Repsについて引用したSUPPORTED_PLATFORMSの行はxcodebuild -showBuildSettings -configuration Release -sdk iphoneosによるものです。モジュールマップの集計は、調査対象391件のうち204件が7つのプロジェクトディレクトリ配下、187件が共有の~/Library/Developer/Xcode/DerivedDataにあるこれら7プロジェクト自身のツリー内(共有ディレクトリ全体にはほかのプロジェクトのものがはるかに多く含まれます)で、そのすべてがビルド成果物であり、7つのリポジトリのいずれにも手書きまたはベンダー提供のモジュールマップはゼロです。見かけ上の重複はコンテンツハッシュで確認しており、2つの生成元は挙動が異なります。監査対象のResumeGeniツリー(プロジェクト内のbuild/DerivedData)にあるXcode由来の15組は、GeneratedModuleMaps-iphonesimulator/配下とターゲットの中間生成物配下に1度ずつ書き込まれ、15組中15組がバイト単位で同一です。Xcodeがヘッダを相対パスで出力するためです。この件数はプロジェクト単位ではなくツリー単位です。同じアプリの共有~/Library/Developer/Xcode/DerivedData配下のツリーは16件、そのIndex.noindex版は22件を持ちます。一般化できるのは仕組みであって数値ではありません。SwiftPMのコピーはそうではありません。Yawaraの.buildディレクトリ配下にある6件のGrappleCoreと3件のGrappleRenderは、それぞれ6種類と3種類の異なるハッシュを持ち、サイズは171〜185バイトの幅があります。各ファイルが自分のビルドルート内の生成-Swift.hへの絶対パスを埋め込んでおり、それ以外は同一だからです。一群が宣言するモジュール名は、公開したコマンドをiPhoneOS 26.5のSDK全体に向けたときに見つかる1,318件の異なるトップレベルClangモジュール名のいずれにも現れません(うち1,099件がusr/include配下、205件がSystem/Library/Frameworks配下)。一群の宣言名との積集合は空です。同じスキャンはSDK全体で重複ゼロを報告しており、これがルールの要求する陰性対照になります。CryptoKitがこの一覧に無いのは、Clangモジュールマップを持たないSwift専用フレームワークとして提供されているためです。したがってCryptoの衝突が無い根拠は、CryptoKitがその名前を占めているからではなく、SDKがその名前のClangモジュールを宣言していないことにあります。swift-crypto 4.4.0は、解決済み依存グラフの中で唯一の手書きモジュールマップを提供します(CCryptoBoringSSLCCryptoBoringSSLShimsCXKCPCXKCPShims、各1宣言)。SymbolKitのホストツール版とターゲット版は、7つのアプリではなく共有ローカルパッケージ941Kitに含まれます。ソース件数はPythonの仮想環境を除外しています。これは効いた補正でした。素朴な集計はRepsにCファイルとヘッダファイルを計上していましたが、それらはすべて.venvsite-packagesの中にあり、どのXcodeターゲットからもコンパイルされないものでした。Waterにはローカルのビルドツリーが無いため、モジュールマップ件数のゼロは、検証済みでクリーンなビルドグラフではなく未ビルドのプロジェクトを反映しています。偽の「クリーン」を生む3つの罠は、それぞれ直接確認しました。timeoutは素のmacOSには無く127で終了します。zshはクォートしない--include=*.pbxprojを展開して「no matches found」で中断します。xcrun --sdk iphoneos --show-sdk-pathはシンボリックリンクを返し、これに対して-H無しのfindはモジュールマップ0件と報告する一方、find -Hは266件を報告します。 

  10. Apple, Xcode 26 Release Notes。2026年7月26日にld_classicld64、およびクラシックリンカに言及する項目を検索しましたが、いずれも見当たりません。したがって、Xcode 16での非推奨告知とXcode 27での削除の間に、これを言い直した記述は存在しません。 

  11. Apple, Xcode 27 Release Notes, Overview: 「Xcode 27 beta 4 includes Swift 6.4 and SDKs for iOS 27, iPadOS 27, tvOS 27, watchOS 27, macOS 27, and visionOS 27.」同じノートのIntel Deprecation(radar 162138432)には「Xcode 27 will only install and run on Apple silicon Macs.」と記録されています。2026年7月26日に確認。 

関連記事

@Stateマクロ — Xcode 27でコンパイルが通らなくなるコード

Xcode 27では、SwiftUIの`@State`がSwiftマクロとして再実装されます。破壊的変更のトリガーはデプロイメントターゲットではなくツールチェーンであり、2つのパターンがコンパイルできなくなります。

4 分で読める

Xcode 27がIntelを切り離す——止まるもの、それでも出荷できるもの

Xcode 27はApple siliconでしか動作しませんが、Universalアプリの配布先はmacOS 12までさかのぼれます。ただしデプロイメントターゲットが27.0に達すると、`ARCHS_STANDARD`から`x86_64`…

6 分で読める