Fixing docs.rs Build Errors
Tags: rust, docker
Published: 2021-12-02 02:51:30

## Introduction
A few weeks ago, I started working on a wrapper for the KF5I18n KDE framework in Rust. I had published the crate but found out soon that the documentation was not being generated automatically. After investigating a little, I discovered that the container used for the documentation generation was missing the KF5I18n library. After a bit of work, I finally got it working, and the docs are now present for my crate [ki18n-rs](https://crates.io/crates/ki18n-rs). I decided to write this since it will be helpful when I choose to write a wrapper for another KDE framework in Rust.

## Initial Setup
First, a few things need to present in the system:
1. Git
2. Docker
3. crates-build-env source
```shell
git clone https://github.com/rust-lang/crates-build-env
```
4. docs.rs source
```
git clone https://github.com/rust-lang/docs.rs
```
I initially tried to use Podman instead of Docker, but I could not execute the `docker-compose` part with `podman-compose`. So I had to give up and Docker instead.

## Build Image
First, navigate to the location of the `crates-build-env/linux` folder we just cloned. If the dependency is already known, one could add it to packages.txt and open a merge request. However, since my primary system is Arch Linux, I first decided to test things out in my local machine.
Instead of adding the dependency to the packages.txt, I first build the default image.
```shell
docker build --tag build-env .
```
Then I added `RUN apt-get update && apt-get install -y libkf5i18n-dev` after the package.txt install. The final Dockerfile had the following contents:
```
FROM ubuntu:focal

# Install the packages contained in `packages.txt`
COPY packages.txt /opt/crates-build-env/packages.txt
RUN apt-get update && \
    cat /opt/crates-build-env/packages.txt | DEBIAN_FRONTEND=noninteractive xargs apt-get install -y && \
    rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y libkf5i18n-dev

CMD ["bash"]
```
After this, I rebuilt the image again. Since docker caches stuff, it does not try to reinstall the packages from packages.txt as long as it has not been modified. Hence it is better to modify Dockerfile to test out things rather than adding packages to packages.txt.

## Testing Crate in Image
Now, create a script file with the following content:
```shell
cd /path/to/docs.rs
docker-compose build
# NOTE: this must be an absolute path, not a relative path
# On platforms with coreutils, you can instead use `$(realpath ../relative/path)`
YOUR_CRATE=/path/to/your/crate
# avoid docker-compose creating the volume if it doesn't exist
if [ -e "$YOUR_CRATE" ]; then
  docker-compose run -e DOCSRS_DOCKER_IMAGE=build-env \
                     -e RUST_BACKTRACE=1 \
                     -v "$YOUR_CRATE":/opt/rustwide/workdir \
    web build crate --local /opt/rustwide/workdir
else
  echo "$YOUR_CRATE does not exist";
fi
```
Run the script, and it should try to test building docs with the newly created container image. 
Additionally, while the comments say that the relative path does not work, I used the relative path directly, and it worked just fine, so I'm not sure if the comment is valid or not.
Also, the environment variable is supposed to be `DOCSRS_DOCKER_IMAGE` and not `DOCS_RS_LOCAL_DOCKER_IMAGE`. I have opened a pull request to fix this in the official docs, so maybe it will be merged by the time I publish this.
If everything goes well, there would be a message saying docs were generated successfully message in the end.

## Add packages to packages.txt file
After confirming the packages that fix the issue, add those packages to the packages.txt file. 
Additionally, run the lint script at `crates-build-env/ci/lint.sh` on the packages.txt to check if everything is in proper order.
Also, there is no need for the modification to the Dockerfile now that the packages have been added to packages.txt.

## Make a Pull Request
First, fork the repository to the personal account. Then open a pull request with the changes. Here are the steps I use:
```shell
git remote add personal https://github.com/<your_username_here>/crates-build-env
git checkout -b new_branch_name
git add -u
git commit -m 'add packages necessary for <your_package_here> to compile'
git push personal
```
I like to create a new branch for the changes since it is easier to keep track of multiple pull requests.
Github will automatically show a button to create a pull request from the newly created branch, so there is not much to say.

## Conclusion
I had difficulty completing the process since I was trying to use Podman instead of Docker. However, all in all, it was a pretty painless process. The official docs can be found [here](https://forge.rust-lang.org/docs-rs/add-dependencies.html), which are pretty good. Additionally, my crate can be found [here](https://github.com/Ayush1325/ki18n-rs).
Now that the documentation is working, I can get back to working on improving the crate again.