A good reason to use package managers when installing software is that it normally just works. And while that's a very compelling reason, I still think developers should first try installing software from source when possible. The two main advantages of installing from source are: learning and control. Control over how the package is built, what's included, where it goes, how it's managed and the flexibility to apply patches and versions possibly not available in your package manager.
Now, I'll be quick to admit that you probably shouldn't spend a huge amount of time trying to install something from source. For many packages the best case scenario is a complicated process requiring specific build tools and dependencies with their own complications. The worst case scenario is poor or lacking documentation and no idea how to even get started.
But, you can try.
Take PostgreSQL. You go to the "Source code" section of the main download page, you'll find a link to the PostgreSQL File Browser. I'm going to install the Beta 2 release of version 16.
While /usr/local
is the preferred destination for self-compiled packages, it's protected by System Integrity Protection in MacOS, which makes things tedious. Thus, I use /opt
which I can own, via chown $(whoami) /opt
.
cd /opt
wget "https://ftp.postgresql.org/pub/source/v16beta2/postgresql-16beta2.tar.bz2"
tar -xvf postgresql-16beta2.tar.bz2
cd postgresql-16beta2/
In a lot of cases, installing from source is a three step process. First you run ./configure
, but it isn't always obvious what flags, if any, to pass. PostgreSQL's ./configure --help
lists the available flags. ./configure
generates the build script based on the local environment. Part of that process is checking the local environment to make sure all the dependencies are met. For example, on my computer, if I run: ./configure --with-gssapi
, I'll get an error "configure: error: could not find function 'gss_store_cred_into' required for GSSAPI". Now if I wanted gssapi
, I'd probably have to Google how to install gssapi
(or if I was sure I had it installed, figure out why it wasn't able to find it). Thankfully, it isn't something I want. In fact, for PostgreSQL, the only flag we'll specify is the --prefix
. While there's no standard to ./configure
from one package to another, --prefix
is commonly used to indicate where the final binary should be installed.
./configure -prefix=/opt/postgres
If that works, it'll have created a Makefile which we can use for the next step: compiling the binary(ies).
make -j4
The -j4
tells Make that it can process up to 4 jobs in parallel. This step might take a minute or two, and it could fail. But, at least for PostgreSQL, it'll probably succeed.
Congratulations, you've successfully compiled PostgreSQL from source! You could, in theory, call it a day. But ./configure
and make
don't "install" the package. This is something I really appreciate because, at this point, nothing outside of /opt/postgresql-16beta2/
has been affected. (For PostgreSQL, you can find the binaries in the src/bin
subfolders.) To actually "install" PostgreSQL, we run make install
. This should be fast as all it does is copy the artifacts created by make
into their final destination. This is largely controlled by the --prefix
option we gave to ./configure
, but make install
could do other things, such as updated man
pages or modifying the $PATH.
PostgreSQL itself requires 1 additional setup step: creating the data directory.
/opt/postgres/bin/initdb -D /opt/postgres/data/
Finally, we can start the PostgreSQL server:
/opt/postgres/bin/postgres -D /opt/postgres/data
(you might want to add /opt/postgres/bin/
to your $PATH, or possibly alias some of those binaries, namely
postgresand
psql`.)
Personally, I much prefer having PostgreSQL explicitly started and stopped (ctrl-c) this way. With a dedicated terminal window with easily accessible logs.
PostgreSQL is a particularly easy and reliable package to install from source. While the ./configure --prefix PATH
, make
and make install
trio are common, some packages useful completely different tools. Others might be simpler, possibly just having a single make
step which generates a single binary that you can copy wherever you want.
But even PostgreSQL has special consideration. If you want to install extensions, say the amazing pg_stat_statements
, you'll have to take additional steps:
cd /opt/postgresql-16beta2/contrib/pg_stat_statements
make
make install
Some extensions, like PostGIS aren't included and thus must be downloaded and installed. PostGIS has dependencies which themselves can be hard to install. And this is the point where I might apt-get install
or brew install
those missing dependencies, while still compiling and installing PostGIS myself.
The goal though is to try, to learn from the process, to maintain control over your environment, and flexibility to tweak as needed.