QEMU 编译报错 undefined reference to g_app_info_launch_default_for_uri_finish 解决过程

· Frytea · 5 分钟 · 技术笔记
QEMU 编译报错 undefined reference to g_app_info_launch_default_for_uri_finish 解决过程

编译 QEMU 时报如下错误:

/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_app_info_launch_default_for_uri_finish'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_type_check_instance_is_fundamentally_a'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_app_info_launch_default_for_uri_async'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_strv_contains'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_list_model_get_type'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_drive_is_removable'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_application_get_resource_base_path'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_log_structured_standard'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_type_get_instance_count'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_list_model_get_n_items'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_file_enumerator_iterate'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_param_spec_get_name_quark'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libgtk-3.so: undefined reference to `g_list_model_get_item'
collect2: error: ld returned 1 exit status
make[1]: *** [qemu-system-x86_64] Error 1
make: *** [subdir-x86_64-softmmu] Error 2

先看一下报错的动态链接库依赖了哪些库:

$ ldd /lib64/libgtk-3.so       
        linux-vdso.so.1 =>  (0x00007ffc89762000)
        libgdk-3.so.0 => /lib64/libgdk-3.so.0 (0x00007f19938ab000)
        libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x00007f19936a7000)
        libpangocairo-1.0.so.0 => /lib64/libpangocairo-1.0.so.0 (0x00007f1993499000)
        libX11.so.6 => /lib64/libX11.so.6 (0x00007f199315b000)
        libXi.so.6 => /lib64/libXi.so.6 (0x00007f1992f4b000)
        libXfixes.so.3 => /lib64/libXfixes.so.3 (0x00007f1992d45000)
        libcairo-gobject.so.2 => /lib64/libcairo-gobject.so.2 (0x00007f1992b3c000)
        libcairo.so.2 => /lib64/libcairo.so.2 (0x00007f1992805000)
        libgdk_pixbuf-2.0.so.0 => /lib64/libgdk_pixbuf-2.0.so.0 (0x00007f19925dd000)
        libatk-1.0.so.0 => /lib64/libatk-1.0.so.0 (0x00007f19923b7000)
        libatk-bridge-2.0.so.0 => /lib64/libatk-bridge-2.0.so.0 (0x00007f1992188000)
        libwayland-client.so.0 => /lib64/libwayland-client.so.0 (0x00007f1991f79000)
        libepoxy.so.0 => /lib64/libepoxy.so.0 (0x00007f1991c4d000)
        libpangoft2-1.0.so.0 => /lib64/libpangoft2-1.0.so.0 (0x00007f1991a37000)
        libpango-1.0.so.0 => /lib64/libpango-1.0.so.0 (0x00007f19917f1000)
        libfontconfig.so.1 => /lib64/libfontconfig.so.1 (0x00007f19915af000)
        libgio-2.0.so.0 => /lib64/libgio-2.0.so.0 (0x00007f199120f000)
        libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x00007f1990fbe000)
        libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007f1990ca8000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f19909a6000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f199078a000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f19903bc000)
        libXinerama.so.1 => /lib64/libXinerama.so.1 (0x00007f19901b9000)
        libXrandr.so.2 => /lib64/libXrandr.so.2 (0x00007f198ffae000)
        libXcursor.so.1 => /lib64/libXcursor.so.1 (0x00007f198fda3000)
        libXcomposite.so.1 => /lib64/libXcomposite.so.1 (0x00007f19

观察输出,所有依赖的动态链接库都有指向一个内存地址,说明所依赖的链接库都已经被加载入内存,排除了链接库不存在情况,下面就有可能是某个链接库有问题了,接下来做两件事:

  • 使用 objdump -T <lib name and path> |grep <funcname> 命令检索报错函数属于哪一个链接库;
  • 使用 find / -name <lib name> 命令查找是否有哪一个报错链接库在系统的动态链接库搜索目录中有多个;

经过一番检索,发现 [libgio-2.0.so](http://libgio-2.0.so) 在系统so检索目录有两个,分别是 /usr/local/lib/libgio-2.0.so/lib64/libgio-2.0.so ,其中 /lib64 为系统默认链接库存放位置,而 /usr/local 为编译安装库的默认安装位置,移除/usr/local/lib/libgio-2.0.so 之后再次尝试编译发现报错减少了。

此时发现系统曾编译安装了 glib ,可能是那时引入了一些错误的 so 库,因此进入编译目录 make uninstall 移除此前安装的错误的库,再次尝试编译发现编译通过。

总结

本次编译错误排查了很久,最后在大佬的协助下终于解决,此类缺少依赖错误排查错误思路可以总结为 检查链接库是否存在 -> 检查是否存在重复链接库 -> 移除错误链接库

参考文献