Build system idea, what about a "magic knowledge /
refactoring" database?
Marc Weber
marco-oweber at gmx.de
Sat Aug 30 05:06:26 EDT 2008
Hi John,
I've extracted among others two things you don't like too much about
cabal:
a) having to specify build dependencies because they may change
(eg example split base or different libraries poviding network
interfaces ..)
b) Cabal can't do everything easily. Examples are the multi stage system
of ghc or wxWidgets ... Can't say much to this point. For my needs cabal
has been enough and packaging many package for NixOs has been easy
(except adding foreign C lib dependencies)
You would also prefer a build command which does never change solving
the problem that you Setup.hs files maybe can't be read by Cabal
vesrions of the future. You'd like to have a cabal independant package
description so you can extract information easily?
Maybe I got some things not right here.. Anyway, how does a package
description look like which would satisfy the write once, let one true
buildsystem build my package on foregin architectures, machines, distros
without having me to change network to jhc-network or such? And probably
without the burden for implementors to have to provide a network-1.0
compatible interface ?
Let's talk about an example:
module Main where
import System.IO
import ClassProvidingShowDerivedAB
data A = ...
{- derive .. - }
main = do
printLn $ showDerivedA $ A ...
printLn $ showDerivedB $ A ...
So the description must contain that we need
- DrIft or the derive library (assuming that the derive library can read Drift syntax)
- a foreign module (probably called ClassProvidingShowDerivedAB) providing
showDerivedAB of type (A .. -> String)
- a foreign module (probably called System.IO) providing printLn of type
(String :: IO ())
where "a foreign module" may also mean or any other set of modules
exporting the given functions..
So a configure system should find packages containing those functions
beeing used and should know (or be able to figure out itself) that
ClassProvidingShowDerivedAB
has been split into ClassProvidingShowDerivedA ClassProvidingShowDerivedB on some systems?
The type system of haskell will be able to give you much better matches
compared to looking for C/C++ interfaces, but String -> IO () is not
very uniq..
So how can this dependency be expressed? Only consider package
dependencies having the word "network" in either its name or
description? You could ask the configure system to test all functions
String -> IO () wether they have the desired behaviour (hoping that none
is implemnted as showDerivedA = const $ removeRecursive "/")..
Anyway it would be quite interesting to see wether we can write an
application guessing dependencies this way.. However I don't like this
to be done automatically. Then the burden of writing the dependencies
into a description file would even become smaller.
If we want a package be buildable on a time frame of
-10 years (past) -> now -> + 10 years (future)
either the configure script or the configure system can check for
different substitutes or versions which did exsist from -10 years in the
past up to now. However we can't know the changes beeing made in the
future or wether different substitutes will become availible..
However some "magic knowledge" could know about my lib and its
dependencies at publication and know about changes having been made to
dependencies up to now. Then it could try refactoring the published code
to fit current versions of the libraries.. In the future maybe this
magic knowledge can be found in darcs patches (it alread provides
support to changing names to some degree..) or it could be collected by
volunteers. Changes which could be resolved automatically are renaming ,
merging and splitting of functions or modules, refactorings such as
adding additional parameters to functions etc..
This magic knowledge could be updated by running a tool such as
autoreconf or whatsover.. I even think this could work quite well for
if you have kind of package database such as hackage knowing about
interface changes from package xx-1.0 to xx-2.0.
But it would be hard to implement a refactoring tool which can refactor
source containing some #ifdefs ? Wait, we could throw away many
#ifdef GHC_VERSION > or < version x.y because the system would know
about the differences?
To uniqely define a set of transformations of your code which has been
written using set of dependencies A so that it can be compiled on
another system B you need something like a *.cabal file again to tell
the nice configure and rewrite engine where to start..
This could look like this
network-1.0 from hackage
HaXmL git repo hash XXYYZZ
Then you could tell the magic tool that instead of network-1.0
jhc-network-0.8 can be tried..
I would really appriciate such a magic tool knowing abouth thousands of
changes/ refactorings
a) if it knows a transformation I can just run it and compile
b) if it knows the difference but there is no transformation
maybe there is a comment helping me fixing the trouble faster
Such a hint could look like: From now on there is a lazy and a strict
variant, so import either X or Y. Or functions W has been removed,
use lib K or L instead.
c) The person doing the initial change (breaking things) knows most
about the change and knows best how to tell people what to do..
Even if i didn't you can upload a transformation to save other peoples
time..
I think this is the way to go in the long run: Create a huge database of
refactorings either giving you hints how to make a package compile on a
different system or maybe even applying some of them automatically.
With some time this has the chance to become some "old deep" knowledge as it is
burried in autotools now ?
Anyway implementing this would be a lot of work put might pay of one
day. Of course this applies not only to haskell systems..
Hopefully it will not result in breakages occur more often because they
will become cheaper?
What do you think?
Sincerly
Marc Weber
More information about the Glasgow-haskell-users
mailing list