
Hi Ross, I'm definitely happy to add more optional fields to the package description file. I knew that the need for such would come up. But the interface to cabal is the required description file fields and the required Setup arguments. How do you maintain that interface if you're generating the required fields of the description file with the Setup program itself? (I'm assuming that you are having Setup configure call the ./configure script or something?) The idea behind making the cabal description file so easy to parse is that other tools can get information like the package name and version from the cabal description file, rather than the description file sucking it in from someplace else. I believe this is what the Debian package generation tools do, for instance. Where do the PACKAGE_NAME, etc. values come from, BTW? A hope with the cabal was to be able to have a Setup.description file at the top level of something like a tarball. Layered tools like Hackage know where it is and how to parse it. If you don't have it in the source tarball, but rather generate it during build time, that breaks this model. The simple build infrastructure is not meant to build everything, though it would be nice if it could build most things without the help of Make and friends. The key is the interface to cabal which allows for layered tools like Hackage and the Debian package generator to come about. You can always use Haskell itself in the Setup file to find the list of modules or what-have-you and call the functions exposed by the simple build infrastructure. That's why the Setup program is a full-blown Haskell program. peace, isaac

On Wed, Dec 01, 2004 at 09:21:33PM -0800, Isaac Jones wrote:
But the interface to cabal is the required description file fields and the required Setup arguments. How do you maintain that interface if you're generating the required fields of the description file with the Setup program itself? (I'm assuming that you are having Setup configure call the ./configure script or something?)
The idea behind making the cabal description file so easy to parse is that other tools can get information like the package name and version from the cabal description file, rather than the description file sucking it in from someplace else. I believe this is what the Debian package generation tools do, for instance.
I suppose what I'd like is a separation of the build information from the basic package description, with the possibility of the configure step producing the build info to be used by the simple build infrastructure. Having hardwired build info is very limiting.
Where do the PACKAGE_NAME, etc. values come from, BTW?
They're set by AC_INIT in configure.ac. That was Sven's concern, but you make a strong case for it originating from the package description. (Nothing to stop configure getting it from there, I imagine.) I'm more concerned about the build information: C compiler options, libraries, include files, frameworks, etc. And the hidden module list, possibly the exposed ones too (though maybe you want that available to your tools).
A hope with the cabal was to be able to have a Setup.description file at the top level of something like a tarball. Layered tools like Hackage know where it is and how to parse it. If you don't have it in the source tarball, but rather generate it during build time, that breaks this model.
OK, so this description will be there whatever build system you use. The build information would be only for Simple.
The simple build infrastructure is not meant to build everything, though it would be nice if it could build most things without the help of Make and friends. The key is the interface to cabal which allows for layered tools like Hackage and the Debian package generator to come about.
I'm not terribly interested in make-based builds, because they're unlikely to be portable across implementations. So I'd like the simple build to be as useful as possible, and it could cover the vast majority of cases if it had a hook at the configure stage to generate the build info. (Not necessarily cpp, if that makes you ill; Einar's suggestion of using make for this purpose could also work, and there are other possibilities.)
You can always use Haskell itself in the Setup file to find the list of modules or what-have-you and call the functions exposed by the simple build infrastructure. That's why the Setup program is a full-blown Haskell program.
Writing a Setup program is also unattractive, both because of portability worries and the need to keep it up-to-date in the future.

Ross Paterson
I suppose what I'd like is a separation of the build information from the basic package description, with the possibility of the configure step producing the build info to be used by the simple build infrastructure. Having hardwired build info is very limiting.
OK.
Where do the PACKAGE_NAME, etc. values come from, BTW?
They're set by AC_INIT in configure.ac. That was Sven's concern, but you make a strong case for it originating from the package description. (Nothing to stop configure getting it from there, I imagine.)
I'm more concerned about the build information: C compiler options, libraries, include files, frameworks, etc. And the hidden module list, possibly the exposed ones too (though maybe you want that available to your tools).
My hope is to eventually just have the exposed modules list on there (and available to layered tools) and have it determine the dependencies. Same with the main modules for executables. It would be nice if the exposed modules list were available to the tools, but that's not a requirement.
I'm not terribly interested in make-based builds, because they're unlikely to be portable across implementations. So I'd like the simple build to be as useful as possible, and it could cover the vast majority of cases if it had a hook at the configure stage to generate the build info. (Not necessarily cpp, if that makes you ill; Einar's suggestion of using make for this purpose could also work, and there are other possibilities.)
You can always use Haskell itself in the Setup file to find the list of modules or what-have-you and call the functions exposed by the simple build infrastructure. That's why the Setup program is a full-blown Haskell program.
Writing a Setup program is also unattractive, both because of portability worries and the need to keep it up-to-date in the future.
What I mean is that you can have two files, Setup.description, and yourgenerateddescription.in. The former has the required fields and the later has the build information, then main would be something like this: main = do e <- doesFileExist "yourgenerateddescription" when (not e) (system "autoconf yourgenerateddescription.in") desc <- readPackageDescription "yourgenerateddescription" defaultMainNoRead desc So the only issue here is that you have a bit of a configure step no matter what commands they use. It would indeed be nice to have hooks for the commands. I'm a bit worried about making the Distribution.Simple interface complex, but I wanted to add hooks for "test" and "postinst" anyway. The problem is, do we need all of: {pre,post}{configure,build,install}, test? In addition to the defaultMain functions we have, we would provide: defaultMainNoReadFuns :: UserFunctions -> PackageDescription -> IO () defaultMainFuns :: UserFunctions -> IO () Where: data UserFunctions { runTests :: Maybe (IO ()), -- ^Used for './setup test' postInst :: Maybe (IO ()) -- ^guaranteed to be run on target preInst :: Maybe (IO ()) -- ^not guaranteed to be run on target ... } And a typical main might look like: main = do defaultMainFuns (emptyUserFuns{preConfigure=myAutoConfFun}) Hmm. This doesn't quite do what you want it to if preConfigure returns ()... Maybe it could return a (Maybe PackageDescription). Any thoughts here on how to make useful hooks? BTW, I was toying with the idea of using the config file parser from John Goerzen's MissingH in the Cabal, and provide it for Setup.lhs authors to write and parser their own configuration-related files. peace, isaac

