Natively installing Lilypond on MacOS

UPDATED: These instructions now work with Lilypond 2.21.x.

I use Lilypond for all my music engraving. I am also an avid Apple user. The official compiled Lilypond package for the MacOS target is 32-bit; such binaries are not supported by MacOS since Catalina. There is an unofficial MacOS build, but installing it can be tricky, and it doesn't always keep up with the latest upstream version. So I set to work figuring out how to compile Lilypond natively, using Homebrew as my build environment. If you want to follow the instructions here, you should have already installed Homebrew and become familiar with what it does. You should also feel comfortable using Terminal.

These instructions install only the command-line Lilypond utilities. They do not install any GUI apps, nor do they register Lilypond.app in your “Applications” directory.

1. Text fonts

Lilypond uses the TeX Gyre font metafamily for its default text engraving. Change directories to a temp directory (such as /tmp) and execute the following:

curl -LO http://www.gust.org.pl/projects/e-foundry/tex-gyre/whole/tg2_501otf.zip
unzip tg2_501otf.zip
mv tg2_501otf/*.otf /Libraries/Fonts/

This will give you several new font families in your universal fonts directory.

2. Dependencies supplied by Homebrew

First, we’ll install MacTeX, a precompiled distribution of TeX.

brew cask install mactex

Next, we need to add a contributed tap. The sadhen/sadhen tap supplies Guile 1.8, which is Lilypond’s preferred version of Guile.

brew tap sadhen/sadhen

Formerly, we had to add another tap for kpathsea functionality, but mactex now bundles it properly. If you had installed kpathsea separately before, and if its binaries live in /usr/local/bin, you will need to uninstall it now.

Now we can install all the dependencies that Homebrew can provide us:

brew install bison gcc guile@1.8 ghostscript fontconfig freetype \
  pango t1utils fontforge texinfo gettext poppler gnu-sed

Finally, it may be necessary to get Homebrew to symlink some of these libraries/resources to common areas:

brew link fontforge
brew link gettext --force

3. Flex

Homebrew supplies flex-2.6.4, but due to upstream bugs Lilypond will choke on any version higher than 2.5.37. So we get to install the older version of flex by hand. I couldn't get texi2dvi to successfully process the documentation (it made the build process choke and die) so I deke out that part of the build. I also skip building the test directory. You’ll want to be in a temp directory to execute the following:

curl -LO https://github.com/westes/flex/archive/flex-2.5.37.tar.gz
tar xzf flex-2.5.37.tar.gz
cd flex-flex-2.5.37
gsed -i -e '/doc \\/d' -e '/tests/d' -e 's/tools \\/tools/' Makefile.am
gsed -i -e '/doc\/Makefile/d' -e '/tests\/Makefile/d' -e '/tests\/.*\/Makefile/d' configure.in
./autogen.sh
./configure
make && make install

4. Extractpdfmark (optional)

This utility is optional, but it will result in much smaller PDF output from Lilypond when building the documentation, so I installed it (in case I want to build the docs later). I couldn’t find a Homebrew package for this, so I installed from source:

curl -L -o extractpdfmark-1.1.0.tar.gz \
  https://github.com/trueroad/extractpdfmark/archive/v1.1.0.tar.gz
cd extractpdfmark-1.1.0
./autogen.sh
./configure --disable-dependency-tracking
make && make install

5. Lilypond

This was the most challenging part. Lilypond won’t compile with clang, Apple’s built-in compiler. Apple pretends to have gcc installed, but in fact the gcc in /usr/bin is just a renamed clang. We have to specify all the GCC-related compilers and preprocessors when we run configure for Lilypond, or it will fall back to using the built-in Apple ones and then fail late in the build process. Also, for some reason Lilypond configures to escalate certain build warnings to fatal errors, so we have to remove that bit of configuration after we run the configure script.

PATH="/usr/local/opt/texinfo/bin:/usr/local/opt/bison/bin:$PATH" \
  CC=/usr/local/bin/gcc-10 \
  CXX=/usr/local/bin/g++-10 \
  CPP=/usr/local/bin/cpp-10 \
  CPPFLAGS="-I/usr/local/include" \
  LDFLAGS="-L/usr/local/lib" \
  ./configure \
  --disable-texi2html \
  --disable-debugging \
  --disable-checking \
  --disable-optimising \
  --enable-gs-api \
  --with-texgyre-dir=/Library/Fonts \
  --without-urwotf-dir \
  --disable-documentation \
  --disable-pipe \
  --disable-profiling
gsed -i -e 's/-Werror=suggest-override//g' config.make
PATH="/usr/local/opt/texinfo/bin:/usr/local/opt/bison/bin:$PATH" make all
make install

And that’s it! You should be able to invoke lilypond from the terminal now.