Linux下安装R(心路历程版)

不像在windows上面下载安装包进行安装那么简单,你只要选择好安装目录,然后一直next就行。
要在Linux下通过源码安装R包是一件非常耗时耗力的事情。由于个人工作性质的原因,需要常常使用大型机进行作业,但是大型机基本都是Linux系统,由于需要使用R,并且经常会做一些个性化分析,需要自己安装相应的R包,但是由于自己没有root权限,在安装软件时难免会收到这样那样的掣肘。我第一次安装R以失败告终,因为安装R时会告诉你需要A库,然后你去安装A库,但是当你去安装A库的时候又会告诉你需要安装B库,如此循环往复,最后终于心撕力竭,手头又有其他事情要忙,终于铩羽而归。但是有一天遇到王道明,他正好也有过如此安装R的经历,最后捯饬了半天终于成功,最后还把这个经历总结下来,我当时内心狂喜,仿佛得到了武功秘籍。想着终于可以痛快地安装R了,但是事实证明我还是Too young Too simple,最后还是经历了之前没有预想到的大坑,凭借着王道明的安装指南和R官方文档,才终于功德圆满,取经归来。

第一难:R依赖库的安装

在安装R之前首先要安装R依赖的包,如何知道R安装需要什么包呢?可以去看R的官方文档R Installation and Administration ,我们主要要安装的依赖包是zlib,bzip,liblzma(这个包如果直接搜索liblzma出来的会是XZ,没错,需要安装的就是XZ)以及PCRE。不过首先需要注意的是,我安装的R版本是R-3.4.2 Short Summer,2017-09-28发行,而依照的官方文档也是Version 3.4.2 2017-09-28,因此其他版本的不一定完全适用,但是一般来说R所依赖的包大致都是这些,可能有版本的区别,安装R的大致顺序也差不多。其次,在安装这些库时最好遵照我下面给出的顺序来依次进行。否则就会报错。

1.安装zlib1.2.5版本及以上

1
2
3
4
cd zlib-1.2.11
./configure --prefix =/bulider/software/zlib
make
make install

2.安装bzip

1
2
3
4
cd bzip2-1.0.6
make -f Makefile-libbz2_so
修改Makefile 中的PREFIX=/bulider/software/bzip2
make && make install

3.安装liblzma5.0.3版本及以上

1
2
3
4
cd xz-5.2.3
./configure -prefix=/bulider/software/xz
make
make install

4.安装pcre

1
2
3
4
5
tar -zxvf pcre-8.41.tar.gz
cd pcre-8.41
./configure --enable-utf --enable-unicode-properties --enable-jit --disable-cpp --prefix /bulider/software/pcre##这个包的安装参数是有要求的,因此用的是官方文档的推荐命令
make
make install

5.安装libcurl7.22.0及以上,但是不要超过版本8

1
2
3
4
5
tar -zxf curl-7.28.0.tar.gz
cd curl-7.28.0
./configure --prefix=/bulider/software/curl
make
make install

第二难:安装R

安装了一打R的依赖包以后,你以为就能修成正果,急流勇退了吗?如果你有这个想法我想说你还是图样图森破!上台拿衣服!
1.进行configure

1
2
3
4
5
/source/R-3.4.2/configure --prefix=/builder/software/R --en
able-R-shlib --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling LDFLAGS="-L/builder/software/zlib/lib -L/builder/software/bzip2/lib -L/builder/software/xz/lib -L/builder/software/pcre/lib -L/builder/so
ftware/curl/lib" CPPFLAGS="-I/builder/zlib/include -I/builder/softw
are/bzip2/include -I/builder/software/xz/include -I/builder/software/pcre/in
clude -I/builder/software/curl/include"##第一步检查环境配置,生成Makefile

