Compose Multiplatform で macOS 向けデスクトップアプリを開発していたとき、配布パッケージのビルドが失敗しました。
./gradlew :desktop-app:packageDistributionForCurrentOS を実行すると、jpackage が DMG 生成の途中でエラーを返して終了します。
原因はコードではなく、OS でした。macOS 26 Tahoeにおける hdiutil のバグです。
症状
hdiutil attach は終了コード 0 を返してもマウントされたボリュームが強制的に read-only になります。
$ mount | grep tabconv
/dev/disk34s1 on /private/tmp/tabconv_mount (hfs, local, nodev, nosuid, read-only, ...)
-readwrite フラグを明示しても挙動は変わりません。その結果、マウント後のファイルコピーが失敗します。
cp: /private/tmp/tabconv_mount/TabConv.app: Read-only file system
jpackage 経由では次のエラーとして表面化します。
java.io.IOException: Command [/usr/bin/hdiutil, attach, ...-tmp.dmg,
-quiet, -mountroot, .../images] exited with 1 code
java.nio.file.FileSystemException: .../images/TabConv/TabConv.app: Read-only file system
根本原因(調査中)
Apple は macOS 26.4 Beta 1 のリリースノートで、HFS+ 外部メディアが自動マウントに失敗する場合がある旨を「known issue」(識別子: 168672160)として公式に認め、diskutil mount コマンドによるワークアラウンドを案内しました。
バグの詳細な原因については Apple から公式な説明はありませんが、コミュニティの調査では fsck_hfs(HFS+ ボリュームの整合性チェックツール)の異常が有力視されています。実際に fsck_hfs を手動実行すると次のような dyld エラーが発生します。
dyld[...]: Library not loaded: @rpath/libclang_rt.ubsan_osx_dynamic.dylib
Referenced from: .../fsck_hfs
Reason: tried: '...' (no such file)
これは UndefinedBehaviorSanitizer(UBSan)用のデバッグライブラリへの依存を示しており、内部デバッグビルドが誤って同梱されたことが原因ではないかと指摘されています。macOS はマウント時の整合性チェックが正常に完了しないと、書き込みを許可せずに read-only でマウントします。
Apple は Beta 2 のリリースに際し、フィードバックへの返答でこのバグの修正を確認しています。
影響を受ける主なツール
| ツール | 使用箇所 |
|---|---|
jpackage (JDK 21) |
.dmg / .pkg 生成(Compose Desktop の packageDistributionForCurrentOS) |
electron-builder |
macOS 向け DMG 生成 |
create-dmg |
HFS+ ベースの DMG 作成 |
背景:ASIF と HFS+ の位置づけ
macOS 26 では Apple Sparse Image Format(ASIF)が新たに導入されました。 ASIF はスパース構造を持ち、ほぼネイティブ速度での読み書きを実現します。 Apple は VM のバッキングストアを RAW(UDIF read-write)から ASIF へ移行するよう推奨しており、HFS+ ベースのディスクイメージは事実上レガシーとして扱われる方向にあります。