Managing manually compiled packages with stow

Posted by R4nd0m 6uy on Wed 18 July 2018

I often compile applications (mostly game) manually because I love using the very last features and seeing the progress of the development! I usually install everything in /usr/local/ to avoid polluting my base system as much as possible. Unfortunately it is difficult to make sur that all files are correcly removed when uninstalling the package manually and miserably fail keeping a sane system!

While surfing the net, I've found this beast and though "why the hell didn't I know this before?!". That's why I would like to present stow that is a small package management system that permits installing applications from a separated folder using symlinks.

Creating a separated sysroot

To have a better overview of the packages I compiled myself, I create an independent sysroot in /opt/. Then configure the system to make sure that libraries and binaries are correcly found. It also makes sure that nothing is installed somewhere else as I can use a standard user at installation, if I have to type "sudo make install" to solve permission issues, it shows that something is wrong.

First I create my sysroot folder and give the right permissions:

sudo mkdir -p /opt/my-sysroot/
sudo chown $(whoami).$(whoami) /opt/my-sysroot/

Then configure the ldloader to find the shared object of the manually installed libraries:

echo /opt/my-sysroot/lib | sudo tee /etc/ld.so.conf.d/my-sysroot.conf

After installing a new library, running ldconfig makes sure that they are correctly loaded at runtime.

Finally I export the PATH environement variable to find binaries using my local .bashrc configuration:

echo "export PATH=/opt/my-sysroot/bin:$PATH" >> ~/.bashrc

Now the separated sysroot is ready to host a new package!

Installing a package from sources

Doing this is dependent of the build system used but the idea is to use a different prefix at installation. I just give the separated sysroot we created by specifying a stow subfolder. I also append the verison of the package to its name, usually using git describe. Then it is easy to have an overview of all available packages and their versions by listing the content of this directory.

With autoconf

When using autoconf, the easiest is to pass the --prefix argument when invoking the ./configure script, for example when configuring package:

./configure --prefix=/opt/my-sysroot/stow/package-$(git describe --tags)
make
make install

Notice that here, sudo is not used when installing the package to make sure that all files will be installed in the sysroot we defined and not in other folders where root permissions are required.

With cmake

The process is very similar with cmake, just use the CMAKE_INSTALL_PREFIX variable on the command line:

cmake -DCMAKE_INSTALL_PREFIX=/opt/my-sysroot/stow/package-$(git  describe --tags)
make
make install

Other build system

Most of the Makefile based applications use the DESTDIR and PREFIX variables, but that is not always the case. Other build systems might use different mechanism or variables.

Morality, refer to the application specific documentation in order to change the installation directory!

Installing a compiled package with stow

Let's go back to our topic and install an application we have just compiled! When installing a package with stow, there are three important parameters to give:

  • The directory containing our packages (stow directory)

By default, stow use the the STOW_DIR environement variable, if unset, uses the current directory. It is also possible to specify it when invoking stow with -d/--dir.

  • The destination directory

When not specified, the destination directory is the parent of the stow directory. Also here it is possible to change it on the command line using the -t/--target argument.

  • The package to install or remove

Finally the package name is a folder existing in the stow direction, in our case package-version. The -S/--stow argument must be given in order to install a package or/and the -D/--delete to remove the package.

Let's stow the cpputest stable version 3.5 package that is avaible in my stow directory:

# Check available packages
ls /opt/my-sysroot/stow/ | grep cpputest
cpputest-v3.8
cpputest-v3.8-214-gf3563d53

# Install stable v3.8 with stow
stow --dir=/opt/my-sysroot/stow/ \
  --target=/opt/my-sysroot/ \
  --stow cpputest-v3.8

Let's see the effect of command in our sysroot

ls -l /opt/my-sysroot/
total 4
lrwxrwxrwx 1 random random   26 Feb 18 12:52 include -> stow/cpputest-v3.8/include/
lrwxrwxrwx 1 random random   22 Feb 18 12:52 lib -> stow/cpputest-v3.8/lib/
drwxr-xr-x 4 random random 4096 Feb 18 12:35 stow/

Now it is easy to switch from a cpputest version to another

stow --dir=/opt/my-sysroot/stow/ \
  --target=/opt/my-sysroot/ \
  --delete cpputest-v3.8 \
  --stow cpputest-v3.8-214-gf3563d53

We can notice that the symlinks have been changed consequently:

ls -l /opt/my-sysroot/
total 4total 4
lrwxrwxrwx 1 random random   40 Feb 18 12:54 include -> stow/cpputest-v3.8-214-gf3563d53/include/
lrwxrwxrwx 1 random random   36 Feb 18 12:54 lib -> stow/cpputest-v3.8-214-gf3563d53/lib/

Stow tree folding/unfolding

You can notice that include is a direct symbolic link to the include directory of cpputest package. That is not good if another package also has a directory called "include"!

Because stow does its best effort to create as less symbolic as possible, it is not necessary to create the include folder. Once another package must install this folder, stow will remove the include symlink, create a directory and create symlinks again within the newly created directory.

Cleaning up an old package

Let's say that a package is getting really old and you want to remove it completely from your system, it is just a matter of uninstalling it with stow and removing the folder in the stow directory.

Despite the package is probably not installed, I always perform the delete operation to make sure that there will be no dangling symbolic links left after erasing the package folder.

stow --dir=/opt/my-sysroot/stow/ \
  --target=/opt/my-sysroot/ \
  --delete cpputest-v3.8
rm -rf /opt/my-sysroot/stow/cpputest-v3.8

No sudo and my system is totally cleanup from the older version!

Where stow can make your life easier

Of course, staw is useful if you always want to work with the latest package or play with the latest game version on your every day machine. It makes also very convenient to switch back to an older version when official server of a given game only work with stable release but want to play locally with the latest for testing.

If you are working in a company and have applications and libraries that depend on each other to be built, you can use an alternate sysroot where application will be updated very frequently, when using a build machine to test each commit when working in a contunously integrated development cycle.

Conclusion

Stow changed the way I handle manually compiled packages, not only for my hobbies but also in my daily job! I hope this small introduction will also help you keeping a clean system while using manually compiled packages!

tags: linux, tutorial