Fix rustup failed with "error: linker `cc` not found" on Alpine Linux 3.17 (Rust 1.66)
Tags: rust, rustup, alpine, docker
Published: 2023-01-09 02:09:45

## Summary

[Alpine Linux](http://alpinelinux.org/) offers [Rustup](https://rustup.rs/) [package](https://pkgs.alpinelinux.org/packages) as well as [Rust](https://www.rust-lang.org/).

I built the development environment of Rust on Alpine Linux with [Docker](https://www.docker.com/).

Well, on the way, I met the error below when testing a [cargo](https://doc.rust-lang.org/cargo/) project:

```console
$ cargo run
```

The output was:

```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
```

This post shows how to fix it.

### Environment

- 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

## Solution

\* Below, `doas` can be replaced with `sudo`.

### Start Docker container

Dockerfile example:

```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 command line examples:

```console
$ # build in the directory where Dockerfile exists
$ docker build .
$ # get the image id
$ docker image ls

$ # start container
$ docker start $IMAGE_ID
$ # get the container id
$ docker container ls

$ # enter vm
$ docker exec -it $CONTAINER_ID sh
```

### Install Rust via Rustup

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

The output was:

```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
```

Then run:

```console
$ rustup-init
```

You will be asked as below. Proceed with the default option:

```
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
>
```

The output was:

```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"
```

Lastly, run to update `$PATH`:

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

Now Rust is in your hands :)

### Create a cargo project (and building it will fail)

Create an example project:

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

The output was:

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

Enter:

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

Then run:

```console
$ cargo run
```

It will fail with:

```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
```

### Fix it

You can fix it by installing [`build-base`](https://pkgs.alpinelinux.org/package/edge/main/x86_64/build-base) package:

```console
# apk add build-base
# #apk add gcc       # alternative (not recomended)
```

The output was:

```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
```

#### Note: Why `build-base` instead of `gcc`

The minimal installation required is just [`gcc`](https://pkgs.alpinelinux.org/package/edge/main/x86_64/gcc). It's a part of `build-base`.
`gcc` may be able to fix the problem in this post.

To install only `gcc` is, however, [not recommended](https://wiki.alpinelinux.org/wiki/GCC), because either `musl-dev` or `libc-dev` will be perhaps necessary in addition soon later.

For example, when building an [Actix Web](https://actix.rs/) server, which is a Rust web framework using actors communication, `build-base` must be required.

## Conclusion

Let's run `cargo run` (or `cargo build`) again:

```
# cargo run
```

Will surely get a little happier :)

```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!
```