记一次debug

问题描述

移植Qt5.5.1到 hisiv400嵌入式开发板,之前的工作包括:
1. 搭建嵌入式开发环境(boot, kernel, fs && 交叉编译环境)
2. 获取Qt5.5.1源码
3. 配置mkspecs文件
4. 设置configure参数

移植Qt到嵌入式平台,最大的问题,就是platform plugin问题,即告诉Qt调用嵌入式平台支持的方式渲染窗口,因为板卡自身不带窗口。

我的情况:EGL && mali

后两步的细节移步这里。

接着执行:

./configure -v ...
make -j5
make install

把相关文件部署到板子上,配置板子的环境变量

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/duino/lib:/mnt/duino/qt5/lib

export QTDIR=/mnt/duino/qt5
export QT_QPA_FONTDIR=/mnt/duino/qt5/lib/fonts
export QT_QPA_PLATFORM_PLUGIN_PATH=/mnt/duino/qt5/plugins
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_FB=/dev/fb0
export QT_QPA_EGLFS_WIDTH=1280
export QT_QPA_EGLFS_HEIGHT=720
export QT_QPA_EGLFS_DEPTH=32
export QT_QPA_EGLFS_DEBUG="yes"
export QT_QPA_EGLFS_INTEGRATION=eglfs_mali

运行Qt demo(qtbase/examples/widgets/widgets/analogclock

./analogclock

配置了QT_QPA_PLATFORM变量,可以省略”-platform eglfs”。

...
Failed to load libGLESv2
Aborted.

就这样不动声色地,毫无征兆地,不知不觉地,出错了。

定位问题

加载库文件失败,这个问题说明它找到了库,只是没有成功加载。说明问题出在程序里面。

Qt依赖三个与窗口渲染有关的外部库libEGL.so, libGLESv2.so, libmali.so

库文件是在程序运行时加载的,那么,这条错误语句,肯定可以在Qt源码里面找到。

cd .../qtbase/src
find . | xargs grep "Failed to load libGLESv2" -r

果然找到了,它出现在qtbase/src/gui/opengl/qopenglfunctions.cpp文件中,QOpenGLES3Helper的构造函数里面。

继续往里面寻找,找到这个函数:

bool QOpenGLES3Helper::init()
{
#ifndef Q_OS_IOS
# ifdef Q_OS_WIN
#  ifndef QT_DEBUG
    m_gl.setFileName(QStringLiteral("libGLESv2"));
#  else
    m_gl.setFileName(QStringLiteral("libGLESv2d"));
#  endif
# else
#  ifdef Q_OS_ANDROID
    m_gl.setFileName(QStringLiteral("GLESv2"));
#  else
    m_gl.setFileNameAndVersion(QStringLiteral("GLESv2"), 2);
#  endif
# endif // Q_OS_WIN
    return m_gl.load();
#else
    return true;
#endif // Q_OS_IOS
}

由于Qt跨平台,所以源码里面有各种预编译命令,习惯就好。

在这个函数上面,看到一段话:

// Functions part of the OpenGL ES 3.0+ standard need special handling. These,
// just like the 2.0 functions, are not guaranteed to be resolvable via
// eglGetProcAddress or similar. Calling them directly is, unlike the 2.0
// functions, not feasible because one may build the binaries on a GLES3-capable
// system and then deploy on a GLES2-only system that does not have these
// symbols. Until ES3 gets universally available, they have to be dlsym'ed.

大概是说OpenGL ES 3.0 和 2.0的兼容性方面的问题。

我一直特别纳闷,为啥我使用的是libGLESv2,会出现QOpenGLES3Helper。我怀疑是不是开始配置的时候,告诉了Qt适配高版本的OpenGL ES, 而实际的低于这个版本,所以导致导入失败。

解决问题

尝试1

在configure的时候,禁止适配高版本的OpenGL ES3。撸起袖子改代码。

打开configure文件,找到下面这段,注释掉。

# If OpenGL ES 2.0 is enabled, check for 3.0 and higher. This is used to allow
# compile-time differentiation and including the version specific (but backwards
# compatible) ES headers (for example, GLES3/gl31.h). Other than that, there is
# no difference in the configuration, even the library is the same.
#if [ "$CFG_OPENGL" = "es2" ]; then
#    if compileTestWithPkgConfig glesv2 unix/opengles3 "OpenGL ES 3.0" ""; then
#        # Add a define for ES3, in addition to ES and ES2.
#        QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_ES_3"
#    fi
#    if compileTestWithPkgConfig glesv2 unix/opengles31 "OpenGL ES 3.1" ""; then
#        # Add a define for ES31.
#        QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_ES_3_1"
#    fi
#fi

之后再./configure && make && make install,运行程序,错误依旧。

尝试2

问题还是在代码里面,QOpenGLES3Helper::init()里的load()失败了,原因可能是版本的问题。把这个函数里的这句话:

m_gl.setFileNameAndVersion(QStringLiteral("GLESv2"), 2);

换成下面几种形式试一试:

m_gl.setFileNameAndVersion(QStringLiteral("GLESv2"), 1);
m_gl.setFileNameAndVersion(QStringLiteral("GLESv2"), 0);
m_gl.setFileName(QStringLiteral("GLESv2"));

第三种设置的方式成功了!!!!!!

当看到连接嵌入式板卡的显示器,显示Qt应用程序的那一刻,突然感觉,整个世界都美好了,简直太棒了!!! 如果拍照方便的话,我肯定贴一张显示器的图片了~毕竟移植Qt这件事情,干了有3个星期,今天终于算是有了一个进步。

你可能感兴趣的:(qt源码_移植)