{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -- | -- Module: $HEADER$ -- Description: Data type describing pkg-config configuration file -- Copyright: (c) 2014 Peter Trsko -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com -- Stability: experimental -- Portability: DeriveDataTypeable, NoImplicitPrelude, OverloadedStrings, -- RecordWildCards -- -- Data type describing /pkg-config/ configuration file. module Data.PkgConfig.Internal.PkgConfig ( -- * PkgConfig PkgConfig(..) -- * Type Aliases , PkgVariable , PkgName , PkgDescription , PkgUrl , PkgVersion -- * Lenses , pkgVariables , pkgName , pkgDescription , pkgUrl , pkgVersion , pkgRequires , pkgRequiresPrivate , pkgConflicts , pkgCflags , pkgLibs , pkgLibsPrivate -- * Serialization , toStrictText ) where import Data.Bool (not, otherwise) import Data.Data (Data) import Data.Function ((.), ($), flip) import Data.Functor (Functor(fmap)) import Data.List as List (filter, map) import Data.Monoid ((<>)) import Data.Typeable (Typeable) import GHC.Generics (Generic) import Text.Show (Show) import qualified Data.Text as Strict (Text) import qualified Data.Text as Strict.Text import Data.Default.Class (Default(def)) import Data.PkgConfig.Internal.Template (PkgTemplate) import qualified Data.PkgConfig.Internal.Template as Template (toStrictText) -- | Variable definition consisting of its name and value in form of -- 'PkgTemplate'. type PkgVariable = (Strict.Text, PkgTemplate) type PkgName = Strict.Text type PkgDescription = Strict.Text type PkgUrl = Strict.Text -- | Package version may use variable expansion and so it is represented by -- 'PkgConfig'. type PkgVersion = PkgTemplate -- | Representation of /pkg-config/ configuration file. data PkgConfig = PkgConfig { _pkgVariables :: [PkgVariable] -- ^ Variable definitions. , _pkgName :: PkgName -- ^ Human-readable name for a library or package. This field is not used -- by /pkg-config/ tool for queries, because it uses @.pc@ file base name. , _pkgDescription :: PkgDescription -- ^ Brief description of the package. , _pkgUrl :: PkgUrl -- ^ URL where people can get more information about and download the -- package. , _pkgVersion :: PkgVersion -- ^ Version of the package. , _pkgRequires :: PkgTemplate -- ^ List of packages required by this package and their version bounds. , _pkgRequiresPrivate :: PkgTemplate -- ^ List of private packages required by this package but not exposed to -- applications. The version specific rules from the Requires field also -- apply here. , _pkgConflicts :: PkgTemplate -- ^ An optional field describing packages that this one conflicts with. -- The version specific rules from the Requires field also apply here. This -- field also takes multiple instances of the same package. E.g.: -- -- @ -- Conflicts: bar \< 1.2.3, bar \>= 1.3.0. -- @ , _pkgCflags :: PkgTemplate -- ^ Compiler flags specific to this package and any required libraries -- that don't support /pkg-config/. If the required libraries support -- /pkg-config/, they should be added to @Requires@ ('_pkgRequires') or -- @Requires.private@ ('_pkgRequiresPrivate'). , _pkgLibs :: PkgTemplate -- ^ Linking flags specific to this package and any required libraries that -- don't support /pkg-config/. The same rules as for @Cflags@ ('_pkgCflags') -- field apply here. , _pkgLibsPrivate :: PkgTemplate -- ^ Linking flags for private libraries required by this package but not -- exposed to applications. The same rules as for @Cflags@ ('_pkgCflags') field apply -- here. } deriving (Data, Generic, Show, Typeable) instance Default PkgConfig where def = PkgConfig { _pkgVariables = [] , _pkgName = Strict.Text.empty , _pkgDescription = Strict.Text.empty , _pkgUrl = Strict.Text.empty , _pkgVersion = def , _pkgRequires = def , _pkgRequiresPrivate = def , _pkgConflicts = def , _pkgCflags = def , _pkgLibs = def , _pkgLibsPrivate = def } -- | Serialize 'PkgConfig' in to strict 'Strict.Text'. toStrictText :: PkgConfig -> Strict.Text toStrictText PkgConfig{..} = Strict.Text.concat [ variablesToStrictText _pkgVariables , Strict.Text.unlines [""] , Strict.Text.unlines $ List.filter (not . Strict.Text.null) [ "Name" <:> _pkgName , "Description" <:> _pkgDescription , "URL" <:> _pkgUrl , "Version" <:>. _pkgVersion , "Requires" <:>. _pkgRequires , "Requires.private" <:>. _pkgRequiresPrivate , "Conflicts" <:>. _pkgConflicts , "Cflags" <:>. _pkgCflags , "Libs" <:>. _pkgLibs , "Libs.private" <:>. _pkgLibsPrivate ] ] where key <:> value | Strict.Text.null value = Strict.Text.empty | otherwise = key <> ": " <> value key <:>. value = key <:> Template.toStrictText value variablesToStrictText = Strict.Text.unlines . map varToText where varToText (name, tmpl) = name <> "=" <> Template.toStrictText tmpl (<$$>) :: Functor f => f a -> (a -> b) -> f b (<$$>) = flip fmap -- | Variable definitions. pkgVariables :: Functor f => ([PkgVariable] -> f [PkgVariable]) -> PkgConfig -> f PkgConfig pkgVariables f cfg@(PkgConfig{_pkgVariables = a}) = f a <$$> \b -> cfg{_pkgVariables = b} -- | Human-readable name of a library or package. This field is not used by -- /pkg-config/ tool for queries, because it uses @.pc@ file base name. pkgName :: Functor f => (Strict.Text -> f Strict.Text) -> PkgConfig -> f PkgConfig pkgName f cfg@(PkgConfig{_pkgName = a}) = f a <$$> \b -> cfg{_pkgName = b} -- | Brief description of the package. pkgDescription :: Functor f => (Strict.Text -> f Strict.Text) -> PkgConfig -> f PkgConfig pkgDescription f cfg@(PkgConfig{_pkgDescription = a}) = f a <$$> \b -> cfg{_pkgDescription = b} -- | URL where people can get more information about and download the package. pkgUrl :: Functor f => (Strict.Text -> f Strict.Text) -> PkgConfig -> f PkgConfig pkgUrl f cfg@(PkgConfig{_pkgUrl = a}) = f a <$$> \b -> cfg{_pkgUrl = b} -- | Version of the package. pkgVersion :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgVersion f cfg@(PkgConfig{_pkgVersion = a}) = f a <$$> \b -> cfg{_pkgVersion = b} -- | List of packages required by this package and their version bounds. pkgRequires :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgRequires f cfg@(PkgConfig{_pkgRequires = a}) = f a <$$> \b -> cfg{_pkgRequires = b} -- | Compiler flags specific to this package and any required libraries that -- don't support /pkg-config/. If the required libraries support /pkg-config/, -- they should be added to @Requires@ ('pkgRequires') or @Requires.private@ -- ('pkgRequiresPrivate'). pkgRequiresPrivate :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgRequiresPrivate f cfg@(PkgConfig{_pkgRequiresPrivate = a}) = f a <$$> \b -> cfg{_pkgRequiresPrivate = b} -- | An optional field describing packages that this one conflicts with. The -- version specific rules from the Requires field also apply here. This field -- also takes multiple instances of the same package. E.g.: -- -- @ -- Conflicts: bar \< 1.2.3, bar \>= 1.3.0. -- @ pkgConflicts :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgConflicts f cfg@(PkgConfig{_pkgConflicts = a}) = f a <$$> \b -> cfg{_pkgConflicts = b} -- | Compiler flags specific to this package and any required libraries that -- don't support /pkg-config/. If the required libraries support /pkg-config/, -- they should be added to @Requires@ ('pkgRequires') or @Requires.private@ -- ('pkgRequiresPrivate'). pkgCflags :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgCflags f cfg@(PkgConfig{_pkgCflags = a}) = f a <$$> \b -> cfg{_pkgCflags = b} -- | Linking flags specific to this package and any required libraries that -- don't support /pkg-config/. The same rules as for @Cflags@ ('pkgCflags') -- field apply here. pkgLibs :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgLibs f cfg@(PkgConfig{_pkgLibs = a}) = f a <$$> \b -> cfg{_pkgLibs = b} -- | Linking flags for private libraries required by this package but not -- exposed to applications. The same rules as for @Cflags@ ('pkgCflags') field -- apply here. pkgLibsPrivate :: Functor f => (PkgTemplate -> f PkgTemplate) -> PkgConfig -> f PkgConfig pkgLibsPrivate f cfg@(PkgConfig{_pkgLibsPrivate = a}) = f a <$$> \b -> cfg{_pkgLibsPrivate = b}