百度aistudio 安装 pycorrecotor

背景

百度aistudio提供的notebook juypter 免费提供CPU/GPU 资源,可以比较方便的做算法测试。同时提供了aistudio 提供了直接访问服务器的terminal,可以直接登录到虚拟机上安装相关依赖,这个操作比Google的colab只能在notebook上操作要方便不少。但是百度为了推广自家的paddle(飞桨框架),禁止了TensorFlow/pytorch等DeepLearning框架。 虚拟机的shell也禁用了root权限,那么就不能直接执行sudo apt-get install 之类的需要root权限的命令了。

实验

现在有一个在notebook jupyter上安装pycorrector的需求,直接pip install pycorrector 但是在自动安装依赖kenlm时报错,kenlm是c++扩展,在gcc 编译时,出现gcc: error trying to exec 'cc1plus': execvp: No such file or directory 这样的错误提示。(By the way, 在Google的colab上可以直接安装) 查看gcc的版本

aistudio@jupyter-104673-1192555:~$ gcc --version  
gcc (Ubuntu 7.5.0-3ubuntu1~16.04) 7.5.0  
Copyright (C) 2017 Free Software Foundation, Inc.  
This is free software; see the source for copying conditions.  There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

aistudio@jupyter-104673-1192555:~$ g++ --version  
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609  
Copyright (C) 2015 Free Software Foundation, Inc.  
This is free software; see the source for copying conditions.  There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

发现gcc 跟 g++的版本不一致,这里简单解释一下cc1plus的用途:

The g++ is a compiler driver. It knows how to invoke the actual compiler (cc1plus), assembler and linker. It does not know how to parse or compile the sources.

g++只是编译器的驱动,它只知道如何去调用实际的编译器(cc1plus)、汇编器以及链接器。但是不知道如何去编译源代码。

参考:https://stackoverflow.com/questions/19899750/what-is-the-difference-between-gcc-g-and-cc1-cc1plus

想到把g++升级到7.5.0,网上很多使用apt-get命名去升级的方案,在这里都不能使用,因为没有root权限。:)

那么只能手动源码安装了,下面说一下步骤:

  • 下载gcc-7.5.0源码
http://mirrors.ustc.edu.cn/gnu/gcc/gcc-7.5.0/gcc-7.5.0.tar.gz  

这里使用了中科大的镜像源,比国外的源要快很多,后面也会用到

  • 解压编译源码
tar xvf gcc-7.5.0.tar.gz  
cd gcc-7.5.0  
# 下载依赖
./contrib/download_prerequisites

发下基本不动,因为使用了国外的额源,下载依赖包的速度太慢了。 看一下download_prequisites源码,

gmp='gmp-6.1.0.tar.bz2'  
mpfr='mpfr-3.1.4.tar.bz2'  
mpc='mpc-1.0.3.tar.gz'  
isl='isl-0.16.1.tar.bz2'

base_url='ftp://gcc.gnu.org/pub/gcc/infrastructure/'

echo_archives() {  
    echo "${gmp}"
    echo "${mpfr}"
    echo "${mpc}"
    if [ ${graphite} -gt 0 ]; then echo "${isl}"; fi
}

重点是上面的几个文件,可以先下载到当前gcc-7.5.0目录。 可以使用上面提到的中科大镜像源wget先下载,镜像站没有的包,可以到源站wget下载。再执行./contrib/dowload_prerequisites,有如下提示:

gmp-6.1.0.tar.bz2: OK  
mpfr-3.1.4.tar.bz2: OK  
mpc-1.0.3.tar.gz: OK  
isl-0.16.1.tar.bz2: OK  
All prerequisites downloaded successfully.  

说明依赖已经安装好了,接下来就行configure跟编译了。

首先创建一个用于存放编译文件的目录build, 进入build目录,执行上级目录的configure命令。

这里需要注意一点,在configure的时候,一定要用--prefix指定有权限install相关可执行文件以及lib文件的目录。 比如:在aistudio中的work/gcc-install, 笔者就没有指定,结果是默认的目录/usr,可想而知,肯定没有权限install。结果后面要用很多trick来解决后面用到各种依赖的问题,在下面会说到。

# 完整命令
mdir build  
cd build  
../configure --prefix ~/work/gcc-install -enable-checking=release -enable-languages=c,c++ -disable-multilib 
  • 接下来就是编译安装了
make -j 30

make install  

正常情况install目录有权限的话,make install应该就结束了。

