2013-10-30 3 views
69

私は、コンパイルスクリプトからTemplate Haskellに情報を伝える必要があります。現在のところ、コンパイルスクリプトは情報をシステム環境に保存しているので、runIOで囲まれたSystem.Environment.getEnvironmentを使って読むだけです。 ghc(Cプリプロセッサの場合は-D...に似ています)への引数や、THでこの目的のために特別に設計されたものなど、より良い方法がありますか?コンパイル時の情報をTemplate Haskell関数に正しく伝えるには?

+9

外部ファイルからその情報を読み出して使用して[ 'addDependentFile'(http://hackage.haskell.org/package/template-haskell-2.8.0.0/docs/Language-Haskell-TH-Syntax。 html#v:addDependentFile)を使って、 'ghc --make'に知られているファイルを明白な選択肢にします。現在の体系上の問題は何ですか? –

+2

@MikhailGlushenkov実際には、環境はプロジェクトディレクトリのルートだけを通過し、さらに詳細な情報がファイルから読み込まれます。ですから、 'addDependentFile'が私の場合に役立ちます。現在のスキームが働いている、私はちょうどそこにいくつかの他の、標準的な方法があるかどうかを知りたい。 –

+5

['location'](http://hackage.haskell.org/package/template-haskell-2.8.0.0/docs/Language-Haskell-TH-Syntax.html#v:location)関数を使用して、プロジェクトディレクトリのルートを取得します(現在のモジュールからルートへの相対パスを知っていると仮定します)。ここに[例](https://gist.github.com/23Skidoo/6258379)があります。 –

答えて

3

あなたは何をしようとしていますか?here、ghcの-Dオプションは、コンパイル時の変数を定義しているようです。

ここでは、同じ件名にはquestionもありますが、これはあなたの質問の他の部分にも答えているようです。

#ifdef MACRO_NAME 
    //Do stuff here 
    #endif 
+1

私がコメントで言ったように、私はCPPと条件付きコンパイルを使いたくありません。私はそれを使用していません、私が望むのはTemplate Haskellに情報を渡すことだけです。 '-D'オプションは、CPPなしでTHでそれを読む方法があるなら、いいでしょう。 –

+1

これも、* haskell *コードの条件付きコンパイル用です。私はマクロを-D(多分いくつかの値を設定したもの)で定義する以外のことは知らないので、あなたはあなたのhaskellの値をチェックすることができ、それが動作するかもしれません。私は確信するために十分な知識を持っていません。 – jaked122

10

ので、多くの人が疑問に興味があるので、私は私の現在のアプローチを追加します、おそらく誰かがそれが役に立つでしょう:私は条件付きコンパイルを行うには、伝えることができるものから は、あなたのような何かをします。おそらく、THがGHCのコマンドラインで-Dのパラメータを読み取ることを許可された場合、おそらく最良の方法ですが、現在実装されているようなものではないようです。

単純なモジュールを使用すると、THはコンパイル時の環境を読み取ることができます。ヘルパー関数はファイルの読み込みも可能です。例えば、環境から構成ファイルのパスを読み込んで、そのファイルを読み取ることができます。

{-# 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 [email protected] 
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 @[email protected] 
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 

それはこのように使用することができる。

{-# LANGUAGE TemplateHaskell #-} 
import THEnv 
main = print $(lookupCompileEnvExp "DEBUG") 

そして:

  • runhaskell Main.hsプリントNothing
  • DEBUG="yes" runhaskell Main.hsプリントJust "yes"
関連する問題