Cabal: Conditional code and dependencies

It would be useful to have mechanisms in Cabal like these: (1) Optional dependencies: "if package foo-1.0 is available, then my program depends on it; otherwise, my program does not depend on it." (see also #3 below). Special case: "my program would prefer package foo-1.2, but if that is not available, I will take any version of foo." Use cases: (a) A tool has an optional "XML export" feature that requires HaXml. If HaXml is available, then the XML export feature will be built. Otherwise, the tool will be built without it. (b) A program requires some unix-specific code (package unix) or windows-specific code (package win32) depending on what operating system the program is built for. (c) Cabal depends on HUnit if DEBUG is set, but it doesn't depend on HUnit if DEBUG is not set. (The dependency isn't controlled by the existence of a package, but by a configuration option.) (c) Let's say I send in a patch that adds a "getAppBinaryDirectory" function to System.Directory, and this patch makes it into version 1.1 of the base package. Then, Cabal 1.3 can say "If the base package version is 1.1, then we want it because it defines getAppBinaryDirectory, otherwise, we will just use base-1.0 and will provide our own implementation of that function." (2) "process this stanza if package foo-1.1 is available," etc. Use cases: (a) A tool comes in a command line version and a GUI version. The command-line version can be used independently of the existence of the GUI version. The GUI version requires wxHaskell. So, we want to say "build the GUI executable if wxHaskell is available, otherwise skip it." (b) A tool has a test suite that requires HUnit. If HUnit isn't available, then the test suite should not be built. (3) It would be useful if Cabal/GHC/Hugs/etc. #defined symbols for installed packages. This would allow us to write: module My.Program.Compat.Lib(foo1, foo2,foo3) #if __PACKAGE_foo__ >= 110 -- Is package foo-1.1 or later available? import Foo(foo1,foo2,foo3) #else foo1 = .... foo2 = .... foo3 = ... #endif Consider the following fragment from Cabal's Distribution.Compat.Directory. The Cabal authors know that the version of System.Directory that is in GHC before 6.02 includes the features Cabal needs. However, other Haskell implementations have no such version test: #if !__GLASGOW_HASKELL__ || __GLASGOW_HASKELL__ > 602 import System.Directory #else /* to end of file... */ ... #endif Instead, we could have: #if __PACKAGE_base__ >= 100 import System.Directory #else /* to end of file... */ getAppUserDataDirectory = .... #endif #if __PACKAGE_base__ < 110 getAppBinaryDirectory = ... #endif Regards, Brian

On Thu, Jul 21, 2005 at 12:32:21AM -0500, Brian Smith wrote:
(3) It would be useful if Cabal/GHC/Hugs/etc. #defined symbols for installed packages. This would allow us to write:
module My.Program.Compat.Lib(foo1, foo2,foo3) #if __PACKAGE_foo__ >= 110 -- Is package foo-1.1 or later available? import Foo(foo1,foo2,foo3) #else
Perhaps this is something cpphs could provide? #if cabal(foo >= 1.1.0) ... (or whatever syntax you like). It can import the relevant stuff from Distribution.* to do the version checking bit. It would probably need to take a command line parameter of some form that allowed it to know what was being compiled with. Thanks Ian

On 2005-07-21, Brian Smith
(b) A program requires some unix-specific code (package unix) or windows-specific code (package win32) depending on what operating system the program is built for.
I just ran into this problem with making MissingH work on Windows. I finally wound up providing a batch file for Windows users that hacks the .cabal file, which then can be used to build the package on Windows. Ugly, but works. -- John
participants (3)
-
Brian Smith
-
Ian Lynagh
-
John Goerzen