Subject: Re: soc zfs: and self-referencing symlinks
To: None <tech-toolchain@netbsd.org>
From: Oliver Gould <ogould@olix0r.net>
List: tech-toolchain
Date: 08/16/2007 17:42:38
On 2007-08-16 18:36 +0200, Quentin Garnier wrote:
> On Thu, Aug 16, 2007 at 12:16:46PM -0400, Oliver Gould wrote:
> >   ...
> >   libnvpair.so.1 -> libnvpair.so.1
> >   libnvpair.so -> libnvpair.so.1
> >   ...
> > 
> > Clearly the shared lib files are useless.  I didn't notice any obvious
> > difference with other lib Makefiles.

I noticed I was missing an include to <bsd.own.mk>.  This doesn't change
anything, though.

> What am I missing?
> 
> A shlib_version file?

That is apparently it; but only after a lot more digging...

This is what was happening:

    #     build  libnvpair/libnvpair.so.1
    rm -f libnvpair.so.1
    cc -Wl,-x -shared -Wl,-soname,libnvpair.so.1   -o libnvpair.so.1
        -Wl,-rpath-link,/lib:/usr/lib  -R/lib  -L/lib  -Wl,--whole-archive
        libnvpair_pic.a -Wl,--no-whole-archive
 *  ln -sf libnvpair.so.1 libnvpair.so.1.tmp 
 *  mv -f libnvpair.so.1.tmp libnvpair.so.1  
    ln -sf libnvpair.so.1 libnvpair.so.tmp
    mv -f libnvpair.so.tmp libnvpair.so

This occurs in <bsd.lib.mk>:

    .if ${OBJECT_FMT} == "ELF"
    #  We don't use INSTALL_SYMLINK here because this is just
    #  happening inside the build directory/objdir. XXX Why does
    #  this spend so much effort on libraries that aren't live??? XXX
 *      ${HOST_LN} -sf lib${LIB}.so.${SHLIB_FULLVERSION} \
		lib${LIB}.so.${SHLIB_MAJOR}.tmp
 *      mv -f lib${LIB}.so.${SHLIB_MAJOR}.tmp lib${LIB}.so.${SHLIB_MAJOR}
        ${HOST_LN} -sf lib${LIB}.so.${SHLIB_FULLVERSION} lib${LIB}.so.tmp
	mv -f lib${LIB}.so.tmp lib${LIB}.so
    .endif

Which is broken when SHLIB_FULLVERSION == SHLIB_MAJOR.  Yet, earlier in
this file, SHLIB_FULLVERSION can be set to SHLIB_MAJOR:

    .if defined(SHLIB_MAJOR) && !empty(SHLIB_MAJOR)		# {
    .if defined(SHLIB_MINOR) && !empty(SHLIB_MINOR)
    .if defined(SHLIB_TEENY) && !empty(SHLIB_TEENY)
    SHLIB_FULLVERSION=${SHLIB_MAJOR}.${SHLIB_MINOR}.${SHLIB_TEENY}
    .else
    SHLIB_FULLVERSION=${SHLIB_MAJOR}.${SHLIB_MINOR}
    .endif
    .else
 *  SHLIB_FULLVERSION=${SHLIB_MAJOR}
    .endif
    .endif							# }

When I set SHLIB_MINOR=0 manually in the Makefile, though, everything
operates as expected:

    libnvpair.so -> libnvpair.so.1.0
    libnvpair.so.1 -> libnvpair.so.1.0
    libnvpair.so.1.0

So, apparently, shlib_version is not read:

    (isla)$ cat shlib_version     
    #       $NetBSD: shlib_version,v 1.3 2005/04/17 07:20:00 provos Exp $
    #       Remember to update distrib/sets/lists/base/shl.* when changing
    #
    major=2
    minor=0
    (isla)$ make print-shlib-major
    1
    (isla)$ make print-shlib-minor
    *** Error code 1

    Stop.
    make: stopped in /mnt/src/zfs/src/cddl/lib/libnvpair

This is because cddl/lib/Makefile.inc (included from bsd.own.mk, I
believe) defines SHLIB_MAJOR=1, and therefore SHLIB_{MINOR,TEENY} are
not read in from shlib_version:

    .if !defined(SHLIB_MAJOR) && exists(${SHLIB_VERSION_FILE})	# {
    SHLIB_MAJOR != . ${SHLIB_VERSION_FILE} ; echo $$major
    SHLIB_MINOR != . ${SHLIB_VERSION_FILE} ; echo $$minor
    SHLIB_TEENY != . ${SHLIB_VERSION_FILE} ; echo $$teeny
    ...
    .endif							# }

I am not authoritative, but I believe that at least one of the following
fixes should be made:

  o  Do not set SHLIB_FULLVERSION to SHLIB_MAJOR.  If no SHLIB_MINOR is
     set, append ".0" to SHLIB_MAJOR.

  o  Read SHLIB_{MINOR,TEENY} from SHLIB_VERSION_FILE if they are
     undefined, regardless of whether SHLIB_MAJOR is defiend.

  o  Change the symlink directives so that libs can be created in the
     case that SHLIB_FULLVERSION == SHLIB_MAJOR.

I have not made patches to do any of these, as my make-foo is weak (and
I have some more time sensitive work to do now that I have found a
workaround ;)

Thanks for the pointer, Quentin!
  - Oliver