Dynamic package information with Setup.hs

I'm writing a cabal package that provides bindings to a C library. I've written a shell script that will download and build this C library to a subdirectory of the user's HOME(~/.cabal-tmp/{lib,include}). Currently I have the following Setup.hs that automatically runs the script before installing: import Distribution.Simple import Distribution.Simple.Setup import Distribution.PackageDescription import System.Process main :: IO () main = defaultMainWithHooks simpleUserHooks { preConf = buildDeps } buildDeps :: Args -> ConfigFlags -> IO HookedBuildInfo buildDeps _ _ = do rawSystem "sh" ["./scripts/build-deps.sh"] return emptyHookedBuildInfo I've tried adding the following lines: extra-lib-dirs: ${HOME}/.cabal-tmp/lib include-dirs: ${HOME}/.cabal-tmp/include But it complains about syntax errors and I found no other way to expand the user's HOME directory in the .cabal file. If I use relative paths in the 'extra-lib-dirs' an error is reported(cabal 1.16). Full paths are also needed for linking against this package as ghc needs to know the linker flags for the native library. Obviously I cant know the full path the library will be installed in advance, as I dont know the HOME directory of the user installing the package until the Setup.hs script is running. My question: How can I use the Setup.hs hooks to update those two fields dynamically?

Hi Thiago,
I've written a shell script that will download and build this C library to a subdirectory of the user's HOME(~/.cabal-tmp/{lib,include}).
please don't do that. It's notoriously hard to get this use case right so that it works for everybody. Some people may want that library built as a shared object; others may want it with profiling and/or debug information. The next guy may want that library compiled with a different version of GCC than the one GHC uses by default. Others may want to link bindings to a copy of that library that's installed in their system (under a path that you cannot guess). What you should do is to add Extra-Libraries: my-external-library to your Cabal file and trust that the user specifies appropriate flags at configure time to ensure that the compiler can find it if necessary. You can distribute a shell script that tries to build the C library and the Haskell library with convenient defaults, i.e. your script should call cabal configure --extra-include-dirs=PATH --extra-lib-dirs=PATH with appropriate paths after having built the C code, but please make sure that your Haskell package works fine for people who want to build the C library themselves without using your script. Take care, Peter

On Thu, Nov 21, 2013 at 5:10 PM, Peter Simons
You can distribute a shell script that tries to build the C library and the Haskell library with convenient defaults, i.e. your script should call
cabal configure --extra-include-dirs=PATH --extra-lib-dirs=PATH
with appropriate paths after having built the C code, but please make sure that your Haskell package works fine for people who want to build the C library themselves without using your script.
Peter, My reason for taking this route is to simplify the installation by making the C library a transparent part of the package. This is similar to the haskell bindings to zlib( the difference is that it bundles zlib source code in the 'cbits' directory since zlib build is simple everything just works). This is common in package managers for other platforms(node.js, python) as it simplifies installation by users that have little experience with building C packages. The goal is to have a generic Setup.hs file that I can use for packaging haskell bindings to libraries that have non-trivial build procedures, and still have everything working after a simple 'cabal install LIB' With that said, I agree that allowing customization by advanced users is essential. Like you suggested, I already use the 'extra-libraries' field without specifying extra-lib-dirs/include-dirs. I still would like to follow the automatic build route with the following changes: - The Setup.hs file will only invoke the download/build script if the --extra-lib-dirs/--include-dirs weren't passed to cabal(I believe the Args argument for the preConf hook is suitable for that) - An additional flag could be provided for users wanting to build against the system's version of the library. This should hide the installation details by providing reasonable defaults (like a library version that is guaranteed to work with the binding) while still giving full control to advanced users. What do you think?

you should look at libs that have c libs embedded in them approach it. a
good simple example would be lz4hs. Its really quite simple and doesn't
require crazy hacks
On Thu, Nov 21, 2013 at 4:25 PM, Thiago Padilha
On Thu, Nov 21, 2013 at 5:10 PM, Peter Simons
wrote: You can distribute a shell script that tries to build the C library and the Haskell library with convenient defaults, i.e. your script should call
cabal configure --extra-include-dirs=PATH --extra-lib-dirs=PATH
with appropriate paths after having built the C code, but please make sure that your Haskell package works fine for people who want to build the C library themselves without using your script.
Peter,
My reason for taking this route is to simplify the installation by making the C library a transparent part of the package. This is similar to the haskell bindings to zlib( the difference is that it bundles zlib source code in the 'cbits' directory since zlib build is simple everything just works).
This is common in package managers for other platforms(node.js, python) as it simplifies installation by users that have little experience with building C packages.
The goal is to have a generic Setup.hs file that I can use for packaging haskell bindings to libraries that have non-trivial build procedures, and still have everything working after a simple 'cabal install LIB'
With that said, I agree that allowing customization by advanced users is essential. Like you suggested, I already use the 'extra-libraries' field without specifying extra-lib-dirs/include-dirs.
I still would like to follow the automatic build route with the following changes:
- The Setup.hs file will only invoke the download/build script if the --extra-lib-dirs/--include-dirs weren't passed to cabal(I believe the Args argument for the preConf hook is suitable for that) - An additional flag could be provided for users wanting to build against the system's version of the library.
This should hide the installation details by providing reasonable defaults (like a library version that is guaranteed to work with the binding) while still giving full control to advanced users.
What do you think? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 22 November 2013 07:10, Peter Simons
Hi Thiago,
I've written a shell script that will download and build this C library to a subdirectory of the user's HOME(~/.cabal-tmp/{lib,include}).
please don't do that. It's notoriously hard to get this use case right so that it works for everybody. Some people may want that library built as a shared object; others may want it with profiling and/or debug information. The next guy may want that library compiled with a different version of GCC than the one GHC uses by default. Others may want to link bindings to a copy of that library that's installed in their system (under a path that you cannot guess).
Not to mention that it doesn't work well for people wanting to build it on a distro level (or even to compile and distribute across multiple machines).
What you should do is to add
Extra-Libraries: my-external-library
to your Cabal file and trust that the user specifies appropriate flags at configure time to ensure that the compiler can find it if necessary.
You can distribute a shell script that tries to build the C library and the Haskell library with convenient defaults, i.e. your script should call
cabal configure --extra-include-dirs=PATH --extra-lib-dirs=PATH
with appropriate paths after having built the C code, but please make sure that your Haskell package works fine for people who want to build the C library themselves without using your script.
Take care, Peter
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com
participants (4)
-
Carter Schonwald
-
Ivan Lazar Miljenovic
-
Peter Simons
-
Thiago Padilha