{-# OPTIONS_GHC -Wall #-} import Distribution.Simple import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Setup import Distribution.PackageDescription --import System.Time import System.Process import System.IO import Control.Exception import Data.List import Data.Time.Clock import Data.Time.Format import System.Locale main :: IO () main = defaultMainWithHooks (simpleUserHooks { buildHook = generateBuildInfoHook } ) -- Before each build, generate a BuildInfo_Generated module that exports the project version from cabal, -- the current svn revision number and the build time. -- -- Note that in order for this Setup.hs to be used by cabal, the build-type should be Custom. generateBuildInfoHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO () generateBuildInfoHook pd lbi uh bf = do { let cabalVersionStr = intercalate "." (map show . versionBranch . pkgVersion . package $ pd) ; svnRevisionStr <- do { r <- catch getSVNRevisionStr myHandler ; if r == "" then noSVNRevisionStr else return r } ; clockTime <- getCurrentTime ; let buildTimeStr = formatTime defaultTimeLocale "%d-%b-%y %H:%M:%S %Z" clockTime ; writeFile "src/lib/DatabaseDesign/Ampersand/Basics/BuildInfo_Generated.hs" $ buildInfoModule cabalVersionStr svnRevisionStr buildTimeStr ; (buildHook simpleUserHooks) pd lbi uh bf -- start the build } where myHandler :: IOException -> IO String myHandler err = do { print err ; noSVNRevisionStr } buildInfoModule :: String -> String -> String -> String buildInfoModule cabalVersion revision time = unlines [ "module DatabaseDesign.Ampersand.Basics.BuildInfo_Generated (cabalVersionStr, svnRevisionStr, buildTimeStr) where" , "" , "-- This module is generated automatically by Setup.hs before building. Do not edit!" , "" , "{-# NOINLINE cabalVersionStr #-}" -- disable inlining to prevent recompilation of dependent modules on each build , "cabalVersionStr :: String" , "cabalVersionStr = \"" ++ cabalVersion ++ "\"" , "" , "{-# NOINLINE svnRevisionStr #-}" , "svnRevisionStr :: String" , "svnRevisionStr = \"" ++ revision ++ "\"" , "" , "{-# NOINLINE buildTimeStr #-}" , "buildTimeStr :: String" , "buildTimeStr = \"" ++ time ++ "\"" ] getSVNRevisionStr :: IO String getSVNRevisionStr = do { (inh,outh,errh,proch) <- runInteractiveProcess "svnversion" ["."] Nothing Nothing ; hClose inh ; hClose errh ; version <- hGetContents outh ; _ <- seq version $ waitForProcess proch ; return (unwords . lines $ version) } noSVNRevisionStr :: IO String noSVNRevisionStr = do { putStrLn "\n\n\nWARNING: Execution of 'svnversion' command failed." ; putStrLn $ "BuildInfo_Generated.hs will not contain revision information, and therefore\nneither will fatal error messages.\n"++ "Please find out why the command 'svnversion .' does not work.\n"++ "Otherwise (re-)install a subversion client (e.g. 'Slik SVN') that supports\nthe command-line 'svnversion'-command without interfering with your other SVN-clients.\n" ; return "??" }