Search code examples
haskelldocumentationhaddockreflex

Haddock breaks down on #if #else #endif clauses


I am trying to generate documentations for a github library using haddock. Here's the code I entered:

$ find -name '*.hs' | xargs haddock --html -o docs
src/Reflex/Dom/Xhr.hs:154:0:
     error: missing binary operator before token "("
     #if MIN_VERSION_aeson(1,0,0)
     ^

Then I looked up the relevant section of my source code Xhr.hs line 154:

import Data.Aeson
#if MIN_VERSION_aeson(1,0,0)
import Data.Aeson.Text
#else
import Data.Aeson.Encode
#endif

I didn't know #if, #else and #endif were part of Haskell but I could guess the meaning. Depending on the version, the code should import either Aeson.Text or Aeson.Encode. Just in case, I looked up the version:

$ ghc-pkg list | grep aeson
    aeson-0.11.3.0

This was enough to give haddock difficulty. The info pages get sent to a folder called docs which contains a few empty html files waiting to be populated with the details of the Reflex.Dom library.


Solution

  • That code uses -cpp. Preprocessor directives are not part of the usual Haskell language. In order to correctly parse that code, you need to specify additional options to Haddock:

    2.1. Using literate or pre-processed source

    Since Haddock uses GHC internally, both plain and literate Haskell sources are accepted without the need for the user to do anything. To use the C pre-processor, however, the user must pass the the -cpp option to GHC using --optghc. [emphasis mine]

    There are two problems, though. C preprocessor macro expansion you've posted will only work with GHC 8.0 (or later) if the package is exposed. It should, however, work with cabal haddock or stack haddock regardless of GHC's version. The latter variants are recommended if you try to build the documentation of a cabal/stack package, by the way.

    If you still know what you're doing, use haddock --optghc=-cpp.