1

我正在尝试使用看起来非常有前途的 Shake,但我碰上了一面小墙。我对haskell很陌生,所以也许我遗漏了一些明显的东西,但这是我的问题:

我想在我的摇动程序中定义一种新的规则。该规则将从依赖项中计算一个值,然后让 Shake 将其存储在其数据库中。因此,如果依赖项是最新的,则shake db 值始终有效。

data PrjList = PrjList FilePath deriving (Typeable,Show,Eq,Hashable,Binary,NFData)

instance Rule PrjList [(String,FilePath)] where
    validStored q a = True

-- Generate the dependency
getProjectList :: FilePath -> Action [(String,FilePath)]
getProjectList dir = apply1 $ PrjList dir

-- We want to traverse recursivly all subdir but stop once we find a BuildConfig file
defaultProjectList :: Rules ()
defaultProjectList = defaultRule $ \(PrjList dir) -> Just $ do
     -- blabla...
     return []

但是,如果我尝试import Development.Shake.Core我有

Could not find module `Development.Shake.Core'
It is a member of the hidden package `shake-0.7'.
it is a hidden module in the package `shake-0.7'
it is a hidden module in the package `shake-0.8'
Use -v to see a list of the files searched for.

如果我不导入它,我有

`validStored' is not a (visible) method of class `Rule'

那么如何定义新规则呢?

额外的问题是:我的想法有趣还是有更好的方法?在考虑如何使用抖动时,我有很多规则会产生这种行为。这样可以避免拥有大量临时文件并利用抖动数据库。事实上,我的下一步是尝试为“文件系统自由规则”定义一个通用规则。用户只需要提供一个key → Maybe (Action value)功能。

4

1 回答 1

0

在shake-0.4 及更高版本validStored中被从Rule类中移除,并替换为:

storedValue :: key -> IO (Maybe value)

因此,您无需定义该值是否仍然正确,而是返回存储的值。这使您尝试做的事情变得更加困难,但仍然可能。您可以将value类型定义为:

data MyValue a = RealResult a | Cheat
instance Eq a => Eq (MyValue a) where
    RealValue a == RealValue b = a == b
    _ == _ = True

现在您可以定义storedValue _ = return $ Just Cheat,并且现有值将始终被视为有效。

使这些“缓存”规则更难的原因是因为我认为它们不是一个好主意,原因有以下三个:

  1. 如果您在编写构建系统时弄错了这些规则之一,则必须删除 Shake 数据库才能恢复到有效状态。
  2. 您不能轻易看到已生成的内容,因此必须求助于在大型多线程系统中很难进行的跟踪。
  3. 在构建系统的每次运行中,即使无事可做,Shake 也必须反序列化整个数据库,包括您存储在其中的任何大值。

我发现如果你只使用临时文件,一切都会变得更加简单。

我可以想象有一些缓存文件内容的反序列化的范围,例如,如果您将复杂的结构存储在文件中,但我还没有一个好的 API 来做这件事。

在 Shake 0.9 及以上

函数 newCache 提供了一种缓存文件内容反序列化的方法。

于 2013-01-31T20:09:53.087 回答