
Hello, Guys I am trying to cabalize HSQL. There is a simple ./configure script which performs some simple checks. Now I would like to perform these checks from Setup.lhs using Cabal hooks. The hooks API looks a little bit strange for me. The preConf hooks returns (Maybe PackageDescription) which after that is merged with the basic description. The Setup.buildinfo file contains only the hooked description instead of merged one. The parser requires to have package name and version, in order to properly parse the description. I need to return the right name and version from preConf hook to satisfy this restriction. I can't do this without re-reading the original description from Setup.description. Isn't it simpler to change the hooks type to something like: PackageDescription -> IO PackageDescription where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code. Cheers, Krasimir

On Tue, Jan 11, 2005 at 02:33:52PM +0200, Krasimir Angelov wrote:
I am trying to cabalize HSQL. There is a simple ./configure script which performs some simple checks. Now I would like to perform these checks from Setup.lhs using Cabal hooks. The hooks API looks a little bit strange for me. The preConf hooks returns (Maybe PackageDescription) which after that is merged with the basic description. The Setup.buildinfo file contains only the hooked description instead of merged one. The parser requires to have package name and version, in order to properly parse the description. I need to return the right name and version from preConf hook to satisfy this restriction. I can't do this without re-reading the original description from Setup.description.
I think these checks are off at the moment. But you can get the effect you're after by using main = defaultMainWithHooks defaultUserHooks can't you? (cf fptools/libraries/X11) There's a need to do something different under Windows, though.
Isn't it simpler to change the hooks type to something like:
PackageDescription -> IO PackageDescription
where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code.
This relates to the discussion on package description structure. With this interface, it would be possible for the preConf hook to alter fields that are supposed to be fixed.

On Tue, 11 Jan 2005 12:49:11 +0000, Ross Paterson
I think these checks are off at the moment. But you can get the effect you're after by using
I still get "*** Exception: Line 1: Parse of field 'name' failed" error if name field from Setup.buildinfo is empty.
main = defaultMainWithHooks defaultUserHooks
can't you? (cf fptools/libraries/X11) There's a need to do something different under Windows, though.
My Setup.lhs is something like: #! runghc \begin{code} import Distribution.Simple import Distribution.Setup import Distribution.PackageDescription main = defaultMainWithHooks hooks hooks = defaultUserHooks { preConf = hsql_configure } hsql_configure :: [String] -> ConfigFlags -> IO (Maybe PackageDescription) hsql_configure args flags = do let pkg_descr = emptyPackageDescription { ccOptions = ... } writePackageDescription hookedPackageDesc pkg_descr return (Just pkg_descr) \end{code} It fails because name and version fields of the returned package description are empty. To work arround I need to use: hsql_configure :: [String] -> ConfigFlags -> IO (Maybe PackageDescription) hsql_configure args flags = do pkg_descr <- readPackageDescription "Setup.description" let pkg_descr' = pkg_descr { ccOptions = ... } writePackageDescription hookedPackageDesc pkg_descr' return (Just pkg_descr')
Isn't it simpler to change the hooks type to something like:
PackageDescription -> IO PackageDescription
where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code.
This relates to the discussion on package description structure. With this interface, it would be possible for the preConf hook to alter fields that are supposed to be fixed.
The library can check whether some fields are equal in the original description and in the updated description. Cheers, Krasimir

On Wed, Jan 12, 2005 at 12:06:11AM +0200, Krasimir Angelov wrote:
I still get "*** Exception: Line 1: Parse of field 'name' failed" error if name field from Setup.buildinfo is empty.
Ah, writePackageDescription is writing an empty name field. The parser doesn't mind if the name field is missing, but does if it's present and empty. It was Isaac's original plan to write to the hooked description, but things have evolved a bit, and that's not workable with the current setup, as the hook doesn't have access to the original package description. But maybe the unmodified defaultUserHooks will do what you want. Suppose you have Setup.buildinfo.in containing just cc-options: @CPPFLAGS@ ld-options: @LDFLAGS@ and add Setup.buildinfo to AC_CONFIG_FILES. Then the preConf of defaultUserHooks will run configure, which will generate Setup.buildinfo, and the pre-hook will then read that to get the extra fields to merge with the package description. All the other pre-hooks will also read Setup.buildinfo for merging in the same way. There's no need to store a modified package description.

To recap, the current setup in Distribution.Simple with the default hooks goes like this: - the package description file (formerly Setup.description, now <package>.cabal) can contain values for all the fields in PackageDescription, but it should be system-independent, and not modified by the Cabal script. - system-dependent information to override some of these fields can be put in a second file (Setup.buildinfo) that can be created by the preConf step (e.g. by running ./configure). However this shouldn't override certain static fields, including name and version. Prehooks read this second file and merge it with the package description for use by the various actions. On Tue, Jan 11, 2005 at 02:33:52PM +0200, Krasimir Angelov wrote:
I am trying to cabalize HSQL. There is a simple ./configure script which performs some simple checks. Now I would like to perform these checks from Setup.lhs using Cabal hooks. The hooks API looks a little bit strange for me. The preConf hooks returns (Maybe PackageDescription) which after that is merged with the basic description. The Setup.buildinfo file contains only the hooked description instead of merged one. The parser requires to have package name and version, in order to properly parse the description. I need to return the right name and version from preConf hook to satisfy this restriction. I can't do this without re-reading the original description from Setup.description.
Krasimir's initial request (getting values from ./configure used via Setup.buildinfo) can be handled by defaultUserHooks, but in off-line discussions Krasimir has said that he also wants to be able to put values supplied on the command line into Setup.buildinfo. That doesn't work at present, because the only way to create Setup.buildinfo from inside the Cabal script is to use writePackageDescription, and that needs a package name and version to produce something that readPackageDescription can read, and moreover unionPackageDescription wants them to be the same as the original ones.
Isn't it simpler to change the hooks type to something like:
PackageDescription -> IO PackageDescription
where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code.
It replaces the need for merging with the need to check that they haven't changed the fields they weren't supposed to. Other alternatives: - have the prehooks return a type other than PackageDescription, containing only the fields they're allowed to override. That means a different parser for buildinfo files. - introduce a variant of writePackageDescription that only writes the fields they're allowed to override (or only writes non-empty fields).

