----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Build.Macros -- Copyright : Simon Marlow 2008 -- -- Maintainer : cabal-devel@haskell.org -- Portability : portable -- -- Generate cabal_macros.h - CPP macros for package version testing -- -- When using CPP you get -- -- > VERSION_ -- > MIN_VERSION_(A,B,C) -- -- for each /package/ in @build-depends@, which is true if the version of -- /package/ in use is @>= A.B.C@, using the normal ordering on version -- numbers. -- -- TODO Figure out what to do about backpack and internal libraries. It is very -- suspicious that this stuff works with munged package identifiers module Distribution.Simple.Build.Macros ( generateCabalMacrosHeader , generatePackageVersionMacros ) where import Distribution.Compat.Prelude import Prelude () import Distribution.PackageDescription import Distribution.Pretty import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Program.Db import Distribution.Simple.Program.Types import Distribution.Types.MungedPackageId import Distribution.Types.MungedPackageName import Distribution.Version import qualified Distribution.Simple.Build.Macros.Z as Z -- | The contents of the @cabal_macros.h@ for the given configured package. generateCabalMacrosHeader :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String generateCabalMacrosHeader pkg_descr lbi clbi = Z.render Z.Z { Z.zPackages = map mkZPackage $ package pkg_descr : map getPid (componentPackageDeps clbi) , Z.zTools = [ Z.ZTool { Z.ztoolName = programId prog , Z.ztoolVersion = ver , Z.ztoolX = major1 , Z.ztoolY = major2 , Z.ztoolZ = minor } | prog <- configuredPrograms $ withPrograms lbi , ver <- maybeToList (programVersion prog) , let (major1, major2, minor) = majorMinor ver ] , Z.zPackageKey = case clbi of LibComponentLocalBuildInfo{} -> componentCompatPackageKey clbi _ -> "" , Z.zComponentId = prettyShow (componentComponentId clbi) , Z.zPackageVersion = pkgVersion (package pkg_descr) , Z.zNotNull = not . null , Z.zManglePkgName = map fixchar . unPackageName , Z.zMangleStr = map fixchar } where getPid (_, MungedPackageId (MungedPackageName pn _) v) = -- NB: Drop the library name! We're just reporting package versions. -- This would have to be revisited if you are allowed to depend -- on different versions of the same package PackageIdentifier pn v -- | Helper function that generates just the @VERSION_pkg@ and @MIN_VERSION_pkg@ -- macros for a list of package ids (usually used with the specific deps of -- a configured package). generatePackageVersionMacros :: Version -> [PackageId] -> String generatePackageVersionMacros ver pkgids = Z.render Z.Z { Z.zPackages = map mkZPackage pkgids , Z.zTools = [] , Z.zPackageKey = "" , Z.zComponentId = "" , Z.zPackageVersion = ver , Z.zNotNull = not . null , Z.zManglePkgName = map fixchar . unPackageName , Z.zMangleStr = map fixchar } mkZPackage :: PackageId -> Z.ZPackage mkZPackage (PackageIdentifier name ver) = Z.ZPackage { Z.zpkgName = name , Z.zpkgVersion = ver , Z.zpkgX = major1 , Z.zpkgY = major2 , Z.zpkgZ = minor } where (major1, major2, minor) = majorMinor ver majorMinor :: Version -> (String, String, String) majorMinor ver = case map show (versionNumbers ver) of [] -> ("0", "0", "0") [x] -> (x, "0", "0") [x, y] -> (x, y, "0") (x : y : z : _) -> (x, y, z) fixchar :: Char -> Char fixchar '-' = '_' fixchar c = c