
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.