解决libGL.so.1: undefined symbol: _glapi_Dispatch

前言

最近在Ubuntu下安装LeapMotion的SDK,其中需要安装依赖库Mesa OpenGL。安装完成之后,运行LeapMotion的Visualizer时出现下面的错误:

1
Visualizer: symbol lookup error: /usr/local/lib/libGL.so.1: undefined symbol: _glapi_Dispatch

在这里记录一下折腾的过程和最终的解决方法。

系统:Ubuntu 14.04 LTS
Mesa-11.2.2
LeapMotion SDK Linux 2.3.1+31549

分析和尝试

按照上面错误,应该是在libGL.so.1里面找不到符号_glapi_Dispatch,因此首先分析一下libGL.so.1:

1
nm -D /usr/local/lib/libGL.so.1 | grep glapi

nm命令用来列出目标文件的符号清单,上述命令运行的结果如下:

1
2
3
4
5
6
7
8
                  U _glapi_check_multithread
0000000000000000 A _glapi_Dispatch
U _glapi_get_dispatch
U _glapi_get_dispatch_table_size
U _glapi_get_proc_address
U _glapi_get_proc_offset
U _glapi_set_context
U _glapi_set_dispatch

其中U和A是输出符号类型说明,A表示“该符号的值是绝对的,在以后的链接过程中,不允许进行改变”,U表示“该符号在当前文件中是未定义的,即该符号的定义在别的文件中”。
可以看到_glapi_Dispatch的值是固定的,且为0,这应该是不正常的。

在Mesa编译的时候,编译目录下也生成了libGL.so.1文件,分析一下该文件的符号:

1
nm -D lib/libGL.so.1 | grep glapi

1
2
3
4
5
6
7
8
U _glapi_check_multithread
U _glapi_Dispatch
U _glapi_get_dispatch
U _glapi_get_dispatch_table_size
U _glapi_get_proc_address
U _glapi_get_proc_offset
U _glapi_set_context
U _glapi_set_dispatch

可以看到_glapi_Dispatch的类型和/usr/local/lib/libGL.so.1是有区别的。因此想试一下直接把这文件替换过去,看能不能解决问题:

1
sudo cp lib/libGL.so.1 /usr/local/lib/

此时运行Visualizer,依然有错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
X Error of failed request: GLXBadContext
Major opcode of failed request: 154 (GLX)
Minor opcode of failed request: 6 (X_GLXIsDirect)
Serial number of failed request: 40
Current serial number in output stream: 39
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 154 (GLX)
Minor opcode of failed request: 24 (X_GLXCreateNewContext)
Value in failed request: 0x0
Serial number of failed request: 39
Current serial number in output stream: 40

解决方法

在搜索上面出现的错误时,找到了这个回答:Problems with libGl, fbConfigs, swrast through each update?,使得最后解决了所有问题。

The swrast thing is the software renderer. That means it’s not finding the hardware driver for your graphics card. There’s a bunch of libGL libraries installed and a bunch of of symbolic links to those libraries. To see these run this from the cmd line.

1
sudo find /usr -iname "*libGL.so*" -exec ls -l {} \;

上面命令的运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
lrwxrwxrwx 1 root root 14  518 16:42 /usr/local/lib/libGL.so.1 -> libGL.so.1.2.0
-rwxr-xr-x 1 root root 3520318 518 16:42 /usr/local/lib/libGL.so.1.2.0
lrwxrwxrwx 1 root root 14 518 16:42 /usr/local/lib/libGL.so -> libGL.so.1.2.0
lrwxrwxrwx 1 root root 19 419 21:41 /usr/local/MATLAB/R2015b/sys/opengl/lib/glnxa64/libGL.so.1 -> libGL.so.1.5.070200
-r-xr-xr-x 1 root root 3200281 730 2015 /usr/local/MATLAB/R2015b/sys/opengl/lib/glnxa64/libGL.so.1.5.070200
lrwxrwxrwx 1 root root 14 419 23:11 /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 -> libGL.so.1.2.0
-rw-r--r-- 1 root root 582136 116 05:09 /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0
lrwxrwxrwx 1 root root 14 113 04:03 /usr/lib/x86_64-linux-gnu/mesa/libGL.so -> libGL.so.1.2.0
lrwxrwxrwx 1 root root 13 113 04:03 /usr/lib/x86_64-linux-gnu/libGL.so -> mesa/libGL.so
-rw-r--r-- 1 root root 1218248 118 2015 /usr/lib/nvidia-352/libGL.so.352.63
lrwxrwxrwx 1 root root 15 1117 2015 /usr/lib/nvidia-352/libGL.so.1 -> libGL.so.352.63
lrwxrwxrwx 1 root root 10 1117 2015 /usr/lib/nvidia-352/libGL.so -> libGL.so.1
-rw-r--r-- 1 root root 1047532 118 2015 /usr/lib32/nvidia-352/libGL.so.352.63
lrwxrwxrwx 1 root root 15 1117 2015 /usr/lib32/nvidia-352/libGL.so.1 -> libGL.so.352.63
lrwxrwxrwx 1 root root 10 1117 2015 /usr/lib32/nvidia-352/libGL.so -> libGL.so.1

可以看到有很多不同版本的库文件,所以解决方法就是使/usr/local/lib/libGl.so.1指向正确的文件:

1
2
sudo rm /usr/local/lib/libGL.so.1
sudo ln -s /usr/lib/nvidia-352/libGL.so.1 /usr/local/lib/libGL.so.1

经过上面这个命令之后,问题解决。