我想在我的项目中找到所有的“Makefile”,然后根据它们生成规则。但是,看起来(故意)没有什么可以逃脱动作。因此,我在摇动功能之前将我的“Makefile”扫描仪提升到了 IO 操作。
main = do
makefiles <- findMakefiles
shake skakeOptions $ generate_rules makefiles
有没有更好的办法?
我想在我的项目中找到所有的“Makefile”,然后根据它们生成规则。但是,看起来(故意)没有什么可以逃脱动作。因此,我在摇动功能之前将我的“Makefile”扫描仪提升到了 IO 操作。
main = do
makefiles <- findMakefiles
shake skakeOptions $ generate_rules makefiles
有没有更好的办法?
首先,我认为目前的方法没有任何问题。Shake 包本身对内置的 Ninja 和 Makefile 解释器使用类似的方法,请参阅有关 Makefile 解释器 或Sake 解释器的详细信息。只要处理 Makefile 足够快(通常是这样),那么您基本上是在使用 Shake 为您的自定义构建语法编写一个解释器,它工作得很好。
有几个原因可以避免这种方法,例如,如果 Makefile 的处理成本很高,或者 Makefile 本身有其他依赖项。在这种情况下,您可以使用组合newCache
来解析 Makefile 一次,addOracle
因此规则可以取决于它们所需的 Makefile 子集。但是,这种方法很难正确,因为它基本上强制了一个间接层,并且您必须对如何generate_rules
工作做出一些假设。ghc-make包使用这种技术(参见“makefile”规则和调用newCache
),usingConfigFile
Shake 包中的函数使用相同的newCache
/addOracle
模式。
坚持原来的方法,您可以在某些地方稍有不同findMakefiles
。你可以做:
main = shakeArgsWith shakeOptions [] $ \_ -> xs -> do
makefiles <- findMakefiles
let rules = generate_rules makefiles
if null xs then rules else withoutActions rules >> want xs
这样做的好处是您可以轻松添加命令行标志来确定在哪里可以找到 Makefile,或处理它的选项。Shake 中的 Ninja 和 Makefile 系统都支持这一点,--makefile=FILE
用于覆盖默认值。即使您不想 move generate_rules
,您也可能希望在原始示例中替换shake
为shakeArgs
,这将为您提供命令行处理。