Ubuntu22.04でAutoinstall of module nvidia/~ が失敗するときの対処法

## はじめに

Ubuntu 22.04環境で `sudo apt upgrade` を行い、カーネルが新しいバージョン (私の場合は `6.8.0-60-generic`) にアップデートされた際、NVIDIAドライバのDKMS (Dynamic Kernel Module Support) ビルドに失敗し、パッケージ設定が完了しない問題に遭遇しました。

具体的には、`linux-headers-XXX` や `linux-image-XXX` の設定中にエラーが発生し、最終的に `E: Sub-process /usr/bin/dpkg returned an error code (1)` と表示される状況でした。

この記事では、その原因特定から解決に至るまでの手順を記録として残します。同様の問題に直面した方の助けになれば幸いです。

## 環境

* OS: Ubuntu 22.04 LTS
* 問題発生時のカーネル: `6.8.0-60-generic`
* NVIDIA Driver: `565.57.01`

## エラー発生状況

`sudo apt upgrade` を実行すると、以下のようなエラーメッセージが表示されました。

```text
linux-image-6.8.0-60-generic (6.8.0-60.63~22.04.1) を設定しています ...
linux-headers-6.8.0-60-generic (6.8.0-60.63~22.04.1) を設定しています ...
/etc/kernel/header_postinst.d/dkms:
Sign command: /usr/bin/kmodsign
Signing key: /var/lib/shim-signed/mok/MOK.priv
Public certificate (MOK): /var/lib/shim-signed/mok/MOK.der

Autoinstall of module nvidia/565.57.01 for kernel 6.8.0-60-generic (x86_64)
Building module(s)........(bad exit status: 2)
Failed command:
unset ARCH; [ ! -h /usr/bin/cc ] && export CC=/usr/bin/gcc; env NV_VERBOSE=1 'ma
ke' -j16 NV_EXCLUDE_BUILD_MODULES='' KERNEL_UNAME=6.8.0-60-generic IGNORE_XEN_PR
ESENCE=1 IGNORE_CC_MISMATCH=1 SYSSRC=/lib/modules/6.8.0-60-generic/build LD=/usr
/bin/ld.bfd CONFIG_X86_KERNEL_IBT= modules
ERROR: Cannot create report: [Errno 17] File exists: '/var/crash/nvidia-kernel-s
ource-565-open.0.crash'

Error! Bad return status for module build on kernel: 6.8.0-60-generic (x86_64)
Consult /var/lib/dkms/nvidia/565.57.01/build/make.log for more information.
...
dpkg: パッケージ linux-headers-6.8.0-60-generic の処理中にエラーが発生しました (--configure):
 installed linux-headers-6.8.0-60-generic package post-installation script subprocess returned error exit status 1
...
処理中にエラーが発生しました:
 linux-headers-6.8.0-60-generic
 linux-headers-generic-hwe-22.04
 linux-generic-hwe-22.04
 linux-image-6.8.0-60-generic
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

## 原因調査
指示に従い、DKMSのビルドログを確認しました。

```Bash
cat /var/lib/dkms/nvidia/565.57.01/build/make.log
```
ログには以下の重要な情報が含まれていました。

コンパイラのバージョン不一致に関する警告:

```Plaintext
warning: the compiler differs from the one used to build the kernel
  The kernel was built by: x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0
  You are using:           cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
```

```Plaintext
cc: error: unrecognized command-line option ‘-ftrivial-auto-var-init=zero’
make[3]: *** [scripts/Makefile.build:243: /var/lib/dkms/nvidia/565.57.01/build/nvidia/nv.o] エラー 1
```

この -ftrivial-auto-var-init=zero オプションに関するエラーが複数のファイルで発生していました。

上記のログから、エラーの根本原因は以下の2点と特定しました。

GCCバージョンの不一致: カーネル (6.8.0-60-generic) はGCC 12.3.0でビルドされていましたが、NVIDIAドライバのDKMSモジュールをビルドしようとしていたのはシステムのデフォルトコンパイラであるGCC 11.4.0でした。
未サポートのコンパイラオプション: GCC 11.4.0は、NVIDIAドライバのビルドスクリプト（またはカーネルのビルドシステムから引き継がれた設定）が使用する -ftrivial-auto-var-init=zero というコンパイラオプションをサポートしていませんでした。このオプションはGCC 12以降でサポートされたもののようです。
結果として、コンパイルが途中で失敗し、NVIDIAカーネルモジュールがビルドできず、関連するパッケージの設定が完了しなかった、という流れです。

## 解決手順
以下の手順で問題を解決しました。

1. GCC 12 のインストール
    まず、カーネルのビルドに使用されたGCC 12.x と互換性のあるGCCをインストールします。

```Bash
sudo apt update
sudo apt install gcc-12 g++-12
```
.
2. デフォルトの GCC/G++ をバージョン 12 に設定
    update-alternatives コマンドを使用して、システムのデフォルトコンパイラ (cc および gcc) がGCC 12を指すように変更します。
    
```Bash
# GCC 12を高い優先度(例: 100)で登録
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12

# (オプション) 既存のGCC 11の優先度を下げるか、確認する
# sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 50 --slave /usr/bin/g++ g++ /usr/bin/g++-11

# デフォルトとしてGCC 12が選択されているか確認・設定
sudo update-alternatives --config gcc
```

プロンプトが表示されたら、gcc-12 に対応する番号を入力してEnterキーを押します。

設定後、バージョンを確認します。

    
```Bash
gcc --version
g++ --version
出力が gcc (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0 のようにバージョン12.xを示していればOKです。
```

.
3. 中途半端なパッケージ設定の修正とNVIDIAモジュールの再ビルド
    GCCのバージョンを修正した後、dpkg の設定問題を解決し、保留中のアップグレードを再試行します。これにより、DKMSが新しいGCC（バージョン12）を使用してNVIDIAモジュールを正しく再ビルドできるはずです。
    
```Bash
sudo dpkg --configure -a
sudo apt -f install
sudo apt upgrade
```
これでエラーが発生せず、パッケージのアップグレードと設定が正常に完了するはずです。