但是笔者之前没有配置prefix,结果要install到一个没有权限的默认/usr目录。所以现在没法make install。因为编译过的过程太慢长了,所以不想重新configure,重新编译。

好在,源码已经编译好了。配置环境变量:

# gcc、g++在这个目录
export PATH=/home/aistudio/gcc-7.5.0/build/gcc/:$PATH

# 看一下是否生效
which gcc  
which g++  
# 查看版本
aistudio@jupyter-104673-1192555:~/kenlm-master$ g++ --version  
g++ (GCC) 7.5.0  
Copyright (C) 2017 Free Software Foundation, Inc.  
This is free software; see the source for copying conditions.  There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  • 手动安装pycorrector的依赖kenlm
wget https://github.com/kpu/kenlm/archive/master.zip  
unzip master.zip  
cd kenlm-master  
python setup install  

不再提示找不到cc1plus,出现了各种找不到头文件的错误信息,说明cc1plus已经能找到了,进入准备编译的阶段了。

根据提示信息,find gcc-7.5.0 -name "xx.hh"查找到各个头文件的目录,这里也有很多坑,因为一个文件所在的目录不一样,虽然文件名一样,但是代码可能是不一样的。笔者在这里踩了不少坑,不断尝试终于找到所有头文件的目录。

gcc 在编译的时候可以用 gcc -I your_headers_dir,指定include的查找路径。

修改 setup.py

# 踩坑之后,找到了所有以来的定义目录
ss = '-I ../gcc-7.5.0/build/gcc/include/ -I ../gcc-7.5.0/libstdc++-v3/include/std/ -I ../gcc-7.5.0/libstdc++-v3/include -I ../gcc-7.5.0/libstdc++-v3/libsupc++/ -I ../gcc-7.5.0/build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/ -I ../gcc-7.5.0/libstdc++-v3/libsupc++/ -I ../gcc-7.5.0/build/x86_64-pc-linux-gnu/libstdc++-v3/include -I ../gcc-7.5.0/build/gcc/include-fixed/ -L ../gcc-7.5.0/build/gcc/'

#print(ss.split(' '))
ss = ss.split(' ')  
s1 = []  
for i in range(0,len(ss),2):  
        #print(i)
        s1.append(ss[i]+ss[i+1])
#print(s1)
#s1 = []

ARGS = ['-O3', '-DNDEBUG', '-DKENLM_MAX_ORDER='+max_order, '-std=c++11']  
# 通过ARGS参数传递给gcc命令
ARGS += s1  
print(ARGS)  

再次执行python setup.py install,正常编译了一小会,但是抛出错误提示:

gcc: fatal error: -fuse-linker-plugin, but liblto_plugin.so not found  

看来是没后找到liblto_plugin.so这个库,find 了一下,发现有这个文件./build/gcc/liblto_plugin.so。无论用 gcc -L ./build/gcc/,增加一个链接库的查找路径,还是把路径增加到PATH变量,都并不起作用。

aistudio@jupyter-104673-1192555:~/gcc-7.5.0$ /usr/bin/gcc -print-file-name=liblto_plugin.so  
/usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so

用系统默认的/usr/bin/gcc 能够查找到liblto_plugin.so,但用刚编译的gcc确找不到此文件。

使用gcc -print-serach-dirs,发现有搜索类似这样的路径:

libraries =/home/aistudio/gcc-7.5.0/build/gcc/../lib/gcc/x86_64-pc-linux-gnu/7.5.0//home/aistudio/gcc-7.5.0/build/gcc/../lib/gcc/x86_64-linux-gnu//home/aistudio/gcc-7.5.0/build/gcc/../lib/gcc//home/aistudio/gcc-7.5.0/build/gcc/../lib/gcc/

所以,直接在gcc下创建了lib目录,把gcc目录拷贝到lib目下。 再执行gcc -print-file-name=liblto_plugin.so

aistudio@jupyter-104673-1192555:~/gcc-7.5.0$ gcc -print-file-name=liblto_plugin.so  
/home/aistudio/gcc-7.5.0/build/gcc/../lib/gcc/liblto_plugin.so

可以正常找到liblto_plugin.so, 再次python setup.py install, 可以正常编译安装kenlm了。

另外,笔者在发现默认的/usr/bin/gcc 可以找到liblto_plugin.so的时候,尝试把编译好的gcc改为gcc_bak,让gcc命令使用的是/usr/bin/gcc,也可以正常编译kenlm。

然后就可以在notebook上, !pip install pycorrector

到此,整个踩坑结束。