J'ai besoin de communiquer des informations provenant de scripts de compilation dans Template Haskell. Actuellement, les scripts de compilation conservent les informations dans l'environnement système. Je les lis donc en utilisant System.Environment.getEnvironment
encapsulé dans runIO
. Existe-t-il un meilleur moyen, tel que de passer des arguments à ghc
(similaire à -D...
pour le pré-processeur C), ou peut-être quelque chose de spécifiquement conçu à cet effet dans TH?
Réponses
Trop de publicités?Comme de nombreuses personnes se sont intéressées à la question, je vais ajouter mon approche actuelle, peut-être que quelqu'un va la trouver utile. Probablement la meilleure façon serait si TH autorisé à lire -D
paramètres sur GHC la ligne de commande, mais il semble que rien de tel n'est actuellement mis en œuvre.
Un simple module permet de TH à lire au moment de la compilation de l'environnement. Une fonction d'assistance permet également de lire des fichiers; par exemple lire le chemin d'accès d'un fichier de configuration de l'environnement, puis de lire le fichier.
{-# LANGUAGE TemplateHaskell #-}
module THEnv
(
-- * Compile-time configuration
lookupCompileEnv
, lookupCompileEnvExp
, getCompileEnv
, getCompileEnvExp
, fileAsString
) where
import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (Lift(..))
import System.Environment (getEnvironment)
-- Functions that work with compile-time configuration
-- | Looks up a compile-time environment variable.
lookupCompileEnv :: String -> Q (Maybe String)
lookupCompileEnv key = lookup key `liftM` runIO getEnvironment
-- | Looks up a compile-time environment variable. The result is a TH
-- expression of type @Maybe String@.
lookupCompileEnvExp :: String -> Q Exp
lookupCompileEnvExp = (`sigE` [t| Maybe String |]) . lift <=< lookupCompileEnv
-- We need to explicly type the result so that things like `print Nothing`
-- work.
-- | Looks up an compile-time environment variable and fail, if it's not
-- present.
getCompileEnv :: String -> Q String
getCompileEnv key =
lookupCompileEnv key >>=
maybe (fail $ "Environment variable " ++ key ++ " not defined") return
-- | Looks up an compile-time environment variable and fail, if it's not
-- present. The result is a TH expression of type @String@.
getCompileEnvExp :: String -> Q Exp
getCompileEnvExp = lift <=< getCompileEnv
-- | Loads the content of a file as a string constant expression.
-- The given path is relative to the source directory.
fileAsString :: FilePath -> Q Exp
fileAsString = do
-- addDependentFile path -- works only with template-haskell >= 2.7
stringE . T.unpack . T.strip <=< runIO . T.readFile
Il peut être utilisé comme ceci:
{-# LANGUAGE TemplateHaskell #-}
import THEnv
main = print $( lookupCompileEnvExp "DEBUG" )
Alors:
-
runhaskell Main.hs
tiragesNothing
; -
DEBUG="yes" runhaskell Main.hs
tiragesJust "yes"
.
Il ressemble à ce que vous essayez de faire ici, L'option-D dans ghc semble définir un temps de compilation variable.
Ici, sur le même sujet est une question qui semble également répondre à l'autre partie de votre question. À partir de ce que je peux dire, pour faire de la compilation conditionnelle, vous faites quelque chose comme:
#ifdef MACRO_NAME
//Do stuff here
#endif