Ross Paterson
On Tue, Jan 11, 2005 at 02:33:52PM +0200, Krasimir Angelov wrote:
Isn't it simpler to change the hooks type to something like:
PackageDescription -> IO PackageDescription
where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code.
It replaces the need for merging with the need to check that they haven't changed the fields they weren't supposed to.
That's not too bad actually; definitely easier than merging, and conceptually simpler than defining either an AbstractPackageDescription (so we can actually tell when they've over-ridden a field) or a new buildinfo type. Though the advantage of the buildinfo type is that the inability to over-ride is enforced by the typechecker.
Other alternatives: - have the prehooks return a type other than PackageDescription, containing only the fields they're allowed to override. That means a different parser for buildinfo files. - introduce a variant of writePackageDescription that only writes the fields they're allowed to override (or only writes non-empty fields).
This second one is also quite easy and not a bad idea in general. peace, isaac

On Wed, 12 Jan 2005 21:32:12 -0800, Isaac Jones
Ross Paterson
writes: On Tue, Jan 11, 2005 at 02:33:52PM +0200, Krasimir Angelov wrote:
Isn't it simpler to change the hooks type to something like:
PackageDescription -> IO PackageDescription
where the argument is the original description and the result is the possible updated one? This avoids the need of merging and simplifies the library code.
It replaces the need for merging with the need to check that they haven't changed the fields they weren't supposed to.
That's not too bad actually; definitely easier than merging, and conceptually simpler than defining either an AbstractPackageDescription (so we can actually tell when they've over-ridden a field) or a new buildinfo type.
Though the advantage of the buildinfo type is that the inability to over-ride is enforced by the typechecker.
Other alternatives: - have the prehooks return a type other than PackageDescription, containing only the fields they're allowed to override. That means a different parser for buildinfo files. - introduce a variant of writePackageDescription that only writes the fields they're allowed to override (or only writes non-empty fields).
This second one is also quite easy and not a bad idea in general.
There is also an another solution which I proposed in our off-line discussions with Ross. The hook can return [(String,BuildInfo)] where the first element of the pair is the library/executable name to which to the BuildInfo is related. The drawback here is that the field exposedModules is in BuildInfo type but we would like to keep this list constant over all platforms. My solution is to make a slight refactoring. In the BuildInfo have three fields exposedModules, hiddenModules and executableModules. The former two fields are used only for libraries while the latter is used only for executables. It is a little bit strange to have fields which are used only in some cases. I propose to introduce a new type: data Library = Library { exposedModules :: [String], buildInfo :: BuildInfo } deriving (Show, Read, Eq) The nice thing here is that now we have symmetry between executables and libraries. The former is represented from Executable type and the letter is represented from Library type. The executableModules and hiddenModules fields can be merged. In some sense the main module of the executable is like the exposed modules of the libraries but in both cases there can exists other modules which are required in order to build. These extra modules we can keep in hiddenModules field. This avoids the need to have fields which are used only for executables or only for libraries in the BuildInfo. After this refactoring BuildInfo will contain only system dependent values which the hook can change. The (PackageDescription -> IO PackageDescription) solution is simpler but as you said the library must check whether the hook is changing only the allowed hooks. I will be happy with either of the above solutions and probably tomorrow I will have enough time to write some code but we need to make a choice. Cheers, Krasimir

Krasimir Angelov
There is also an another solution which I proposed in our off-line discussions with Ross. The hook can return [(String,BuildInfo)] where the first element of the pair is the library/executable name to which to the BuildInfo is related. The drawback here is that the field exposedModules is in BuildInfo type but we would like to keep this list constant over all platforms. My solution is to make a slight refactoring. In the BuildInfo have three fields exposedModules, hiddenModules and executableModules. The former two fields are used only for libraries while the latter is used only for executables. It is a little bit strange to have fields which are used only in some cases. I propose to introduce a new type:
The refactoring you propose for buildinfo and packagedescription are probably a good thing outside the context of the hooks. I'll work on that late tonight if you can wait, if you can't wait then go ahead and do it. I have to think about the [(String, Buildinfo)] idea and the PackageDescription -> IO PackageDescription ideas. I'll let you know ASAP. peace, isaac

It does seem bizarre to supply an interface that lets users change all the fields, and then check that they haven't used it. On Wed, Jan 12, 2005 at 09:32:12PM -0800, Isaac Jones wrote:
Though the advantage of the buildinfo type is that the inability to over-ride is enforced by the typechecker.
and the type makes the usage clear.
participants (4)
-
Isaac Jones
-
Krasimir Angelov
-
Ross Paterson
-
ross@soi.city.ac.uk