From ripley at stats.ox.ac.uk  Sun May 13 21:58:44 2007
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Sun, 13 May 2007 20:58:44 +0100 (BST)
Subject: [Rd] Help understanding LAPACK symbol resolution
In-Reply-To: <6phtzuga5n9.fsf@gopher4.fhcrc.org>
References: <6phtzuga5n9.fsf@gopher4.fhcrc.org>
Message-ID: <Pine.LNX.4.64.0705132040280.27271@auk.stats>

On Sun, 13 May 2007, Martin Morgan wrote:

> R developers,
>
> I am trying to understand how symbols are resolved, so that I can
> configure a package that I contributed to, and so that I can provide
> guidance to (linux / OSX) users of the package. To be concrete, my
> package uses the LAPACK Fortran symbol zsysv. This is not in
> libRlapack, but is defined on my system in the library
> /usr/lib64/liblapack.so.
>
> * I suspect that the reason the symbol is not in libRlapack is just
>  one of economy, i.e., no use for the symbol in R routines, rather
>  than for other nefarious reasons (?? some fundamental incompatibility
>  with R?)

Space saving.  'Writing R Extensions' covers this.

> I guess that most of my package users will have an R built without
> special attention to their lapack library, so will start with
> something like
>
> mtmorgan at gopher4:~> R CMD config LAPACK_LIBS
> -L/home/mtmorgan/arch/x86_64/R-devel/lib -lRlapack
>
> My R is built with --enable-R-shlib, so predictably enough
>
> R CMD INSTALL --clean <pkg>
>
> is 'successful' (zsysv_ is marked as unresolved in the <pkg>.so, but
> this doesn't stop compiling and linking). Also predictably enough,
> loading the package in R indicates 'undefined symbol: zsysv_'. Inside
> R, LD_LIBRARY_PATH starts with he R_HOME/lib, and includes /usr/lib64,
> so I surmise that the libraries defined at compile / link are the ones
> where symbols are searched (rather than all libraries in
> LD_LIBRARY_PATH).

Not the way R is usually built.  Library dirs specified by -L during 
configure are added to R_LIBRARY_PATH, but not those specified by the 
environment LD_LIBRARY_PATH at build time.  Most loaders have a -R/-rpath 
option, but R does not (by default) make use of it.  (I personally think 
it should: ELF originates on Solaris and that makes very effective use of 
-R.)

At run time ld.so searches its cache as well as LD_LIBRARY_PATH.  The 
order is system-specific: Linux says

    o (ELF only) Using the DT_RPATH dynamic section attribute  of  the
      binary  if present and DT_RUNPATH attribute does not exist.  Use
      of DT_RPATH is deprecated.

    o Using the environment variable LD_LIBRARY_PATH.  Except  if  the
      executable  is  a set-user-ID/set-group-ID binary, in which case
      it is ignored.

    o (ELF only) Using the DT_RUNPATH dynamic section attribute of the
        binary if present.

    o From  the  cache file /etc/ld.so.cache which contains a compiled
      list of candidate libraries previously found  in  the  augmented
      library  path.  If, however, the binary was linked with -z node-
      flib linker option, libraries in the default library  paths  are
      skipped.

    o In  the default path /lib, and then /usr/lib.  If the binary was
      linked with -z nodeflib linker option, this step is skipped.

(and for a 64-bit system, read lib64 for lib).


> To allow the user to provide a specific LAPACK, I added lines to a
> configure.in file that allow for a --with-lapack
>
> LAPACK_LIBS=`"${R_HOME}/bin/R" CMD config LAPACK_LIBS`
> AC_ARG_WITH([lapack],
> 	AC_HELP_STRING([--with-lapack=LIB_PATH],
> 		[LAPACK library location with complex routines]),
> 		[LAPACK_LIBS=$withval])
>
> added a check to see that zsysv_ is actually available
>
> AC_CHECK_FUNC(zsysv_,,
> 	AC_MSG_ERROR([lapack needs zsysv_ in ${LAPACK_LIBS}]))
>
> and substituted LAPACK_LIBS into a Makevars.in file
>
> AC_SUBST(LAPACK_LIBS)
> AC_OUTPUT(src/Makevars)
>
> Makevars.in:
> PKG_LIBS=@LAPACK_LIBS@
>
> I then install my package with
>
> R CMD INSTALL --clean --configure-args=--with-lapack=-llapack <pkg>
>
> or more generally
>
> R CMD INSTALL --clean \
>   --configure-args="--with-lapack='-L/usr/lib64 -llapack'" <pkg>
>
> This 'works', in the sense that the package compiles, loads, and
> apparently runs as expected. I'm concerned though about how lapack is
> being found, and how symbols are actually being resolved.
>
> When I
>
> mtmorgan at gopehr4:~> ldd <pkg>.so
>
> I see an entry
>
>        liblapack.so.3 => /usr/lib64/liblapack.so.3 (0x00002b0928a1c000)
>
> and I do NOT see an entry pointing to libRlapack .Am I right in
> interpreting this to mean:
>
> * All LAPACK symbols in my package, including those that
>  coincidentally have a definition in libRlapack, resolve to
>  /usr/lib64/liblapack.so?

Yes.  libRlapack.so will not be in the search path.

> * liblapack.so will be found without any need to specify
>  LD_LIBRARY_PATH, or other configuration variables? Or is the library
>  being found because my LD_LIBRARY_PATH already includes /usr/lib64?

Both ld (used for linking) and ld.so (used a runtime) look in that path by 
default.

>  If the latter, how can the user 'best' configure their system to
>  find the required library (I think I'm looking for something between
>  'get the system administrator to install lapack in a findable place'
>  and 'set LD_LIBRARY_PATH before starting R').

Better to set it in the ld.so cache (via a file in /etc/ld.so.conf.d on a 
modern system), and set -L at build time.

> * Resolving symbols to libraries will occur in a way consistent with
>  the last two points (as opposed to the implementation details)
>  across platforms, compilers, and static vs. shared libraries?
>
> Thanks for any reassurance or corrective guidance.

The standard advice would be to supply the LAPACK routines in the package, 
and compile them if they are not found in $LAPACK_LIBS.  Remember that 
there are quite a few buggy LAPACKs out there so it is better to use your 
own than a system one that might be faster but inaccurate.

As I recall, fastICA is an example of the latter strategy.

-- 
Brian D. Ripley,                  ripley at stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595



[Rd] Help understanding LAPACK symbol resolution
Prof Brian Ripley