How can I build a Haskell program with optional dependencies?

Viewed 101

I am writing some simulation software for my own research and made a visualization tool as part of the project. This works perfectly fine on my workstation, and i can use it to for example monitor a simulation as it is running, or visualize the log data later. I have come to a point were I need to run simulations on a cluster now though, and OpenGL is neither available, nor needed for the actual simulations. However, since the project depends on OpenGL, it will not build.

Now obviously I could create a separate branch without the OpenGL parts, which will probably be my short term solution, but seems like a bit of a pain to maintain.

I am not sure what the best long term solution would be. Ideally I'd like to have a setup that optionally builds the visualization part if OpenGL is available, and skips it if not. Does stack (or cabal) support this type of thing?

Another option would be to make the visualization part a different project, but this would make monitoring the simulation as it is running significantly more difficult.

What is the best way to solve this?

1 Answers

There are a couple ways you can do this.

The first and simplest would be to split up your code into two different packages. One would be the code without the OpenGL dependency, and the other would be the visualization tool using OpenGL. If there's no reason you can't do it this way, this is by far the best option.

If you cannot do this, then you can use Cabal flags, as someone mentioned in the comment. An example of a cabal file with flags is:

name:        mylibname
description: some description

...

flag opengl
  description: build opengl support
  default:     False

library
  ...
  build-depends: base, containers, ...
  if flag(opengl)
    build-depends: OpenGL
    cpp-options: -DWITH_OPENGL
  ...

Now in your source files, you can do this:

{-# LANGUAGE CPP #-}

...

#ifdef WITH_OPENGL
    someOpenGLCode
#endif

By default, your builds won't include the OpenGL parts. You can use either cabal or stack to ask to build the package with OpenGL. In cabal, you can either do so on the command line with -f or --flags option, or in the cabal.project file with the flags: field. Someone else already linked to what looks like some equivalent stack documentation (though I don't know stack well enough to comment on its correctness)

Related