首先注意一点,如果你要把R安装到另一个文件夹里而不是源码所在的文件夹里,那么你首先要创建一个文件夹,然后在这个文件夹里对R进行编译,在configure时要加上全路径/source/R-3.4.2/configure,同时在后面加上--prefix=参数,比方我要安装到/builder/software/R,那么就需要加入--prefix=/builder/software/R这个参数,而我的源码在/source/R-3.4.2这个文件夹里。
其次由于R是用C语言写的,因此要从源码编译R需要把R的源码需要通过gcc将源码编译为可执行文件。在前面我们安装了一些R的依赖库,这些依赖库是在编译R的时候要用到的,如果在一般情况下这些依赖库都会放到系统指定的位置来进行使用,但是由于我没有root权限,因此无法将这些库文件放到系统指定的库路径或者修改相应的配置文件,只能把这些库的路径通过LDFLAGSCPPFLAGS这两个参数来传递给gcc,关于这两个参数可以参考。告诉gcc这些路径里有相应的库。其中LDFLAGS传递的是给链接器的参数,CPPFLAGS传递的是相应的头文件。这两个参数都是configure的参数。
2.通过上一步生成了Makefile后,觉得胜利已经在前方向你招手,于是你进行了

1
make

但是出现了报错!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/usr/bin/ld: warning: libpcre.so.1, needed by ../../lib/libR.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: liblzma.so.5, needed by ../../lib/libR.so, not found (try using -rpath or -rpath-link)
../../lib/libR.so: undefined reference to `pcre_fullinfo'
../../lib/libR.so: undefined reference to `lzma_lzma_preset@XZ_5.0'
../../lib/libR.so: undefined reference to `lzma_alone_decoder@XZ_5.0'
../../lib/libR.so: undefined reference to `lzma_crc64@XZ_5.0'
../../lib/libR.so: undefined reference to `lzma_raw_encoder@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_config'
../../lib/libR.so: undefined reference to `lzma_code@XZ_5.0'
../../lib/libR.so: undefined reference to `lzma_stream_decoder@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_free'
../../lib/libR.so: undefined reference to `lzma_raw_decoder@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_free_study'
../../lib/libR.so: undefined reference to `pcre_assign_jit_stack'
../../lib/libR.so: undefined reference to `pcre_exec'
../../lib/libR.so: undefined reference to `lzma_version_string@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_maketables'
../../lib/libR.so: undefined reference to `lzma_stream_encoder@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_compile'
../../lib/libR.so: undefined reference to `pcre_study'
../../lib/libR.so: undefined reference to `pcre_version'
../../lib/libR.so: undefined reference to `lzma_end@XZ_5.0'
../../lib/libR.so: undefined reference to `pcre_jit_stack_alloc'
collect2: error: ld returned 1 exit status
make[3]: *** [R.bin] Error 1
make[3]: Leaving directory `/builder/software/R/src/main'
make[2]: *** [R] Error 2
make[2]: Leaving directory `/builder/software/R/src/main'
make[1]: *** [R] Error 1
make[1]: Leaving directory `/builder/software/R/src'
make: *** [R] Error 1

这个报错是因为什么原因导致的?我们可以看到里面说

1
2
/usr/bin/ld: warning: libpcre.so.1, needed by ../../lib/libR.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: liblzma.so.5, needed by ../../lib/libR.so, not found (try using -rpath or -rpath-link)

说缺少libpcre.so.1liblzma.so.5这两个库文件,我心里浮现了一副黑人问号脸我在前面./configure的时候还传入了PCREXZ这两个库的路径,为什么还是会报错?
于是我先是进行了谷歌,从谷歌上找到了一篇R安装攻略,在这篇攻略里也提到了这个问题,

此处报错是由于没有找到动态库,看第一二行
解决方法:添加动态库
cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/opt/pcre-8.39/lib
/opt/xz-5.2.2/lib

但是在这个攻略里最后的解决方法是修改/etc/ld.so.conf文件,将前面安装的库的路径添加到这个文件中,但是我没有root权限,并不能修改这个文件,因此这个方法对我并不适用。后来在鹏帆和许骄的提醒下,我们在后面看到建议说try using -rpath or -rpath-link,后来我搜索了这两个命令,这两个命令是用于通过gccld传递参数的时候用的,

gcc编译链接动态库时,很有可能编译通过,但是执行时,找不到动态链接库,那是因为-L选项指定的路径只在编译时有效,解决方法是通过-Wl(注意,是字母表K之后的小写L),rpath=<your_lib_dir>,使得execute记住链接库的位置

于是我试着在configure的时候加入这两个参数

1
2
3
4
5
/builder/software/R-3.4.2/configure --prefix=/builder/software/R --en
able-R-shlib --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling LDFLAGS="-L/builder/software/zlib/lib -L/builder/software/bzip2/lib -L/builder/software/xz/lib -Wl,--rpath/builder/software/pcre/lib -Wl,--rpath/builder/so
ftware/curl/lib" CPPFLAGS="-I/builder/software/zlib/include -I/builder/softw
are/bzip2/include -I/builder/software/xz/include -I/builder/software/pcre/in
clude -I/builder/software/curl/include

但是这样总会报错,后来我知道,configure的时候我们传入的参数都会写到Makeconf文件里面,那么我可不可以先按照原来的我方法先进行configure,然后再对Makeconf文件进行修改呢?于是我还是先按照之前的方法进行configure

1
2
3
4
5
/builder/software/R-3.4.2/configure --prefix=/builder/software/R --en
able-R-shlib --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling LDFLAGS="-L/builder/software/zlib/lib -L/builder/software/bzip2/lib -L/builder/software/xz/lib -L/builder/software/pcre/lib -L/builder/so
ftware/curl/lib" CPPFLAGS="-I/builder/software/zlib/include -I/builder/softw
are/bzip2/include -I/builder/software/xz/include -I/builder/software/pcre/in
clude -I/builder/software/curl/include

然后在make之前修改Makeconf中的参数

1
LDFLAGS = -L/builder/software/zlib/lib  -L/builder/software/bzip2/lib   -L/builder/software/curl/lib -Wl,-rpath=/builder/software/xz/lib -Wl,-rpath=/builder/software/pcre/lib

再进行

1
make

之前的报错终于不见了!但是出现了新的报错心里有句mmp:

1
2
3
4
5
6
7
8
9
/usr/bin/ld: cannot find -lpcre
collect2: error: ld returned 1 exit status
make[3]: *** [libR.so] Error 1
make[3]: Leaving directory `/builder/software/R-3.4.2/src/main'
make[2]: *** [R] Error 2
make[2]: Leaving directory `/builder/software/R-3.4.2/src/main'
make[1]: *** [R] Error 1
make[1]: Leaving directory `/builder/software/R-3.4.2/src'
make: *** [R] Error 1

