Try installing from source first

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 ""
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 postgresandpsql`.)

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 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.



Enjoyed the read. Thank you :)


Thank you!

Leave a Comment

All comments are reviewed before being made public.