{-# LANGUAGE DeriveAnyClass #-}
module Pier.Build.CFlags
( TransitiveDeps(..)
, CFlags(..)
, getCFlags
, ghcDefines
) where
import Control.Applicative (liftA2)
import Control.Monad (guard)
import Data.Semigroup
import Data.Set (Set)
import Development.Shake
import Development.Shake.Classes
import Distribution.PackageDescription
import Distribution.System (buildOS, OS(OSX))
import Distribution.Text (display)
import Distribution.Types.PkgconfigDependency
import Distribution.Version (versionNumbers)
import GHC.Generics (Generic(..))
import qualified Data.Set as Set
import Pier.Build.Stackage
import Pier.Core.Artifact
data TransitiveDeps = TransitiveDeps
{ transitiveDBs :: Set Artifact
, transitiveLibFiles :: Set Artifact
, transitiveIncludeDirs :: Set Artifact
, transitiveDataFiles :: Set Artifact
} deriving (Show, Eq, Typeable, Generic, Hashable, Binary, NFData)
instance Semigroup TransitiveDeps
instance Monoid TransitiveDeps where
mempty = TransitiveDeps Set.empty Set.empty Set.empty Set.empty
TransitiveDeps dbs files is datas
`mappend` TransitiveDeps dbs' files' is' datas'
= TransitiveDeps (dbs <> dbs') (files <> files') (is <> is')
(datas <> datas')
data CFlags = CFlags
{ ccFlags :: [String]
, cppFlags :: [String]
, cIncludeDirs :: Set Artifact
, linkFlags :: [String]
, linkLibs :: [String]
, macFrameworks :: [String]
}
getCFlags :: TransitiveDeps -> Artifact -> BuildInfo -> Action CFlags
getCFlags deps pkgDir bi = do
pkgConfFlags <- mconcat <$> mapM getPkgConfFlags (pkgconfigDepends bi)
return CFlags
{ ccFlags = ccOptions bi ++ fst pkgConfFlags
, cppFlags = cppOptions bi
, cIncludeDirs =
Set.fromList (map (pkgDir />) $ includeDirs bi)
<> transitiveIncludeDirs deps
, linkFlags = ldOptions bi ++ snd pkgConfFlags
, linkLibs = extraLibs bi
, macFrameworks = guard (buildOS == OSX)
>> frameworks bi
}
getPkgConfFlags :: PkgconfigDependency -> Action ([String], [String])
getPkgConfFlags (PkgconfigDependency name _) = liftA2 (,)
(runPkgConfig [display name, "--cflags"])
(runPkgConfig [display name, "--libs"])
where
runPkgConfig = fmap words . runCommandStdout . prog "pkg-config"
ghcDefines :: InstalledGhc -> [String]
ghcDefines ghc = ["-D__GLASGOW_HASKELL__=" ++
cppVersion (ghcInstalledVersion ghc)]
where
cppVersion v = case versionNumbers v of
(v1:v2:_) -> show v1 ++ if v2 < 10 then '0':show v2 else show v2
_ -> error $ "cppVersion: " ++ display v