I am quite new at using homebrew and I am trying to figure out how it works to use some libraries (boost, gsl, openblas for example) in my own project.
I have understood that each formula is installed by Homebrew in /usr/local/Cellar/ and then symlinked in usr/local/bin, usr/local/lib, usr/local/include, so it seems, excepts for keg-only formulas so it does not mess with already installed libraries by the OS (cf. Understand homebrew and keg-only dependencies for example). But I found out that every formula is also linked to a /usr/local/opt directory.
So my question is why is there this /usr/local/opt directory (it is kind of redundant), and what path do I have to use for using formulas (usr/local/Cellar or usr/local/ or usr/local/opt basically) ?
It provides a path for a formula's contents that does not change across version upgrades.
Consider this scenario: Say you build libfoo.dylib
with Homebrew. It is version 2.0.0, and so it lives at /usr/local/Cellar/libfoo/2.0.0/lib/libfoo.dylib
. You want to link to it from another program you are building, so you pass -L/usr/local/Cellar/libfoo/2.0.0/lib -lfoo
to gcc
. Your program compiles. Later on, you upgrade to libfoo 2.0.1 and remove v2.0.0. Now /usr/local/Cellar/libfoo/2.0.0/lib/libfoo.dylib
no longer exists, and your program no longer runs, because it can't dynamically load libfoo.
That's okay. libfoo.dylib
is also available at /usr/local/lib/libfoo.dylib
. It's a symlink to the latest version of libfoo, so it should always be present. So you pass -L/usr/local/lib -lfoo
to your program and compile it. Later you upgrade to libfoo 2.0.1. No problem, because /usr/local/lib/libfoo.dylib
is still present and points to the v2.0.1 copy.
That's great, and Homebrew existed with just that system for a while. The problem is, some formula are "keg-only", so they are not symlinked from /usr/local
. (Generally they are keg-only because they shadow a version of a library that ships with OS X, and superseding OS X libraries can cause problems.) Say you want to link to a keg-only version of the library. It's not symlinked from /usr/local/lib
, so you have to give the full path to the version installed in /usr/local/Cellar
, which is brings you back to the first problem listed above.
/usr/local/opt
solves this problem. It provides a place for the current version of all formulae to be symlinked, regardless of whether they are keg-only or not. Now, when you want to compile your program, you can use -L/usr/local/opt/libfoo/lib -lfoo
, and your program will link to the latest version of libfoo, even if you upgrade it and even if it is keg-only.
Just to complement mipadi answer.
From an article aptly named '/usr/local/opt'
Storing files in consistent locations is an important part of keeping
a system clean and maintainable. On most Linux systems, the majority
of software is installed using a package manager. A package manager
tracks the files that are installed, so it can update and remove
software with minimal side-effects.
There are times, however, when software that is not available through
the package manager must be installed. To minimize the side-effects on
the filesystem, such software is installed within the /usr/local
directory. UNIX-style installation of software puts files in the bin,
lib, share, etc. subdirectories under the local root, but it is very
common to install software into package-specific directories and add
soft-links from the local root instead. Doing so allows for easy
removal of the software—simply remove the package-specific directory
as well as any links pointing into it.
Some software provides local installation instructions that promote
creating a package-specific directory directly in /usr/local. This
does not promote good organization, as it mixes UNIX hierarchy
directories with package-specific directories. Installation of
software into package-specific directories is already done elsewhere,
in the /opt directory, and it would therefore make sense to follow the
same conventions and put locally installed package-specific
directories in a /usr/local/opt directory.
Including a version number in the directory name is not required, but
it is good practice for locally-installed software because it allows
multiple versions to be installed and tested simultaneously. To run a
specific version of the software, run the executable under the package
directory directly. Any version can be made the default by controlling
which executable is linked to from /usr/local/bin. For example, a new
version of software can be installed and tested without removing the
old version. When the new version is ready, the link in /usr/local/bin
can be updated to point to it. The old version of the software can
then be removed when it is no longer needed.
Source: Copyright © 2014 Extellisys