
On Sat, 2007-07-28 at 17:08 +0200, Thorkil Naur wrote:
So what I wonder is how we can make this work reliably. We use the flags that pkg-config tells us to use, I'd rather not add platform-specific hacks if we can get the pkg-config settings fixed. So I presume when you run pkg-config --libs gtk+-2.0 it does not list -L/opt/local/lib, or if it does it lists it after -L/usr/X11R6/lib. Is that the case?
For the GTK+ tutorial helloworld.c program:
$ pkg-config --libs gtk+-2.0 -L/Users/thorkilnaur/tn/install/gtk+-2.10.14/lib -L/opt/local/lib -L/usr/X11R6/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lSM -lICE -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lintl -liconv -lfreetype -lz -lfontconfig -lpng12 -lXrender -lX11 $ gcc -v -Wall -g helloworld.c -o helloworld `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` ...
Scrutinizing the link arguments output by gcc, it appears that the -Ls and the -ls specified on the gcc command have been separated and inserted between other -Ls and -ls supplied by gcc. But the order of the -Ls produced by pkg-config is retained and, as mentioned, this is the case that works without change.
Ok.
For the Gtk2Hs demo World.hs program, the matter is more complex, especially since the link arguments generated by ghc presumably goes via ghc-pkg that I have never studied in detail before. But let me venture a guess anyway.
First we look at the gtk package and its dependents:
$ for p in gtk-0.9.12 glib-0.9.12 cairo-0.9.12; do echo $p: `ghc-pkg field $p depends`; done gtk-0.9.12: depends: base-2.0 mtl-1.0 glib-0.9.12 cairo-0.9.12 glib-0.9.12: depends: base-2.0 cairo-0.9.12: depends: base-2.0 mtl-1.0 glib-0.9.12 $
Further:
$ for p in gtk-0.9.12 glib-0.9.12 cairo-0.9.12; do echo $p: `ghc-pkg field $p library-dirs`; done gtk-0.9.12: library-dirs: /Users/thorkilnaur/tn/install/gtk+-2.10.14/lib /usr/X11R6/lib /Users/thorkilnaur/tn/install/gtk2hs-0.9.12/lib/gtk2hs glib-0.9.12: library-dirs: /opt/local/lib /Users/thorkilnaur/tn/install/gtk2hs-0.9.12/lib/gtk2hs cairo-0.9.12: library-dirs: /opt/local/lib /usr/X11R6/lib /Users/thorkilnaur/tn/install/gtk2hs-0.9.12/lib/gtk2hs $
The actual link arguments constructed by ghc when compiling World.hs are:
$ ghc -v --make World.hs -o helloworld ... Linking helloworld ... *** Linker: gcc -v -o helloworld World.o -L/Users/thorkilnaur/tn/install/gtk+-2.10.14/lib -L/usr/X11R6/lib -L/Users/thorkilnaur/tn/install/gtk2hs-0.9.12/lib/gtk2hs -L/opt/local/lib -L/Users/thorkilnaur/tn/install/ghc-6.6-for-buildbot-20070221_1000/lib/ghc-6.6.20070220 -lHSgtk -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lSM -lICE -lgmodule-2.0 -lfreetype -lz -lfontconfig -lpng12 -lXrender -lX11 -lgthread-2.0 -lHScairo -lcairo -lSM -lICE -lfreetype -lz -lfontconfig -lpng12 -lXrender -lX11 -lHSglib -lgobject-2.0 -lglib-2.0 -lintl -liconv -lHSmtl -lHSbase -lHSbase_cbits -lHSrts -lm -u _base_GHCziBase_Izh_static_info -u ... $
The -Ls are:
-L/Users/thorkilnaur/tn/install/gtk+-2.10.14/lib -L/usr/X11R6/lib -L/Users/thorkilnaur/tn/install/gtk2hs-0.9.12/lib/gtk2hs -L/opt/local/lib -L/Users/thorkilnaur/tn/install/ghc-6.6-for-buildbot-20070221_1000/lib/ghc-6.6.20070220
My guess is now that ghc constructs this list from the package library-dirs, heaping new ones onto the growing list at the end. World.hs refers only gtk-0.9.12 which for some reason doesn't refer /opt/local/lib. However, gtk depends on glib and glib includes /opt/local/lib before /usr/X11R6/lib, but because the latter already appears in the current list, the new one (/opt/local/lib) is simply tucked onto the end. And so on, thereby explaining why /opt/local/lib ends up appearing after /usr/X11R6/lib.
Yes, that's the culprit.
I don't know what could be done about this, but certainly, the problem cannot be said to be caused by GTK+. Really, the basic problem is this horrendously primitive manner which is used on many of our systems of letting the order of appearance in certain lists influence the outcome of important processes. Plus, of course, the lack of possibility of warning users about this, for example by reporting on ambiguous references in case symbols are defined in multiple libraries.
Indeed, it's not Gtk+'s fault. It's the fact that we're splitting up the flags pkg-config tells us about glib, and gtk+, assigning them to the ghc packages glib and gtk and then reconstructing the link command line - but in the wrong order. I'll have to think about this. Thanks for the detailed investigation Thorkil. Duncan