Three questions about patch to cabal

Jeremy Shaw jeremy.shaw at linspireinc.com
Mon Jul 17 20:45:13 EDT 2006


At Thu, 13 Jul 2006 12:26:22 +0100,
Simon Marlow wrote:
> 
> Jeremy Shaw wrote:
> 
> >  (1) Flag sanity checking
> > 
> >   Not all combinations of flags are sensible. For example, we can
> >   already specify:

> There's another restriction I know of: if the code uses Template Haskell, then 
> --enable-library-vanilla will always be required.  Since the extensions used are 
> all listed in the .cabal file, checking this will be easy.

Hrm, that puts me back in the same situation I am in now -- not having
a good way to split the profiling libraries into a separate package.

I have written up some of my thoughts below. I would love to hear
opinions from any interested parties, such as compiler writers,
package maintainers, end users, etc.

Goals
=====

 Overall Goal
 ------------

 My overall goal is to add some flags to Cabal that will make it
 easier for package maintainers to provide several variations of the
 same library in separate packages. For example, separate packages for
 the library compiled: vanilla, profiling, smp, bytecode, etc. If a
 package (such as the profiling) needs files that are already in
 another package (such as vanilla), it will simply depend on the other
 package. (i.e. it will *not* contain a second copy of the files)

 Currently, in order to split the profiling and vanilla libraries into
 separate .debs, I have to do some fancy hacking in the Debian
 specific dh_haskell script. If someone wants to build .rpms, they
 will probably come up with their own hacks to achieve the same goal.

 Clearly, this should be fixed at the Cabal level, instead of having
 each package maintainer come up with a duplicate set of hacks.

 Proper Level Of Abstraction
 ---------------------------

 Cabal is nice because it hides all the nasty compiler and platform
 specific build issues from the user. The user puts *what* they want
 in the .cabal file, and they let Cabal take care of the *how*.

 I think it is very desirable to retain this abstraction in the
 configure flags as much as possible. To me, this means that the
 flags:

    --disable-library-vanilla --enable-library-profiling

 Should have a specified behavior that is compiler and platform
 independent. It is the job of the compiler specific Cabal code to
 meet the spec. (e.g. Distribution.Simple.GHC, etc)

 Appropriate Level of Error Reporting
 ------------------------------------

 Some options never make sense, for example:

    --enable-library-vanilla --disable-library-vanilla

 We can check for that nonsense all the time.

 But the are other combinations of flags that only make sense from a
 maintainers point of view. The typical end user would just end up
 with a broken library install.

 So I propose we enable strict flag checking by default, but provide a
 flag, such as --maintainer-mode, that loosen the restrictions.

 Difficulties
 ------------

 It is difficult to make a specification that all compilers can
 meet. For example, most compilers do not support profiling, so they
 can not support the --enable-*-profiling flag at the moment. In this
 case, we could just extend the spec to say that it is an error to
 enable profiling for a compiler that does not support profiling.

 On the other hand, someone might make a compiler that does not allow
 you to install the vanilla and profiling libraries at the same
 time. Now you have the problem that you do want to have a -prof .deb,
 but it is going to work different from the 'standard'.

 Of course, the specifications are supposedly reasonable
 specifications that are dictated by the actual needs of the users and
 the package maintainers. So, I think in most cases, having a
 specification to meet will make it easier for compiler writers, since
 they will not have to learn the hard way that certain features are
 important.

 There will be exceptions. That is why, for example, the .cabal file
 has compiler specific fields like ghc-options even though it has the
 Extensions field. I am not quite sure how that translates to
 configure flags.

How to Handle GHC + Profiling + TemplateHaskell
===============================================

 Profiling + TemplateHaskell Question
 ------------------------------------

 I currently only have 6.4.1 installed -- as far as I can tell,
 profiling + TH does not work at all in 6.4.1. In ghc head, if I do,

   ghc --make -prof Test.hs -o test

 Does the compiler automatically build the vanilla objects and then
 build the profiling objects? Or do I need to first build without
 -prof, and then build with -prof?

 I think I can implement a solution in three incremental steps:

  (1) Add finer granularity configure flags
  (2) Add sanity checking to the argument processing
  (3) Add some 'speed' hacks

 How It Would Work In Cabal
 --------------------------

 The spec for the flags:

   --maintainer --disable-library-vanilla --enable-library-profiling

 is something like,

  + build the libraries with profiling enabled

  + copy out just the files needed add profiling support to a system
    that already has the vanilla libraries available

  + this assumes that the profiling and vanilla libraries can co-exist
    (i.e. do not have conflicting files, etc)

 Here is how the Cabal code for GHC would meet that spec:

 (1) In the 'build' phase:
      
     (i) if ghc requires you to explicitly build the vanilla libraries
       before building the profiling libraries, then do that.

     (ii) build the profiling libraries

 (2) In the 'install/copy' phase, *only* copy the profiling libraries
     out.

 (NOTE: This is actually quite easy -- I have already implemented it
 in Cabal).

 Downside Of This Solution
 -------------------------
 
 The downside of the above implementation is that the vanilla
 libraries will be built twice. Once for installation in the -vanilla
 package, and a second time when trying to create the -prof package.

Unsafe Speed Hacks:
===================

In most cases, the above solution will be fine. But, if you are
dealing with a package where building the vanilla libraries twice is a
huge overhead, then it might be worthwhile to try to use one the hacks
presented below. The downside is they require you to understand the
situations in which they can be safely used. These hacks are a perhaps
a bit like unsafePerformIO, unsafeCoerce, etc ;)

 change copy/install to allow selective copy
 -------------------------------------------

 Add the flags --copy-only-profiling --copy-only-vanilla. This
 solution works for vanilla and profiling, because they contain
 uniquely named output files. But, if you want to build with and with
 out the -O2 flag, then you really do have to run the build phase
 twice.

 --no-clean
 ----------

 If we did not delete the vanilla libraries before building the
 profiling libraries, then we would only have to build them once. On
 the other hand, if we look at our -O2 example, it *would* require a
 'clean' between builds.

Your Comments Here
==================

If you have any suggestions, see any pitfalls, or have a completely
different idea about how to solve this problem, please let me know. I
think the approach is pretty conservative -- so if it does not work
out, we should still be in a good position to try a different
approach. But, anything we can learn now will certainly help :)

j.


More information about the Libraries mailing list