[Haskell-cafe] Defining a CPP macro when building documentation

Maxime Henrion mhenrion at gmail.com
Sun May 24 16:58:06 EDT 2009


	Hello all,


I have been exposed to a problem that have happened to others too, and
since I have found a (scary) solution with the help of Duncan Coutts,
I'm now sharing it with you.

The reason I wanted to pass specific CPP flags to haddock was to allow
the documentation of the full module to get built, even when only parts
of the module would end up getting compiled because of restrictions on
the build platform.

In this mail, Duncan Coutts gives a very helpful bit of code to override
the haddockHook and pass additional options to haddock :

http://www.haskell.org/pipermail/haskell-cafe/2008-December/051785.html

In my case, I needed something very similar, except that I needed to
pass those additional options to hsc2hs which my code uses.  This worked
fine as long as the cabal commands sequence was ["configure","haddock"]
and not ["configure","build","haddock"].  The reason for this is that in
the latter case, the library wasn't being processed again, but output of
previous runs of hsc2hs were reused.

So I worked around this with an ugly hack that removes the .hs files
before running haddock, in order to force re-processing!  Here's the
final code I ended up with :

import Distribution.Simple
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(withPrograms), buildDir)
import Distribution.Simple.Program (userSpecifyArgs)

import System.Directory
import System.FilePath

-- Define __HADDOCK__ when building documentation.
main = defaultMainWithHooks simpleUserHooks {
  haddockHook = \pkg lbi h f -> do
    let progs = userSpecifyArgs "hsc2hs" ["-D__HADDOCK__"] (withPrograms lbi)
    removePreProcessedFiles (buildDir lbi)
    haddockHook simpleUserHooks pkg lbi { withPrograms = progs } h f
}

-- Horrible hack to force re-processing of the .hsc file.  Otherwise
-- the __HADDOCK__ macro doesn't end up being defined.
removePreProcessedFiles :: FilePath -> IO ()
removePreProcessedFiles dir =
  removeFile (dir </> "System/BSD/Sysctl.hs")
    `catch` \_ -> return ()

Cheers,
Maxime



More information about the Haskell-Cafe mailing list