Dynamic linking again

Andre Pang ozone@algorithm.com.au
Wed, 4 Sep 2002 16:02:43 +1000

On Mon, Sep 02, 2002 at 03:16:37 +0100, Simon Marlow wrote:

> > ghc -optl-export-dynamic  -ldl -L/usr/lib/ghc-5.04/ -lHSrts 
> > -lHSlang  \
> >   TestDLink.o -o TestDLink
> > 
> > since doing
> > 
> > ghc -optl-export-dynamic  -ldl -package rst -package lang  \
> >   TestDLink.o -o TestDLink
> > 
> > gives:
> > /usr/lib/ghc-5.04/libHSrts.a(RtsAPIDeprec.o): In function 
> > `rts_mkAddr':
> > RtsAPIDeprec.o(.text+0x14): undefined reference to `Addr_Azh_con_info'
> > /usr/lib/ghc-5.04/libHSrts.a(RtsAPIDeprec.o): In function 
> > `rts_getAddr':
> > RtsAPIDeprec.o(.text+0x2d): undefined reference to `Addr_Azh_con_info'
> > RtsAPIDeprec.o(.text+0x35): undefined reference to 
> > `Addr_Azh_static_info'
> > collect2: ld returned 1 exit status
> I'm not sure exactly what's going here.  RtsAPIDeprec.o does refer to
> Addr_Azh_con_info, which is defined in the Addr module in the lang
> package.  However, RtsAPIDeprec normally isn't linked in, because
> nothing refers to anything in it.

RtsAPIDeprec.o is in libHSrts.a (as the error message says).
Therefore using libHSrts.a means that you'll get all of
RtsAPIDeprec.o along with it, and therefore need to resolve all
its unresolved symbols.

I think I also understand why using -package doesn't work.  I'll
paste in two (cropped) gcc lines below; the first line is when
you use the "-lHSrts -lHSlang" options (which works), and the
second is when you use "-package rts -package -lang" (which
doesn't work):

    ... -L/usr/lib/ghc-5.04                      -L/usr/lib/gcc-lib/i386-linux/3.2 -L/usr/lib/gcc-lib/i386-linux/3.2/../../..                            Main.o -ldl          -lHSlang -lHSlang_cbits -lHShaskell98 -lHSbase -lHSbase_cbits -lHSrts -lgmp -lm -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-linux/3.2/crtend.o /usr/lib/gcc-lib/i386-linux/3.2/../../../crtn.o
    ... -L/usr/lib/ghc-5.04/ -L/usr/lib/ghc-5.04 -L/usr/lib/gcc-lib/i386-linux/3.2 -L/usr/lib/gcc-lib/i386-linux/3.2/../../.. /usr/lib/ghc-5.04/HSbase.o Main.o -ldl -lHSrts  -lHSlang                -lHShaskell98 -lHSbase -lHSbase_cbits -lHSrts -lgmp -lm -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-linux/3.2/crtend.o /usr/lib/gcc-lib/i386-linux/3.2/../../../crtn.o

.. so the only real difference between the line which works and
the line which doesn't work is:

    * line which works has /usr/lib/ghc-5.04/HSbase.o
    * line which works has an extra -lHSrts flag

It turns out that the pedant linker needs to see the -lHSrts flag
before -lHSlang.  This is a bit odd, since the HSlang library is
the one which has the required "Addr_Azh_con_info" symbol.  Of
course, ld(1) says:

    -( archives -)
    --start-group archives --end-group

      The archives should be a list of archive files. They may be
      either explicit file names, or -l options.

      The specified archives are searched repeatedly until no new
      undefined references are created. Normally, an archive is
      searched only once in the order that it is specified on the
      command line. If a symbol in that archive is needed to
      resolve an undefined symbol referred to by an object in an
      archive that appears later on the command line, the linker
      would not be able to resolve that reference. By grouping
      the archives, they all be searched repeatedly until all
      possible references are resolved.

      Using this option has a significant performance cost.  It
      is best to use it only when there are unavoidable circular
      references between two or more archives.

I'd classify this as an ld problem, but we still have to work
around it.

Aaaaanyway, using either "-package lang -package rts" or
"-package rts -package lang" doesn't affect the order of the -l
options, so we probably have to whack it in there manually.

#ozone/algorithm <ozone@algorithm.com.au>          - trust.in.love.to.save