I'm currently testing porting our build system from make to shake and have hit a roadblock:
Given the following project structure:
static/a.js
static/b.coffee
build/a.js
build/b.js
That is, various input extensions map to identical output extensions, so a straightforward "build//*.js" %>
rule isn't going to work.
I wanted to avoid using priority if possible, and writing an ad-hoc build rule that checks for the existence of either possible input felt clunky (especially since this situation occurs with other filetypes as well), so I wrote the following:
data StaticFileMapping a = StaticFileMapping String String (FilePath -> FilePath -> Action a)
staticInputs :: FilePath -> StaticFileMapping a -> Action [FilePath]
staticInputs dir (StaticFileMapping iExt _ _) = (findFiles (dir </> "static") [iExt])
staticInputToOutput :: StaticFileMapping a -> FilePath -> FilePath
staticInputToOutput (StaticFileMapping _ oExt _) = (remapDir ["build"]) . (-<.> oExt)
staticTargets :: FilePath -> StaticFileMapping a -> Action [FilePath]
staticTargets dir sfm = (map $ staticInputToOutput sfm) <$> staticInputs dir sfm
rules :: FilePath -> StaticFileMapping a -> Rules ()
rules dir sfm@(StaticFileMapping _ _ process) = join $ mconcat . (map buildInputRule) <$> staticInputs dir sfm
where buildInputRule :: FilePath -> Rules ()
buildInputRule input = (staticInputToOutput sfm input) %> (process input)
That way I can define a mapping for each input type (.coffee -> .js
, .svg -> .png
) and so on, with only a tiny amount of code implementing the transformation for each. And it almost works.
But it seems impossible to go from (Action a)
to Rules _
without throwing the value inside the Action
away first, as far as I can tell.
Is there a function with type (Action a) -> (a -> Rules ()) -> Rules ()
or (Action a) -> (Rules a)
? Can I implement either one myself, or do I need to modify the library's code?
Or is this entire approach hare-brained and I should take some other route?