On Tue, Dec 07, 2004 at 09:50:58AM -0800, Isaac Jones wrote:
My hope is to eventually just have the exposed modules list on there (and available to layered tools) and have it determine the dependencies. Same with the main modules for executables. It would be nice if the exposed modules list were available to the tools, but that's not a requirement.
Another possibility is to have Exposed-Modules in the package description, and a field in the build info listing modules from that list to be excluded from a build on this system.
What I mean is that you can have two files, Setup.description, and yourgenerateddescription.in. The former has the required fields and the later has the build information, then main would be something like this:
main = do e <- doesFileExist "yourgenerateddescription" when (not e) (system "autoconf yourgenerateddescription.in") desc <- readPackageDescription "yourgenerateddescription" defaultMainNoRead desc
How about using optional files as the hooks, something like configure pkg_descr ... = configureExists <- fileExists "configure.lhs" when configureExists $ rawSystem "runhaskell" ["configure.lhs"] buildInfoExists <- fileExists "yourgenerateddescription" buildInfo <- if buildInfoExists then readBuildInfo "yourgenerateddescription" else return (defaultBuildInfo pkg_descr) ... (You'd probably also want some way for configure.lhs to indicate failure.) I'd also like Setup.lhs itself to be optional, defaulting to the simple one, which can be precompiled.
So the only issue here is that you have a bit of a configure step no matter what commands they use. It would indeed be nice to have hooks for the commands. I'm a bit worried about making the Distribution.Simple interface complex, but I wanted to add hooks for "test" and "postinst" anyway. The problem is, do we need all of: {pre,post}{configure,build,install}, test?
There can be different tests before and after installation, too, and the test would need some way of indicating success or failure. I imagine you have a plan to have Hackage plug into an autobuilder so the package list can show what versions of what compilers a package works with -- that would be very useful, not least in flagging abandoned packages.
BTW, I was toying with the idea of using the config file parser from John Goerzen's MissingH in the Cabal, and provide it for Setup.lhs authors to write and parser their own configuration-related files.
I'd be keener to have specified file formats with corresponding parsers in the library. Lengthy Setup.lhs scripts will be a maintainance headache, I think.

What about this interface for user-supplied command hooks. The Bool in "test" is for whether or not they have provided the --post-inst flag or something. This is so they can have different test suites depending on whether or not the package has been installed. For each of the pre-functions, a Maybe PackageDescription is returned. If Nothing, then it gets the description from the file or the default description you passed in. If (Just p), then it uses the description returned by the pre-functions. The post-commands return ExitCode, and if they are failure codes, then that command will die with that code. data UserFunctions = UserFunctions { runTests :: Bool -> IO ExitCode, -- ^Used for './setup test {--post-inst}' preConf :: IO (Maybe PackageDescription), postConf :: IO ExitCode, preBuild :: IO (Maybe PackageDescription), postBuild :: IO ExitCode, preClean :: IO (Maybe PackageDescription), postClean :: IO ExitCode, preCopy :: IO (Maybe PackageDescription), postCopy :: IO ExitCode, preInst :: IO (Maybe PackageDescription), postInst :: IO ExitCode, -- ^guaranteed to be run on target preSDist :: IO (Maybe PackageDescription), postSDist :: IO ExitCode, preReg :: IO (Maybe PackageDescription), postReg :: IO ExitCode, preUnreg :: IO (Maybe PackageDescription), postUnreg :: IO ExitCode } I don't particularly like the idea of: {{system "runhaskell" ["postinst.hs"]}} because it seems like a less elegant IO ExitCode. runhaskell doesn't exist, and it relies on more moving parts. peace, isaac

On Wed, Dec 08, 2004 at 10:42:26PM -0800, Isaac Jones wrote:
What about this interface for user-supplied command hooks. [...]
For each of the pre-functions, a Maybe PackageDescription is returned. If Nothing, then it gets the description from the file or the default description you passed in. If (Just p), then it uses the description returned by the pre-functions.
I'm not sure what's going on here. It seems only preConf needs to return anything, and that shouldn't be the whole PackageDescription (since you want part of that static), just the build information.
I don't particularly like the idea of: {{system "runhaskell" ["postinst.hs"]}} because it seems like a less elegant IO ExitCode. runhaskell doesn't exist, and it relies on more moving parts.
Sure it exists -- I read about it in the spec.
participants (4)
-
Isaac Jones
-
Isaac Jones
-
Ross Paterson
-
ross@soi.city.ac.uk