University of Minnesota, Twin Cities School of Statistics Charlie's Home Page
This web page provides information about use of R on the computers in the School of Statistics, University of Minnesota.
library
(packagename), then you
don't need to read this page.
dyn.load
(sharedlibraryname)
and you want this to work on different machines, then you
do need to read this page.
As readers may or may not know, all of our linux workstations run the same version of linux (SuSE 9.3) but we have two kinds of hardware. The machines bought this year having the Frontier Systems brand are AMD Opteron dual-processor systems. We call them 64 bit for short because they have 64 bit C pointers. The machines bought in previous years having the General Nanosystems brand are AMD Athlon dual-processor (black case) or single-processor (white case) systems. We call them 32 bit for short because they have 32 bit C pointers.
You can always tell what kind of a machine you have (under linux) by doing
cat /proc/cpuinfo
which will give information about the number and types of processors in the machine.
A simpler way to distinguish machines with with the arch
command.
oak$ arch i686
is what you see on a 32 bit machine, and
zephyr$ arch x86_64
is what you see on a 64 bit machine.
When you run programs that come with the SuSE linux installed on the machine, they just work.
Problems arise when you try to run a program compiled for one architecture on a different architecture. Your home directory and the directory in which R is installed are visible on all machines and can therefore contain code compiled on either architecture.
The 64 bit machines have a hardware 32 bit emulation mode. So binaries and libraries compiled on 32 bit machines work on all machines.
This does not work the other way around. Stuff compiled on 64 bit machines does not run on 32 bit machines.
As of 3 January 2006 we have two R binaries
/APPS/32/bin/R /APPS/64/bin/R
If you are on 32 bit, then you automatically get the first when you just
say R
.
If you are on 64 bit, then you automatically get the second when you just
say R
.
On 64 bit you can run the first, if you so desire,
but you must invoke it using the full path name
/APPS/32/bin/R
.
It will work in emulation mode.
If you never load your own C code into R with
dyn.load
(sharedlibraryname)
and never use libraries other than those that those installed by
the system administrators and you load with
library
(packagename), then you
should have no problems. Just say R
with no additional
fuss to invoke R, and it will work.
Otherwise, you will have to be aware of
Everything must match except that you can run /APPS/32/bin/R
on a 64 bit machine and load a library compiled on 32 bit.
Also, when compiling, everything must be compiled on one
architecture. Remove all object files .o
and .so
before compiling. Any stuff compiled with the other architecture
won't work!
The machine named oak
is 32 bit. The code foo.c
is found on the
web page explaining Calling C and Fortran from R.
oak$ /APPS/32/bin/R CMD SHLIB foo.c gcc -I/APPS/32/lib/R/include -I/usr/local/include -fPIC -g -O2 -c foo.c -o foo.o gcc -shared -L/usr/local/lib -o foo.so foo.o oak$ /APPS/32/bin/R --vanilla --quiet > dyn.load("foo.so") > .C("foo", n=as.integer(5), x=as.double(rnorm(5))) $n [1] 5 $x [1] 0.23809671 5.92472146 0.48857718 0.35638561 0.04285859
The machine named zephyr
is 64 bit.
The shared library foo.so
was compiled on 32 bit (in the
preceding section).
zephyr$ /APPS/64/bin/R --vanilla --quiet > dyn.load("foo.so") Error in dyn.load(x, as.logical(local), as.logical(now)) : unable to load shared library '/HOME/faculty/charlie/tmp/moof/foo.so': /HOME/faculty/charlie/tmp/moof/foo.so: cannot open shared object file: No such file or directory
The error message is cryptic, but what happened is clear. It doesn't work.
zephyr$ /APPS/32/bin/R --vanilla --quiet > dyn.load("foo.so") > .C("foo", n=as.integer(5), x=as.double(rnorm(5))) $n [1] 5 $x [1] 0.06865342 0.09680243 0.01240681 0.71240126 0.48262325
zephyr$ rm *.o *.so zephyr$ /APPS/64/bin/R CMD SHLIB foo.c gcc -I/APPS/64/lib64/R/include -I/usr/local/include -fPIC -g -O2 -c foo.c -o foo.o gcc -shared -L/usr/local/lib64 -o foo.so foo.o zephyr$ /APPS/64/bin/R --vanilla --quiet > dyn.load("foo.so") > .C("foo", n=as.integer(5), x=as.double(rnorm(5))) $n [1] 5 $x [1] 0.006842728 0.010809147 0.226847601 0.829887253 0.974997980 > q()
It just works. But note well the rm *.o *.so
.
It wouldn't have worked without that.
The machine named oak
is 32 bit.
The shared library foo.so
was compiled on 64 bit (in the
preceding section).
oak$ cd tmp/moof oak$ /APPS/32/bin/R --vanilla --quiet > dyn.load("foo.so") Error in dyn.load(x, as.logical(local), as.logical(now)) : unable to load shared library '/HOME/faculty/charlie/tmp/moof/foo.so': /HOME/faculty/charlie/tmp/moof/foo.so: cannot open shared object file: No such file or directory > q()
Again the error is cryptic. The file
command will always tell
you what you are dealing with.
oak$ file foo.so foo.so: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped
If you know that AMD x86-64
doesn't work on this (32 bit)
architecture, then you know what's going on.
Of the five examples, two don't work.
/APPS/32/bin/R
). Works.
You must be aware of (1) where you compiled (2) where you are, and (3) which R binary you are running to understand what happens.
There is no problem building or checking an R package
(with R CMD check
) so long as
.o
and .so
files
that were compiled on the other architecture from the src
subdirectory of the package.
If you don't, R will give very uninformative error messages when
R CMD check
fails. The most informative part of the
error message is where it tells you
* checking if this is a source package ... WARNING Subdirectory 'packagename/src' contains object files.
When you fail to clean the src
subdirectory before compiling
on the other architecture, bad things happen.
* checking replacement functions ... WARNING Error: .First.lib failed for 'bernor' Call sequence: 2: stop(gettextf(".First.lib failed for '%s'", libraryPkgName(package)), domain = NA) 1: library(package, lib.loc = lib.loc, character.only = TRUE, verbose = FALSE) Execution halted In R, the argument of a replacement function which corresponds to the right hand side must be named 'value'. * checking foreign function calls ... WARNING Error: .First.lib failed for 'bernor' Call sequence: 2: stop(gettextf(".First.lib failed for '%s'", libraryPkgName(package)), domain = NA) 1: library(package, lib.loc = lib.loc, character.only = TRUE, verbose = FALSE) Execution halted See section 'System and foreign language interfaces' of the 'Writing R Extensions' manual.
But what does all that mean? The error messages are totally uninformative.
You must think. What version of R am I using? The unix command
type R
will tell you what binary will run if you type R
.
And what kind of binaries do I have in the src
directory?
The unix command file *.o *.so
will tell you what they are.
You will need a separate install of each architecture (if you use both),
and you will need some kind if trickery in your .bashrc
that I haven't bothered to figure out yet to chose which one gets loaded.
Alternatively, you will have to use /APPS/32/bin/R
on both
architectures and always build on 32 bit.