移植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, 而实际的低于这个版本,所以导致导入失败。
在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,运行程序,错误依旧。
问题还是在代码里面,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个星期,今天终于算是有了一个进步。