{-# LANGUAGE MultiParamTypeClasses, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}moduleDevelopment.Shake.Files((*>>))whereimportControl.DeepSeqimportControl.MonadimportControl.Monad.IO.ClassimportData.BinaryimportData.HashableimportData.TypeableimportDevelopment.Shake.CoreimportDevelopment.Shake.FileimportDevelopment.Shake.FilePatternimportDevelopment.Shake.FileTimeinfix1*>>newtypeFiles=Files[FilePath]deriving(Typeable,Eq,Hashable,Binary,NFData)newtypeFileTimes=FileTimes[FileTime]deriving(Typeable,Show,Eq,Hashable,Binary,NFData)instanceShowFileswhereshow(Filesxs)=unwordsxsinstanceRuleFilesFileTimeswherevalidStored(Filesxs)(FileTimests)=fmap(==mapJustts)$mapMgetModTimeMaybexs-- | Define a rule for building multiple files at the same time.-- As an example, a single invokation of GHC produces both @.hi@ and @.o@ files:---- > ["*.o","*.hi"] *>> \[o,hi] -> do-- > let hs = replaceExtension o "hs"-- > need ... -- all files the .hs import-- > system' "ghc" ["-c",hs]---- However, in practice, it's usually easier to define rules with '*>' and make the @.hi@ depend-- on the @.o@. When defining rules that build multiple files, all the 'FilePattern' values must-- have the same sequence of @\/\/@ and @*@ wildcards in the same order.(*>>)::[FilePattern]->([FilePath]->Action())->Rules()ps*>>act|not$compatibleps=error$"All patterns to *>> must have the same number and position of // and * wildcards\n"++unwordsps|otherwise=doforM_ps$\p->p*>\file->doapply1$Files$map(substitute$extractpfile)ps::ActionFileTimesreturn()rule$\(Filesxs)->ifnot$lengthxs==lengthps&&and(zipWith(?==)psxs)thenNothingelseJust$doactxsliftIO$fmapFileTimes$mapM(getModTimeError"Error, multi rule failed to build the file:")xs