rustup が "error: linker `cc` not found" で失敗 - Alpine Linux 3.17 (Rust 1.66)
Tags: rust, rustup, alpine, docker
Published: 2023-01-09 02:40:09

## はじめに

[Alpine Linux](http://alpinelinux.org/) では [Rustup](https://rustup.rs/) が [パッケージ](https://pkgs.alpinelinux.org/packages) として提供されています。[Rust](https://www.rust-lang.org/) もあります。

[Docker](https://www.docker.com/) で Alpine Linux 上に Rust の開発環境を構築しました。

そしてその過程においてですが、以下のようなエラーが発生しました。[cargo](https://doc.rust-lang.org/cargo/) プロジェクトを試験的に動かした時のことです:

```console
$ cargo run
```

出力は以下の通りでした:

```consokle
   Compiling alpine-rust-example v0.1.0 (/(...)/alpine-rust-example)
error: linker `cc` not found
  |
  = note: No such file or directory (os error 2)

error: could not compile `alpine-rust-example` due to previous error
```

こちらの修正方法について記述します。

### 環境

- Alpine Linux [3.17](https://alpinelinux.org/posts/Alpine-3.17.0-released.html)
- Rust [1.66](https://releases.rs/docs/1.66.0/)
- Rustup 1.25

## 解決の流れ

\* 以下、`doas` の代わりに `sudo` を使っても大丈夫です。

### Docker コンテナの起動

Dockerfile 例:

```dockerfile
FROM alpine:3.17

# ports published
EXPOSE 80
EXPOSE 443
# packages base
RUN apk update --no-cache
RUN apk upgrade --no-cache
RUN apk add --no-cache openrc
# rust
RUN apk add --no-cache rustup

# [ init system - activate OpenRC ]
ENTRYPOINT ["/sbin/init"]
```

Docker コマンド例:

```console
$ # Dockerfile のあるディレクトリでビルド
$ docker build .
$ # image id 取得
$ docker image ls

$ # コンテナ起動
$ docker start $IMAGE_ID
$ # container id 取得
$ docker container ls

$ # vm 操作
$ docker exec -it $CONTAINER_ID sh
```

### Rust を Rustup でインストール

```console
$ doas apk add rustup
```

出力は以下の通りでした:

```console
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/community/x86_64/APKINDEX.tar.gz
(1/6) Installing ca-certificates (20220614-r3)
(2/6) Installing brotli-libs (1.0.9-r9)
(3/6) Installing nghttp2-libs (1.51.0-r0)
(4/6) Installing libcurl (7.87.0-r0)
(5/6) Installing libgcc (12.2.1_git20220924-r4)
(6/6) Installing rustup (1.25.1-r0)
Executing busybox-1.35.0-r29.trigger
Executing ca-certificates-20220614-r3.trigger
OK: 18 MiB in 24 packages
```

続いてこちらを実行します:

```console
$ rustup-init
```

以下のようにたずねられるでしょう。デフォルトの選択肢のままで進んで OK です:

```
Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /(...)/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /(...)/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  /(...)/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile file located at:

  /(...)/.profile

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-unknown-linux-musl
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>
```

出力は以下の通りでした:

```console
info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-musl
info: syncing channel updates for 'stable-x86_64-unknown-linux-musl'
info: latest update on 2022-12-15, rust version 1.66.0 (69f9c33d7 2022-12-12)
info: downloading component 'cargo'
(...)
info: downloading component 'clippy'
(...)
info: downloading component 'rust-docs'
(...)
info: downloading component 'rust-std'
(...)
info: downloading component 'rustc'
(...)
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
(...)
info: installing component 'rust-std'
(...)
info: installing component 'rustc'
(...)
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-unknown-linux-musl'

  stable-x86_64-unknown-linux-musl installed - rustc 1.66.0 (69f9c33d7 2022-12-12)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source "$HOME/.cargo/env"
```

最後に以下を実行して `$PATH` を更新します:

```console
$ source "$HOME/.cargo/env"
```

これで Rust の環境ができました :)

### cargo プロジェクトを作成 (そしてその後にビルドで失敗)

サンプルプロジェクトをつくりましょう:

```console
$ cargo new alpine-rust-example
```

出力は以下の通りでした:

```console
     Created binary (application) `alpine-rust-example` package
```

中に入ります:

```console
$ cd alpine-rust-example
```

そこで実行します:

```console
$ cargo run
```

以下の通り失敗するはずです:

```console
   Compiling alpine-rust-example v0.1.0 (/(...)/alpine-rust-example)
error: linker `cc` not found
  |
  = note: No such file or directory (os error 2)

error: could not compile `alpine-rust-example` due to previous error
```

### 修正

[`build-base`](https://pkgs.alpinelinux.org/package/edge/main/x86_64/build-base) パッケージをインストールすればエラーは解消します:

```console
# apk add build-base
# #apk add gcc       # 別の方法 (非推奨)
```

出力は以下の通りでした:

```console
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/community/x86_64/APKINDEX.tar.gz
(1/19) Installing libstdc++ (12.2.1_git20220924-r4)
(2/19) Installing binutils (2.39-r2)
(3/19) Installing libmagic (5.43-r0)
(4/19) Installing file (5.43-r0)
(5/19) Installing libgomp (12.2.1_git20220924-r4)
(6/19) Installing libatomic (12.2.1_git20220924-r4)
(7/19) Installing gmp (6.2.1-r2)
(8/19) Installing isl25 (0.25-r0)
(9/19) Installing mpfr4 (4.1.0-r0)
(10/19) Installing mpc1 (1.2.1-r1)
(11/19) Installing gcc (12.2.1_git20220924-r4)
(12/19) Installing libstdc++-dev (12.2.1_git20220924-r4)
(13/19) Installing musl-dev (1.2.3-r4)
(14/19) Installing libc-dev (0.7.2-r3)
(15/19) Installing g++ (12.2.1_git20220924-r4)
(16/19) Installing make (4.3-r1)
(17/19) Installing fortify-headers (1.1-r1)
(18/19) Installing patch (2.7.6-r8)
(19/19) Installing build-base (0.5-r3)
Executing busybox-1.35.0-r29.trigger
OK: 254 MiB in 43 packages
```

#### 備考: なぜ `gcc` では無く `build-base` を使うのか

最小限のインストールにとどめるのであれば [`gcc`](https://pkgs.alpinelinux.org/package/edge/main/x86_64/gcc) で十分なはずです。これは `build-base` の一要素です。
`gcc` だけでも本記事の問題ならば解決できるでしょう。

しかしながら `gcc` だけをインストールするというのは、[推奨されていません](https://wiki.alpinelinux.org/wiki/GCC)。というのも `musl-dev` と `libc-dev` のいずれかが、きっとすぐに追加で必要になるからです。

一例ですが、[Actix Web](https://actix.rs/) というアクターモデルを採用している Rust の Web フレームワークがあります。こちらのサーバーを立てようとする時などは `build-base` が必要になります。

## おわりに

それでは `cargo run` (あるいは `cargo build`) を再度実行してみましょう:

```
# cargo run
```

先ほどよりも良いことが訪れるのでは無いでしょうか :)

```console
   Compiling alpine-rust-example v0.1.0 (/(...)/alpine-rust-example)
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/alpine-rust-example`
Hello, world!
```