About cabal and compatibility

Isaac Jones ijones at syntaxpolice.org
Sat Dec 10 20:45:43 EST 2005

Robert Dockins <robdockins at fastmail.fm> writes:

> On Saturday 10 December 2005 07:14 pm, you wrote:
>> Robert Dockins <robdockins at fastmail.fm> writes:
> The Happy build system now does two things that aren't your standard build 
> actions:
> 1) It creates module which contains the version string before compilation
> 2) After compilation it runs CPP on a number of template files with various 
> different "-D" options to genreate the parser templates.
> I was messing around with doing these using user hooks and I ended up needing 
> to tie pretty deeply into cabal even for the simple task 1).

What I would like to do is to stabalize an interface one of these
days.  The problem is that, IMO, we need experience with what users
want & need in order to stabalize the interface.  When writing layered
tools like cabal-get, Lemmih had to modify cabal's interface, and when
writing cabal-install, I had to modify the interface.

But I'll definitely look at the Eternal Compatibility thing!

> I have attached my initial attempts so you can see what's happening.
> The user hooks change you are talking about would require a complete rework of 
> my Setup.hs file.  Its only ~130 lines, but then Happy is a pretty small 
> project.

Not at all.  See below.

>> I only know of one or two packages that use the hooks.  Do you know of
>> backward compatibility problems that cabal has caused?
> No, this is all speculation currently.
>> BTW, I just added a "cabal-version" field to cabal so that if a
>> package requires a particular version of cabal, it can say so.
> Well, cabal the library already has to be invoked before the package file is 
> even read!  If the Setup.hs doesn't typecheck because the cabal interfaces 
> have changed, you won't even get that far. 

True enough, It's mainly useful for parsing the .cabal file.  Setup
can't use this information for compiling, but humans can use it to
understand compile failures, and cabal-get can use it.

>> Further, my grand plan is that once stuff gets into hackage, we can
>> try making modifications and seeing if it breaks any packages, and if
>> so, offer patches to those package authors (since it's probably eaiser
>> for cabal hackers to write such patches than most package authors).
> That depends on the complexity of the build system.  In my experience, just 
> trying to figure out what a build system is doing can be pretty difficult.  I 
> can't imagine you want to undertake the maintaince of other people's build 
> systems.

I'm certainly not talking about maintaining them, but usually if you
modify an interface, the kinds of changes you make are mechanical and

> OTOH, if Cabal is only aiming at pretty simple projects, this may never be an 
> issue.

The plan with cabal was to handle simple projects at first, and add
more complex projects as we go along.  That's basically happening, and
my hope is that we can fix the "simple" interface sooner, and the more
complex interface later.

> import Data.Version
> import Control.Exception
> import System.Cmd
> import System.IO
> import System.Exit
> import System.Directory
> import Distribution.Setup
> import Distribution.Simple
> import Distribution.Simple.Utils
> import Distribution.Simple.LocalBuildInfo
> import Distribution.PackageDescription

It would be nice if you used qualified imports so I could see exactly
what it is that you need from cabal.  Also you'll get better error
messages if things disappear.

> main = do
>   descFile <- defaultPackageDesc
>   desc <- readPackageDescription descFile
>   let ver = (pkgVersion (package desc))
>   defaultMainWithHooks (mkHooks desc ver)
> mkHooks :: PackageDescription
>         -> Version
>         -> UserHooks
> mkHooks desc ver = 
>   defaultUserHooks
>   { readDesc  = return (Just desc)
>   , postConf  = doPostConf ver
>   , postBuild = createTemplates
>   , postClean = cleanDerivedFiles
>   }

With the proposed change, all you have to do is something basically
like this, not reworking the whole build system:

>   defaultUserHooks
>   { readDesc  = return (Just desc)
>   , confHook  = (confHook defaultUserHooks) >> doPostConf ver
>   , buildHook = (buildHook defaultUserHooks) >> createTemplates
>   , cleanHook = (cleanHook) >> cleanDerivedFiles
>   }


> createVersionModule :: Version -> IO ()
> createVersionModule version = do
>   h <- openFile "src/Version.hs" WriteMode
>   hPutStr h "module Version where\n"
>   hPutStr h ("version = \""++(showVersion version)++"\"")
>   hClose h

That's interesting.  I was recently thinking of generating something
like CabalInfo.hs which has information like the PackageDescription
and the LocalBuildInfo.  You would turn on this feature w/ the .cabal
file.  I'm not sure if any of the information is useful except for the
version number, though.

We could also add -DPACKAGE_VERSION or something to the cpp line.
That would be pretty easy.


>        perlRE = "s/^#\\s+(\\d+)\\s+(\\\"[^\\\"]*\\\")/{-# LINE \\1 \\2 #-}/g;s/\\$$(Id:.*)\\$$/\\1/g"

> 	   rawSystem "perl" ["-pi.hspp","-e",perlRE,file]


/me runs away ;)

But seriously folks, you should check out the new (experimental!)
"Program" interface in the CVS / darcs HEAD.  The nice thing about it
is you can add perl as a Program and configure will find it, and users
can say: ./setup configure --with-perl=/my/special/perl.



More information about the Libraries mailing list