于是我在想,可能是前面我把LDFLAGS里面参数由-L/builder/software/pcre/lib修改为了-Wl,-rpath=/builder/software/pcre/lib之后不再出现原来的报错,但是现在又出现了新的报错,而我在使用原来的参数时不会出现这个新的报错,结合之前我搜索到的结果,是不是因为我之前的写法只能让路径gcc在编译时有效,而后来的写法只能让其在进行运行时有效?那么如果我让两种参数同时出现,虽然我把库的路径传递了两次,但是会不会就不再报错了?时间是检验真理的唯一标准!先试验一把!于是我把两种参数的路径都加到了Makeconf

1
LDFLAGS = -L/builder/software/zlib/lib  -L/builder/software/bzip2/lib -L/builder/software/xz/lib -L/builder/software/pcre/lib -L/builder/software/curl/lib -Wl,-rpath=/builder/software/xz/lib -Wl,-rpath=/builder/software/pcre/lib

再次进行

1
make

终于没有了报错。说明make成功了,于是我再进行

1
make install

终于安装完成!你挑着担我牵着马

总结

  1. 在Linux下用源码安装R是个大坑尤其是在没有root权限的情况下
  2. 安装R之前一定要将R要求的依赖库预先安装好,版本和安装顺序都要对。具体可以参考R官方文档R Installation and Administration
  3. 在安装好R的依赖库之后,在进行R的安装的时候要注意将依赖库的路径传入到参数中,而且一定要注意传入的方式。
  4. 注意分析报错信息,从中寻找原因,不要盲目瞎想,多谷歌,多问老司机。
  5. 关于-Wl -rpath更详细的介绍参考
------本文结束欢迎留言(你的邮箱将不会被显示)------