Neovim for old Linux kernel
Lately many of the client's old arm64 machines running on Ubuntu 20 have been on life support. Ubuntu 20 was running on older kernel (5.15'ish) which has older GLIBC libaries. This meant something dasterdly blasphemous. One could not install pre-compiled binaries built on newer kernels (Ex: 6.1 and above). This also meant that some apt repositories absolutely gave up on maintanance for certain applications. Like neovim in this case, which was on a very old and almost unusable version.
I was excited about Bob, but their pre-built bob distribution itself could not be run on these machines. Well, so first, I compiled bob itself. So I did. But then, it turned out even their neovim remote repos now have neovim binaries built with newer kernel. Anyways, so bob did not checkout.
Migrating to newer Ubuntu was not an option as of now, because of certain legacy dependencies used to run very important services.
Build your own Neovim
Thats it! This seemed like the only option and it actually helped. Surely, I was not going to build directly on the host machine. These days, running or building anything naked can be dangerous.
Docker, the true workhorse
Since the original issue was coined around the kernel, why not use that as the strength? Since Docker relies on the host's kernel, this was the perfect match.
Now there were 2 options:
Create a .deb package
Create naked binaries and their libraries
Option 1. was great for straight forward distribution, but the client wanted more control by explictly allowing to run the binary fom the $PATH.
The Dockerfile, that would contain all necessary build dependencies, was simple enough. You will notice, I also installed Git since we would clone the neovim repo and then do the build.
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y \
git \
ninja-build \
gettext \
libtool \
libtool-bin \
autoconf \
automake \
cmake \
g++ \
pkg-config \
unzip \
ccache \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /neovim
Please note that, Docker installation was NOT a Rootless mode and hence I used a separate and isolated instance for the build purpose as the above Dockerfile is running a root user.
So, since the build was going to happen inside the Docker container, how is one supposed to get the artifacts out on the host? Well, it turned out this was as simple as using volume mounts.
#! /bin/bash
docker build -t neovim-builder:20.04 .
mkdir -p neovim_install
docker run -it --rm \
-v $(pwd)/neovim_install:/neovim_install \
neovim-builder:20.04 /bin/bash -c " \
git clone https://github.com/neovim/neovim.git . && \
git checkout stable && \
make CMAKE_BUILD_TYPE=Release && \
make DESTDIR=/neovim_install install \
"
So this build.sh script above would do all thats needed.
Build the dependency builder image
Create a local mount point for the artifacts to be available
Actual neovim build
Tip: Use buildx to use Docker's caching while doing a Docker build. For buildx you would certainly a latest Docker installation. You could also use DOCKER_BUILDKIT=1 environment when running docker build command
Update the $PATH
If you looked into the mounted path, this was it!
└── usr
└── local
├── bin
├── lib
└── share
Copy over the artifacts to respective machines and update the $PATH
Now in resp. rc files, $PATH would look something like it
export PATH=/home/ubuntu/docker/nvim/neovim_install/usr/local/bin:........
Ofcourse, use your own path where you copied over the artifacts
Run nvim --version to see your own neovim binary
Conclusion
Its never too late to build your own stuff. Infact, make this a habit for the D-day.



