This should work on other Fedora-based distributions and for other packages, but I have not done extensive testing
Using up-to-date versions of software on RHEL is a pain. I understand the eneterprise benefits, but configuring a development environment can be confusing, with most people using a combination of symlinks, adding folders to PATH
, and enabling an scl_source
While this is still generally acceptable, there exists an alternative method (sorry).
The alternatives
essentially creates a symlink, but it actually is a symbolic link to the alternatives directory, which in turn is a symbolic link to the actual program.
This allows for better package management and confines all sysadmin changes to the /etc directory, all while making switching back easier. It feels to me a lot like virtualenv
in python
$ git --version
git version 1.8.3.1
$ cmake --version
cmake version 2.8.12.2
This gist is mainly because I always forget how to do it when setting up a new system for myself, but it also shows a simple method for dealing with alternative versions of software
A semi-updated version of cmake
is available through yum
, but named cmake3
. At the time of writing this, cmake3
is version 3.17 and the latest is 3.18. For my needs, 3.17 is sufficient so I will install cmake3
from yum
sudo yum -y install cmake3
But now I have to type cmake3
every time I want to use cmake
, and from practice I know muscle memory will hit enter before 3 every time without fail. And scripts don't need to care about this strange naming.
So now I will "install" both versions of cmake
to the alternatives
directory by providing the path for the new program, new program name, original location, and priority. Priority is a bit clunky, but the option with the highest priority is the default version. Also, I install to /usr/local/bin
. I'm sure there are other opinions, but putting it in the "locally installed" folder makes the most sense to me.
Along with the program itself, the associated programs are installed as slave
s [sic] so the versioning is preserved across the group. These are combined as a family
in the redhat implementation, which helps to group multiple master
s [sic] together and handle one being deleted.
old cmake
sudo alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake 10 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake \
--family cmake
cmake3
sudo alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
--family cmake
And that's it, we're suddenly 7+ years in the future.
$ cmake --version
cmake3 version 3.17.3
For this, we will install the latest version of git
from source (mainly following their instructions), and then do the same process as before.
first install dependencies
sudo yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
sudo yum install gcc perl-ExtUtils-MakeMaker
Then navigate to /usr/src
(or a temporary folder if you don't plan on keeping the files) and download the latest from the Linux kernel archives and extract. At the time of writing, this is 2.28.0, but check the link for newer/other versions. Note that they are sorted lexicographically instead of by release, so 2.28.0 come directly before 2.3.0
cd /usr/src
sudo wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.28.0.tar.gz
sudo tar xzfv git-2.28.0.tar.gz
And compile the source code, preparing to install to /usr/local/git
cd git-2.28.0/
sudo make prefix=/usr/local/git all
sudo make prefix=/usr/local/git install
If there are any build issues along the way, google the "X not found", or similar if the missing package is not obvious
Git is now installed to /usr/local/git/bin
, but this is not on the $PATH
so we will use alternatives
again.
Looking at the two install locations, the programs slightly differ. 1.8 has 5 git*
programs, while 2.28 has 7. I go ahead and add gitk
and git-cvsserver
to the new version entry.
old version
sudo alternatives --install /usr/local/bin/git git /usr/bin/git 10 \
--slave /usr/local/git-receive-pack git-receive-pack /usr/bin/git-receive-pack \
--slave /usr/local/git-shell git-shell /usr/bin/git-shell \
--slave /usr/local/git-upload-archive git-upload-archive /usr/bin/git-upload-archive \
--slave /usr/local/git-upload-pack git-upload-pack /usr/bin/git-upload-pack \
--family git
new version
sudo alternatives --install /usr/local/bin/git git /usr/local/git/bin/git 20 \
--slave /usr/local/git-cvsserver git-cvsserver /usr/local/git/bin/git-cvsserver \
--slave /usr/local/git-receive-pack git-receive-pack /usr/local/git/bin/git-receive-pack \
--slave /usr/local/git-shell git-shell /usr/local/git/bin/git-shell \
--slave /usr/local/git-upload-archive git-upload-archive /usr/local/git/bin/git-upload-archive \
--slave /usr/local/git-upload-pack git-upload-pack /usr/local/git/bin/git-upload-pack \
--slave /usr/local/gitk gitk /usr/local/git/bin/gitk \
--family git
And now git should point to the new version. Note: It might require you to reload the terminal. Not sure why--cmake never seems to need it
$ git --version
git version 2.28.0
If you ever want to change the default version from the highest priority, you can do it by interacting with alternatives
. alternatives --list
will show all the configured options
$ sudo alternatives --list
...
git auto /usr/local/git/bin/git
cmake auto /usr/bin/cmake3
The "auto" means it is using the highest priority alternative. This can be set to manual and changed with --config <name>
$ sudo alternatives --config git
There are 2 programs which provide 'git'.
Selection Command
-----------------------------------------------
1 git (/usr/bin/git)
*+ 2 git (/usr/local/git/bin/git)
Enter to keep the current selection[+], or type selection number:
And it can be changed back from manual with sudo alternatives --auto git
This should work for most, if not all, programs that need multiple versions, and every change is managed by alternatives so you know where to look when you inevitably forget.
I'm sure there are things I missed, so feel free to let me know if it doesn't work and I can look further into it.
https://www.redhat.com/sysadmin/alternatives-command
https://linux.die.net/man/8/alternatives