[Haskell-cafe] Synchronising cabal package version with self-reported version

Don Stewart dons at galois.com
Fri Apr 17 22:41:47 EDT 2009

> Hi all,
> In a command-line app of mine I want to have a --version flag, like
> many GNU apps do to report their version.  The only way I know to
> provide the version number is to hardcode it in the source code
> somewhere.  That means I have the version number in two places: the
> .cabal file and the source code.  I just know that one day they'll get
> unsynchronised, and --version will be wrong.
> Is there any way to put the version number in _one_ place, and have
> both the .cabal and source refer to it?  Or even any easier way to
> synchronise both version numbers?

Yes, cabal provides support for this. Here's how we do that in xmonad.

In your program, import the magic module Paths_$progname:

    import Paths_xmonad (version)

        ["--version"]         -> putStrLn ("xmonad " ++ showVersion version) 

which provides many fields from the .cabal file used to compile the

In your .cabal file , have something like:

    name:               xmonad
    version:            0.8.1

Problem solved :)
Look in

    $ vim dist/build/autogen/Paths_xmonad.hs

to see what you get to play with:

    module Paths_xmonad (
        getBinDir, getLibDir, getDataDir, getLibexecDir,
      ) where

    import Data.Version (Version(..))
    import System.Environment (getEnv)

    version :: Version
    version = Version {versionBranch = [0,8,1], versionTags = []}

    bindir, libdir, datadir, libexecdir :: FilePath

    bindir     = "/home/dons/.cabal/bin"
    libdir     = "/home/dons/.cabal/lib/xmonad-0.8.1/ghc-6.10.1"
    datadir    = "/home/dons/.cabal/share/xmonad-0.8.1"
    libexecdir = "/home/dons/.cabal/libexec"

    getBinDir, getLibDir, getDataDir, getLibexecDir :: IO FilePath
    getBinDir = catch (getEnv "xmonad_bindir") (\_ -> return bindir)
    getLibDir = catch (getEnv "xmonad_libdir") (\_ -> return libdir)
    getDataDir = catch (getEnv "xmonad_datadir") (\_ -> return datadir)
    getLibexecDir = catch (getEnv "xmonad_libexecdir") (\_ -> return libexecdir)

    getDataFileName :: FilePath -> IO FilePath
    getDataFileName name = do
      dir <- getDataDir
      return (dir ++ "/" ++ name)

-- Don

More information about the Haskell-Cafe mailing list