Building Neovim

Date: 2023/03/05 (initial publish), 2023/10/10 (last update)

Source: en/note-00039.md

Previous Post Top Next Post

TOC

CMake revisited

Since Neovim uses CMake as its build system, I made quick review of its usage after reading following interesting references.

CMake basics

The good old way to configure a source package with CMake is as follows:

$ cd path/to/source
$ mkdir build
$ cd build
$ cmake [<options>] ..

Then, build and install the configured source package with the generated build system, e.g., “Unix Makefile” is as follows (executed in build/ directory):

$ make
$ sudo make install

Here, this build and install process can also be done with the build system agnostic way as:

$ cmake --build . --verbose
$ sudo cmake --install . --verbose

CMake and DEB-package

This above basic method installs binary executables directory to the system. The removal of installed files is a bit tricky. It will be nice if we can create a DEB-package and install it with dpkg -i <packagename>.deb. Then its clean removal is intuitive process.

$ cmake --build . --verbose
$ cpack -G DEB --verbose
$ sudo dpkg -i <packagename>-linux64.deb

Please note this is not how official Debian packages are build. This CMake functionality merely creates a DEB-package compliant to its bunary package format without adding debian/* files.

If cpack is invoked without -G DEB, this also builds TGZ-package.

Prebuild Neovim DEB-package

Debian Neovim DEB-package

Debian ships Neovim based on upstream Neovim v0.7.2 version (released on 2022-06-27) for the upcoming bookworm release.

Please note this uses external libraries via shared library mechanism.

$ ldd /usr/bin/nvim
        linux-vdso.so.1 (0x00007ffec159e000)
        liblua5.1-luv.so.0 => /lib/x86_64-linux-gnu/liblua5.1-luv.so.0 (0x00007f4788c16000)
        libuv.so.1 => /lib/x86_64-linux-gnu/libuv.so.1 (0x00007f4788be6000)
        libmsgpackc.so.2 => /lib/x86_64-linux-gnu/libmsgpackc.so.2 (0x00007f4788bdd000)
        libvterm.so.0 => /lib/x86_64-linux-gnu/libvterm.so.0 (0x00007f4788bca000)
        libtermkey.so.1 => /lib/x86_64-linux-gnu/libtermkey.so.1 (0x00007f4788bbd000)
        libunibilium.so.4 => /lib/x86_64-linux-gnu/libunibilium.so.4 (0x00007f4788ba6000)
        libtree-sitter.so.0 => /lib/x86_64-linux-gnu/libtree-sitter.so.0 (0x00007f4788b78000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4788521000)
        libluajit-5.1.so.2 => /lib/x86_64-linux-gnu/libluajit-5.1.so.2 (0x00007f4788aec000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4788340000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4788ae7000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4788ae0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4788c61000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4788ac0000)

This Neovim in Debian bookworm uses 0.1.4 version of libvterm which is the one found in Debian bookworm.

Why Debian Neovim package is stack in 0.7.2.

The Debian bookworm/testing uses the upstream Neovim v0.7.2 release (2022-06-27) which requires to use 0.1.4 version of libvterm. The 0.1.4 version of libvterm is available in bookworm/testing repository as of 2023-04-09.

The newer upstream Neovim v0.8.0 release (2022-10-01) requires to use 0.3 version of libvterm.

The latest upstream Neovim v0.9.0 release (2023-04-07) requires to use 0.3.1 version of libvterm.

The 0.3.1 version of libvterm isn’t available in bookworm/testing nor unstable/sid repository as of 2023-04-09.

This is the cause of Debian Neovim/testing to be stack in 0.7.2 as of 2023-04-11.

The 0.3.1 version of libvterm is available in experimental repository as of 2023-04-09.

So it is possible to build Neovim using experimental repo.

You should be able to build Debian package using the essentially the same code in debian/* after updating it to cope with new upstream source tree for post-build testing. Following packages are needed:

External library dependencies are linked dynamically for this case.

Upstream Neovim DEB-package

No more (There were DEB package up to 8.3 but no more on 2023-09-03)

Upstream provides DEB-packages for Linux (x64) == amd64 platform at:

External library dependencies are linked statically.

Local build of Neovim DEB-packages using CMake

Since upstream Neovim is fast moving platform, it is nice to have its latest version.

Upstream repository situation on 2023-04-11.

External dependencies as shared library

When building Neovim, you need to provide options to configure Neovim source to match header and library file locations on Debian. Initial cmake needs to be executed with following options.

$ GENERATOR="-G Ninja"
$ BUILD_TYPE=RelWithDebInfo
$ DEB_HOST_MULTIARCH=x86_64-linux-gnu
$ cd path/to/source
$ mkdir build
$ cd build
$ cmake \
  $GENERATOR \
  -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
  -DBUSTED_OUTPUT_TYPE=nvim \
  -DLIBLUV_LIBRARY:FILEPATH=/usr/lib/$DEB_HOST_MULTIARCH/lua/5.1/luv.so \
  -DLIBLUV_INCLUDE_DIR:PATH=/usr/include/lua5.1 \
  -DPREFER_LUA=OFF \
  -DCOMPILE_LUA=OFF \
  "$LOGLEVEL" ..
$ cpack -G DEB
$ sudo dpkg -i nvim-linux64.deb

This configure source to use -dev packages and build a binary executable linked to shared libraries like normal DEB-package build via debian/* for the official Debian repository.

External dependencies as statically linked library

Statically linking external libraries frees us from library version mismatch troubles.

Here is how to build such Neovim by oneself.

Let’s build Neovim as described in Building Neovim: Quick start for Developer.

$ git clone https://github.com/neovim/neovim
$ cd neovim && make CMake_BUILD_TYPE=RelWithDebInfo
$ cd build
$ cpack -G DEB --verbose
$ sudo dpkg -i nvim-linux64.deb

This cpack -G DEB is probably how upstream builds its DEB-packages.

Now (2023-04-09), this builds the latest Neovim master branch on git repo (0.10.0-dev version) with all external libraries statically linked.

$ bin/nvim --version
NVIM v0.10.0-dev-19+g339011f59
Build type: Debug
LuaJIT 2.1.0-beta3
Compilation: /usr/bin/cc -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wvla -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes -fno-common -Wimplicit-fallthrough -fdiagnostics-color=always -fstack-protector-strong -DNVIM_LOG_DEBUG -DUNIT_TESTING -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include/luajit-2.1 -I/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/build/src/nvim/auto -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/build/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/build/cmake.config -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/src -I/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include -I/home/osamu/github/neovim/neovim-cmake-deb/neovim/.deps/usr/include

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/local/share/nvim"

Run :checkhealth for more info

Let’s see what was built.

$ ldd bin/nvim
    linux-vdso.so.1 (0x00007fff131a7000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4860921000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f48610b0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4860740000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f48610ed000)

Caveat of DEB-package made by CMake

The DEB-package build by CMake doesn’t use some package features.

Before installing DEB-packages build by CMake (including ones built by upstream), you must remove both Debian neovim and neovim-runtime packages in advance to avoid package conflicts.

Since command normally provided by the update-alternatives are not available, view, vimdiff, ex, and editor commands needs some workaround such as the use of alias defined in ~/.bashrc:

# nvim: nvim with LazyVim -- as /usr/bin/nvim
export EDITOR=nvim
export VISUAL=nvim
# `vi` as neovim with LazyVim
alias vi='nvim'
# `v` as neovim without resource file
alias v='nvim  -u NORC'
# `v0` as neovim with minimum resouce file
alias v0='nvim -u ~/.nvim'
# sudoedit to use nvim w/o resource file
alias svi="SUDO_EDITOR='/usr/bin/nvim -u NORC' /usr/bin/sudoedit"
# vim alias
alias vimdiff='nvim -d'
alias view='nvim -R'
alias ex='nvim -e'
alias editor=nvim

This should force to use Neovim as the backend of vim-related command.

Automating nvim build

I made a simple script to build DEB-packages:

Then I included this builder to this web site script. Now, I can see my latest build results on this site:

Since I use bare CMAKE, there are no APT compatible data. So use wget and dpkg -i.

Previous Post Top Next Post