Building Liquidsoap
Forewords
Installing liquidsoap can be a difficult task. The software relies on an up-to date OCaml compiler, as well as a bunch of OCaml modules and, for most of them, corresponding C library dependencies.
Our recommended way of installing liquidsoap is via opam. opam can take care
of installing the correct OCaml compiler, optional and required
dependencies as well as system-specific package dependencies.
The opam method is described in details in the documentation. We recommend that any
interested user head over to this link to install the software via
opam.
The remainder of this document describes how to compile liquidsoap locally for developers.
Overview
Liquidsoap is compiled using dune, which is the
most popular OCaml build system at the moment. dune is
tightly integrated with opam so, even if you are installing
from source using dune, opam remains an
important tool.
Generally speaking, compiling from source may require the latest version of the liquidsoap code as well as its dependencies. Some of its dependencies are optional and can be ignored at first and some are not.
Keep in mind that, although opam is generally aware of
required minimal version for dependencies, dune is not. If
a dependency is outdated, dune compilation will simply
fail, at which point your may have to figure out if you need to update a
dependency.
Each branch of liquidsoap is compiled using github actions. When trying to build a specific branch, if the CI passes with it then, most likely, you are missing a dependency, or it is not the latest version.
opam pinning
opam pinning is a mechanism to update opam
with the latest version of a package, even before it is published to the
official opam repository. This is the easiest way to update a dependency
to its latest version.
You can pin directly from a local git repository checkout:
git clone https://github.com/savonet/ocaml-metadata.git
cd ocaml-metadata
opam pin -ny .
You can also pin directly using a git url:
opam pin -ny git+https://github.com/savonet/ocaml-cry
See opam pin --help for more details about the available
options.
Dependencies
The best way to figure out what dependencies are required or optional
and their versions is to use the latest opam package. Since
liquidsoap development is using dune and
opam, the dependencies are kept in sync via the local
liquidsoap opam package(s) and this serves as the de-facto list of
dependencies and their versions.
First, you should pin the latest liquidsoap code:
opam pin -ny git+https://github.com/savonet/liquidsoap
Then, ask opam to list all the dependencies for
liquidsoap:
opam info liquidsoap
opam info liquidsoap-lang
This should give you a (long!) list of all dependencies. Then, you
can query opam to see what each dependency does. This is
particularly useful for optional dependencies on
liquidsoap-core which provide opt-in features. For instance
opam info soundtouch will let you know that this package
provides functions for changing pitch and timestretching audio data.
Lastly, there are two types of dependencies:
- Dependencies maintained by us
- Dependencies not maintained by us
For dependencies not maintained by us, most of the time, we rely on the latest published version. Very rarely should you have to fetch/pin the latest version of these dependencies.
For dependencies maintained by us, we may break their API during our
development cycle, and you maybe have to fetch/pin the latest version
when compiling the latest liquidsoap code. You may also
have to check out a specific branch when compiling
liquidsoap from a specific development branch when the
changes in the liquidsoap code are paired with changes in one of our
dependencies. Typically, this happens a lof with the ffmpeg
binding.
Optional packages
Liquidsoap’s support for audio/video codecs, I/O backends, and other
features is provided by optional OCaml packages. These live under
src/modules/synced/ in the repository and are also
published independently on the opam repository
(e.g. ffmpeg, alsa, jack,
pulseaudio, srt, lame,
flac, opus, vorbis,
samplerate, soundtouch, etc.).
When building with dune from the top-level repository,
all packages whose C library dependencies are detected on the system are
compiled automatically — no manual pinning is required. If a C library
is missing, the corresponding package is simply skipped (unless
LIQUIDSOAP_INSTALL_NO_OPTIONAL_FAIL is set to
false, in which case the build will report it as an
error).
You can install the optional packages independently via opam as well:
opam install ffmpeg opus vorbis flac samplerate
Run opam info liquidsoap to see the full list of
optional dependencies and what each one provides.
Environment variables
When compiling Liquidsoap from source, certain environment variables can be set to control the build process and customize the build configuration. Here’s a brief overview of the relevant environment variables and their purposes:
IS_SNAPSHOT: Set this variable to indicate whether you are building a snapshot version of Liquidsoap. It affects the version suffix and whether the Git commit is displayed.LIQ_GIT_SHA: Override Git commit hash (SHA) if the build system cannot automatically extract it from the repository.LIQUIDSOAP_BUILD_VERSION: Override the displayed version of Liquidsoap.LIQUIDSOAP_BUILD_TARGET: Controls the runtime lookup paths for Liquidsoap components.- Set to
default: Uses paths detected in the OPAM switch directory. - Set to
standalone: Uses paths relative to the binary location, ideal for self-contained deployments (zip/tarball distributions). - Set to
posix: Configures paths to standard system directories, for use by OS package maintainers. The following environment variables can be used to override individual paths when using theposixtarget (defaults shown):LIQUIDSOAP_RUN_DIR(default:/var/run/liquidsoap): Runtime/PID file directory.LIQUIDSOAP_LOG_DIR(default:/var/log/liquidsoap): Log file directory.LIQUIDSOAP_LIBS_DIR(default:/usr/share/liquidsoap/libs): Liquidsoap standard library directory.LIQUIDSOAP_BIN_DIR(default:/usr/share/liquidsoap/bin): Liquidsoap binary scripts directory.LIQUIDSOAP_CAMOMILE_DIR(default:/usr/share/liquidsoap/camomile): Camomile charset data directory.LIQUIDSOAP_CACHE_DIR(default:/var/cache/liquidsoap): System cache directory.
- Set to
LIQUIDSOAP_INSTALL_NO_OPTIONAL_FAIL: Set totrueto allowdune build @installto succeed even when optional C libraries are not available on the system. Useful when building in environments where not all optional dependencies are present.LIQUIDSOAP_LDFLAGS: Extra flags passed to the C linker when linking the liquidsoap binary. Useful to force-link specific libraries when diagnosing build failures or building in non-standard environments.
Compiling
First, install the dependencies:
opam install --deps-only ./opam/liquidsoap.opam ./opam/liquidsoap-lang.opam
Then build:
dune build
If an error occurs, you may need to see if you need to update a dependency. Hopefully, with a short iteration of this cycle, you will end up with a successful build!
Once you have a successful build, you can also use the top-level
liquidsoap script. This script builds the latest code and
executes it right away. It works as if you were calling the
liquidsoap binary after installing it:
./liquidsoap -h output.ao
From here, you can start changing code, testing script etc. Happy hacking!
Debugging with AddressSanitizer
AddressSanitizer (ASAN) is a compiler instrumentation tool that detects memory errors such as use-after-free, buffer overflows, and use-after-scope bugs at runtime. It is useful when tracking down crashes or subtle memory corruption in the C bindings or OCaml runtime.
Pre-built packages
An ASAN-instrumented build of Liquidsoap is produced automatically on
every commit to main and v*-latest branches
and is available in two forms:
- Debian package: attached to the rolling release
assets on the releases page,
with
asanin the filename. - Docker image: published to the GitHub Container
Registry as
ghcr.io/savonet/liquidsoap:asan-<sha>, where<sha>is the full Git commit SHA.
To run your script under the ASAN Docker image:
docker run --rm -v /path/to/your/script.liq:/script.liq \
ghcr.io/savonet/liquidsoap:asan-<sha> /script.liq
ASAN output goes to stderr and includes a stack trace pointing at the offending allocation and access sites.
ASAN options
You can tune ASAN’s behaviour at runtime via the
ASAN_OPTIONS environment variable. Consult the AddressSanitizer
flags reference for the full list of available options. A good
starting point is to enable leak detection:
export ASAN_OPTIONS="detect_leaks=1"
Building locally with ASAN
To build Liquidsoap yourself with ASAN, create an opam switch using
the ocaml-option-address-sanitizer variant:
opam switch create asan-dev ocaml-variants.5.4.0+options ocaml-option-address-sanitizer
eval $(opam env)
opam install --deps-only ./opam/liquidsoap.opam ./opam/liquidsoap-lang.opam
dune build