2015-10-05 42 views
2

如何在摇动中传递参数然后在我们的规则中使用它们?我想提出的一些等价物:如何在摇动中构建变体?

make ARCH=x86_64

make DEBUG=YES 等等

现在我一直在使用环境变量和getEnv函数来模拟这些。
我如何使一个给定参数(环境变量)的依赖关系,以便它可以在构建中读取一次,将其存储在某处并从多个规则访问它?

例如现在,我在多个规则中多次执行getEnv,但在编译期间,环境变量可能会更改。此外,例如,调试标志可以更改编译器和链接器标志,这意味着信息需要在链接和编译输出规则中都可用。

+0

“但在编译期间,环境变量可以改变” - 你能澄清一下吗?环境变量在进程开始时被捕获,所以在运行期间不会改变,除非你调用类似'setEnv'的东西。 –

+0

另一个问题是,你是否想要将'DEBUG = YES'改为'DEBUG = NO'来更改所有依赖该设置的规则(重建大部分项目),或者只是忽略更改,或者构建到不同的目录? –

+0

关于第一个评论:那么我忘记了那么划伤了。 关于第二条评论:是的,我想改变所有依赖于该设置的规则来改变。例如,编译/链接标志将会改变,输出目录也会改变。 – Fr0stBit

回答

1

您现有的使用环境变量的方法应该可行,并且由于环境变量已被Shake跟踪,所以一种方法是解析DEBUG=YES并将其转换为环境变量。例如:

main = shakeArgsWith shakeOptions [] $ \_ args -> do 
    let (vars,files) = partition ('=' `elem`) args 
    forM_ vars $ \v -> let (a,'=':b) = break (== '=') v in setEnv a b 
    return $ Just $ if null files then rules else want files >> withoutActions rules 

rules :: Rules() 
rules = ... 

由于环境变量是本地的一个进程(及其子进程),这可能会工作得很好。

当然,将这些信息存储在环境变量中有点难看。你可以创建自己的Oracle存储信息,而不是:

main = shakeArgsWith shakeOptions [] $ \_ args -> do 
    let (vars,files) = partition ('=' `elem`) args 
    let vars2 = [(a,b) | v <- vars, let (a,'=':b) = break (== '=') v] 
    return $ Just $ do 
     global <- addOracle $ \(Global x) -> return $ lookup x vars2 
     if null files then rules global else want files >> withoutActions (rules global) 

newtype Global = Global String deriving (Show,Typeable,Eq,Hashable,Binary,NFData) 

rules :: (Global -> Action (Maybe String)) -> Rules() 
rules global = undefined 

现在,而不是将信息写入到一个环境变量,setEnv,我们把它存放在与addOracle的预言,这将仍然被跟踪,而不是冲突与任何其他环境变量的片断。

+0

梦幻般的解决方案! shakeArgsWith入口点就是我想要的一切。 oracle功能看起来也很整洁,但从文档中很难理解。我会给它一个镜头,但:P!谢谢回答! – Fr0stBit

+0

最好的文档在https://hackage.haskell.org/package/shake/docs/Development-Shake.html#v:addOracle。他们是Shake更复杂的一个方面。 –