69 votes

Comment communiquer correctement les informations de compilation aux fonctions de Template Haskell?

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?

13voto

Petr Pudlák Points 25113

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 tirages Nothing;
  • DEBUG="yes" runhaskell Main.hs tirages Just "yes".

3voto

jaked122 Points 151

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X