Created
October 31, 2010 15:44
-
-
Save hvr/656738 to your computer and use it in GitHub Desktop.
Example CABAL Setup.hs file for automatic package versioning via `git describe`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Exception | |
import Control.Monad | |
import Data.Maybe | |
import Data.Version | |
import Distribution.PackageDescription (PackageDescription(..), HookedBuildInfo, GenericPackageDescription(..)) | |
import Distribution.Package (PackageIdentifier(..)) | |
import Distribution.Simple (defaultMainWithHooks, simpleUserHooks, UserHooks(..)) | |
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..)) | |
import Distribution.Simple.Setup (BuildFlags(..), ConfigFlags(..)) | |
import Distribution.Simple.Utils (die) | |
import System.Process (readProcess) | |
import Text.ParserCombinators.ReadP (readP_to_S) | |
main :: IO () | |
main = defaultMainWithHooks simpleUserHooks | |
{ confHook = myConfHook | |
, buildHook = myBuildHook | |
} | |
-- configure hook | |
myConfHook :: (GenericPackageDescription, HookedBuildInfo) | |
-> ConfigFlags | |
-> IO LocalBuildInfo | |
myConfHook (gpdesc, hbinfo) cfg = do | |
gitVersion <- inferVersionFromGit | |
let GenericPackageDescription { | |
packageDescription = pdesc@PackageDescription { | |
package = pkgIden }} = gpdesc | |
let gpdesc' = gpdesc { | |
packageDescription = pdesc { | |
package = pkgIden { pkgVersion = gitVersion } } } | |
-- putStrLn $ showVersion gitVersion | |
confHook simpleUserHooks (gpdesc', hbinfo) cfg | |
-- build hook | |
myBuildHook :: PackageDescription | |
-> LocalBuildInfo | |
-> UserHooks | |
-> BuildFlags | |
-> IO () | |
myBuildHook pdesc lbinfo uhooks bflags = do | |
gitVersion <- inferVersionFromGit | |
let lastVersion = pkgVersion $ package pdesc | |
when (gitVersion /= lastVersion) $ | |
die("The version reported by git '" ++ showVersion gitVersion ++ | |
"' has changed since last time this package was configured (version was '" ++ | |
showVersion lastVersion ++ "' back then), please re-configure package") | |
buildHook simpleUserHooks pdesc lbinfo uhooks bflags | |
-- |Infer package version from Git tags. Uses `git describe` to infer 'Version'. | |
inferVersionFromGit :: IO Version | |
inferVersionFromGit = do | |
ver_line <- init `liftM` readProcess "git" | |
[ "describe" | |
, "--abbrev=5" | |
, "--tags" | |
, "--match=v[0-9].[0-9][0-9]" | |
, "--dirty" | |
, "--long" | |
] "" | |
-- ver_line <- return "v0.1-42-gf9f4eb3-dirty" | |
let versionStr = (head ver_line == 'v') `assert` replaceFirst '-' '.' (tail ver_line) | |
Just version = listToMaybe [ p | (p, "") <- readP_to_S parseVersion versionStr ] | |
return version | |
-- |Helper for replacing first occurence of character by another one. | |
replaceFirst :: Eq a => a -> a -> [a] -> [a] | |
replaceFirst _ _ [] = [] | |
replaceFirst o r (x:xs) | o == x = r : xs | |
| otherwise = x : replaceFirst o r xs |
Note that this approach is no longer valid, as Cabal does not permit tags in package versions. A shame, because I feel this approach is cleaner than generating a new module, although I understand why the Cabal developers made the choice.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Alternative approach to the one described in http://www.hyperedsoftware.com/blog/entries/build-info-gen.html