
I think the API for hooks is in need of an overhaul. It has a few problems: 1. it isn't extensible. When a new command is added, typically all the Setup.hs scripts break because they haven't hooked then new command. 2. it isn't composable. It ought to be easy to augment PackageDescription in Setup.hs, but it isn't: to do it right, you have to modify every hook. 3. It's too complicated. I'm sure we don't need all those pre- and post- hooks. 4. tools that build on Cabal (e.g. cabal-rpm) don't work with hooks. If your Setup.hs uses hooks to modify the PackageDescrption, then cabal-rpm won't see the modifications. I can fix 1-3, but 4 is more of a design problem. I'll outline a possible partial solution to 4 later, however. Anyway, here's the basic idea. A common thing to want to do in Setup.lhs is to modify the PackageDescription, so we provide a way to do that: modifyPackageDescription :: (PackageDescription -> IO PackageDescription) -> UserHooks -> UserHooks modifyPackageDescriptionPostConf :: (PackageDescription -> LocalBuildInfo -> IO PackageDescription) -> UserHooks -> UserHooks modifyPackageDescription supplies a function that is run before every command, to modify the existing PackageDescription, and it can do IO. modifyPackageDescriptionPostConf is similar, except that it does not apply to the configure command, and it gets to see the LocalBUildInfo. These mostly subsume all the preHooks. For example, modifyPackageDescriptionPostConf can be used to read the results of the autoconf script. (We'll also need to provide a way to merge a new BuildInfo with the existing PackageDescription). The good thing about this is it's extensible and composable. Adding more commands to Cabal won't break Setup.lhs scripts that use these combinators. This could also help us solve problem (4) above: Cabal can provide a way to output the modified PackageDescription to a file, that can be read in by cabal-rpm. For example, "cabal-setup descr" could output the real PackageDescription. We might still want to hook the real commands, however. So let's look at simplifying the UserHooks type: type ConfHook = Args -> ConfigFlags -> PackageDescription -> IO LocalBuildInfo type Hook a = Args -> a -> PackageDescription -> LocalBuildInfo -> IO () data Hooks = Hooks { confHook :: ConfHook, postConfHook :: Hook ConfigFlags buildHook :: Hook BuildFlags, makefileHook :: Hook MakefileFlags, cleanHook :: Hook CleanFlags, copyHook :: Hook CopyFlags, installHook :: Hook InstallFlags, sdistHook :: Hook SDistFlags, registerHook :: Hook RegisterFlags, unregisterHook :: Hook UnregisterFlags, haddockHook :: Hook HaddockFlags, pfeHook :: Hook PfeFlags } I've missed out runTests and a few others, but the main idea is that I got rid of most the pre- and post-hooks. The configure command is special, because it doesn't see the LocalBuildInfo, so we also need a postConfHook for doing further actions after configure (e.g. running the autoconf script). Suppose we supply thenHook: thenHook :: Hook a -> Hook a -> Hook a thenHook hook1 hook2 args flags pd lbi = do hook1 args flags pd lbi hook2 args flags pd lbi Then to add a post-hook to the build command you could do this: addPostBuild :: Hook BuildFlags -> Hooks -> Hooks addPostBuild hook hooks = hooks { buildHook = buildHook hooks `thenHook` hook } Alternatively, we could supply addPostBuild, addPreBuild, etc. and hide the representation of the Hooks type completely. Comments? Cheers, Simon

On Tue, Apr 24, 2007 at 09:45:54AM +0100, Simon Marlow wrote:
I think the API for hooks is in need of an overhaul.
I agree.
4. tools that build on Cabal (e.g. cabal-rpm) don't work with hooks. If your Setup.hs uses hooks to modify the PackageDescrption, then cabal-rpm won't see the modifications.
That's something I think you just shouldn't be doing, and hopefully we won't need to after this summer.
Anyway, here's the basic idea. A common thing to want to do in Setup.lhs is to modify the PackageDescription, so we provide a way to do that:
Again, I don't think that'll be true after the configurations stuff is implemented.
thenHook :: Hook a -> Hook a -> Hook a thenHook hook1 hook2 args flags pd lbi = do hook1 args flags pd lbi hook2 args flags pd lbi
Then to add a post-hook to the build command you could do this:
addPostBuild :: Hook BuildFlags -> Hooks -> Hooks addPostBuild hook hooks = hooks { buildHook = buildHook hooks `thenHook` hook }
I think most of the time we would want `thenHooks` (defined in terms of thenHook), e.g. (with the current names) we'd have something like: defaultBuildHooks = simpleBuildHooks `thenHooks` configureBuildBooks where configureBuildBooks might define a confHook (to run ./configure) and a cleanHook (to remove config.log etc). Thanks Ian

Ian Lynagh wrote:
On Tue, Apr 24, 2007 at 09:45:54AM +0100, Simon Marlow wrote:
I think the API for hooks is in need of an overhaul.
I agree.
4. tools that build on Cabal (e.g. cabal-rpm) don't work with hooks. If your Setup.hs uses hooks to modify the PackageDescrption, then cabal-rpm won't see the modifications.
That's something I think you just shouldn't be doing, and hopefully we won't need to after this summer.
Yes, I quite agree. I saw the code in e.g. base/Setup.hs, and noticed how it broke with 'setup makefile', and decided there must be a better way. Certainly configurations are an even better way.
thenHook :: Hook a -> Hook a -> Hook a thenHook hook1 hook2 args flags pd lbi = do hook1 args flags pd lbi hook2 args flags pd lbi
Then to add a post-hook to the build command you could do this:
addPostBuild :: Hook BuildFlags -> Hooks -> Hooks addPostBuild hook hooks = hooks { buildHook = buildHook hooks `thenHook` hook }
I think most of the time we would want `thenHooks` (defined in terms of thenHook), e.g. (with the current names) we'd have something like:
defaultBuildHooks = simpleBuildHooks `thenHooks` configureBuildBooks
where configureBuildBooks might define a confHook (to run ./configure) and a cleanHook (to remove config.log etc).
Right, I can imagine that might be more convenient. So we agree in principle that removing all the pre/post hooks from UserHooks and providing thenHook/thenHooks would be an improvement? It's a bit of a no-brainer refactoring, I might do it when I'm feeling bored sometime. Or maybe Thomas could do it as part of the SOC project? Cheers, Simon
participants (2)
-
Ian Lynagh
-
Simon Marlow