Music Suite is a language for describing music, based on Haskell.
There are two ways of setting up the development environment:
- Using Nix (recommended on Linux)
- Manually (recommended on Windows and OS X)
Install the Nix package manager. We recommend using 2.3.1 or later.
Enter environment using:
nix-shell --pure
All build commands should be run in the Nix shell. You can exit the Nix shell using Ctrl-D
.
Install the following.
- Lilypond, 2.22.1 or later
- Timidity++, 2.15.0 or later
- ghcup
Make sure that lilypond
timidity
and ghcup
are available your shell environment (e.g. by adding them to PATH
).
Use ghcup
to install GHC:
ghcup install 8.10.4
$ cabal update
$ cabal build
To run all tests except doctests (see below):
$ cabal test --test-show-details=streaming --test-options=--color=always
To run individual tests:
$ cabal run TEST_NAME -- TEST_ARGS...
e.g.
$ cabal run music-suite-test-xml-parser
Some tests have expected output, stored in test/regression
.
If the output of these tests have changed, the diff should be manually inspected to assure that the new output is in fact correct. This may be because:
- The output is in fact expected to change.
- The output has changed in a way that is invisible to the end user, such as a a change to an
*.ly
output file that does not affect the appearance of the printed music.
To identify the latter it may be necessar to run lilypond
or timidity
on both the old and new versions of the output file. To do this manually after a failure.
- (optional) Re-run regression tests to see that it fails:
cabal test music-suite-test-regression --test-options=--color=always
- For each failing file, run
lilypond
(for*.ly
files) ortimidity
(for*.mid
files). - Regenerate the expected files:
cabal test music-suite-test-regression --test-options=--color=always --test-options=--accept
- For each changed file, run
lilypond
ortimidity
as before. - Inspect the old/new version side by side.
- If all are correct, commit the changes to
test/regression
.
Note: after running
--accept
, you can usegit diff --name-only test/regression
to get a list of changed files, assuming the repo was clean before.
Music Suite makes use of doctests.
You can pass any file or directory. For example to test src/Music/Pitch
:
$ cabal build music-suite && cabal exec doctester --package music-suite -- src/Music/Pitch
To test a single file:
$ cabal build music-suite && cabal exec doctester --package music-suite -- src/Music/Score/Meta.hs
To run all doctests use (Nix only):
$ doctests
$ cabal build music-suite && cabal exec --package music-suite ghci
or
$ cabal repl
See these instructions.
The output appears in docs/build
. You can point a HTTP server to this directory.
$ cabal haddock
$ cabal exec runhaskell -- examples/chopin.hs -f ly -o t.ly
To replicate all steps run by the CI (Nix only), run:
$ ci
We use Nix to pin the version of GHC and Cabal freeze files to pin the version of all Haskell dependencies. This describes how to upgrade GHC.
Because GHC pins a version of the Haskell base library, GHC and the Cabal dependencies need to be upgraded together. This is the recommended workflow:
- Update the commit/URL and hash in
default.nix
- Use
$ nix-prefetch-url --unpack <url>
to obtain the hash (and verify) - Enter new Nix shell (may take a while)
- Update the
ghc-version
field incabal.project
to whatever is printed byghc --version
- Comment out
reject-unconstrained-dependencies
incabal.project
- Update
index-state
in Cabal config to a recent time - Run
cabal update
- Run
rm cabal.project.freeze
- Run
cabal freeze
- Run
cabal test
to check that compiling/testing works (and fix errors) - Restore
reject-unconstrained-dependencies
- Commit your changes.
- Comment out
reject-unconstrained-dependencies
incabal.project
- Add the dependency to
music-suite.cabal
- Update
index-state
in Cabal config to a recent time - Run
cabal freeze
- Run
cabal test
to check that compiling/testing works (and fix errors) - Restore
reject-unconstrained-dependencies
- Commit your changes.
-
The high-level DSL:
Music.Time
: high-level DSL for time and rhythmMusic.Pitch
: high-level DSL for pitch (common, scientific)Music.Dynamics
: high-level DSL for dynamicsMusic.Parts
: high-level DSL for instruments and partsMusic.Prelude
: prelude/standard library for the Music Suite DSL
-
The notation DSL:
Music.Notation.Standard
: DSL for representing Common/Western music notation
-
Import & Export:
Data.Music.Lilypond
: AST, parsing and pretty-printing for the Lilypond languageData.Music.MusicXml
: AST, parsing and pretty-printing for MusicXML
-
Utility
Control.*
: miscellaneous algorithms and utilitiesData.*
: miscellaneous data structures