国产化麒麟linux系统开发编译常见问题汇总
团队自研股票软件关注威信龚总号:QStockView,下载
1 问题处理
1.1 Unknown module in QT:QJsonDocument
缺少 QJsonDocument
解决方法:
Pro 文件中加上 QT+=core;
播放器库问题
1.2 代码中汉字乱码需要设置文件编码格式
原因分析:
Window 系统默认的文件格式是 GBK,所以汉字可以直接显示;linux 文件默认格式是 UTF8,所以汉字显示乱码;
解决方法:
在 QtCreator 中,工具 - 选项 - 文本编辑器 - 行为将默认编码改成 GBK,保存后,再关闭原来打开的文件(打开的还是原来的 utf8,不会自动刷新),重新打开;中文就正常显示了;
1.3 Ui 文件无法编译问题
no rule to make target *.ui needed by
解决办法:
缺少 ui 文件,复制添加 ui 文件;
1.4 覆盖关于 moc_**.cpp 的配方
原因分析:
因为有两个不同路径下的同名文件,需要被加入到 pro 中,生成 makefile 时会产生错误;所以要重命名一个文件;
解决办法
重命名其中的一个文件,然后修改引用命名,再重新编译;
1.5 窗口句柄 long 转 Qjsonvalue 报错
将 long 型的 winid 插入 QjsonObject 时,出现报错,conversion from long int to QJsonValue is ambiguous;windows 系统下正常;
QJsonObject root;
root.insert("method", "getWndHandle");
root.insert("componentID", "AnalysisCenter");
QJsonObject data;
long id = this->winId();
data.insert("winId", id);
root.insert("data", data);
解决方法:
采用 Quint64 类型,并通过 QVairiant 进行转换;
1.6 linux 回调函数
解决办法
Int __stdcall recvcallback(int type)
换成 static __stdcall recvcallback(int type)
1.7 goto 无法识别使用
解决办法:
采用 do{}while(0) 和 break 代替;
1.8 信号槽枚举用 int 传递编译错误
Involid use of incomplete type
解决办法:
用 int 强制转换,并且包含 #include<QVariant>
1.9 linux QPrinter no such file or directory
HUI 报了 QPrinter 错误
解决办法:
在 pro 文件中添加 QT += printsupport
1.10 HUI 编译报错 UI_*.h No such file or directory
解决办法:
在 pro 文件中加入 HUIControl/GeneratedFiles,这些 ui_*.h 文件是 HUI 库的一些界面 ui 文件编译生成后的文件;
1.11 回调函数编译报错出现重复定义
解决办法:
将回调函数设置为 static 静态函数;
1.12 LibQtPrintSupport.so syntax error colloct2
:error:ld returned 1 exsit status
报错原因:从 windows 下经过压缩处理,然后放到 linux 下,文件系统不一样,so 文件结构被改变了
解决办法:
将 HUI 的压缩包放到麒麟 linux 系统下,然后用 zip HUIControl.zip 命令解压缩;
1.13 “undefined reference to `vtable for ……..”
QT 中, 类要支持信号与槽机制, 需要继承自 QObject 并在头文件开头添加 Q_OBJECT 宏. 如果使用 QtCreator 创建类时, 没有选择继承自 QObject 类或其子类, 而在创建后手工修改继承自 QObject 并手工添加 Q_OBJECT 宏, 则在编译时有可能会出现 "undefined reference to `vtable for’…" 错误.
解决方法:
把新创建的类从项目中移除 (注意不要从磁盘上删除), 编译,然后再添加进工程,QtCreator 就会重新解析此类, 再编译就不再会出现上述错误。
信号槽连接不能用
1.14 Undefined reference to **showEvent()
Undefined reference to **showEvent()
原因分析:
生成 pro 文件时包含了不需要的文件 rangemonthview.h
解决办法:
在 pro 文件中找到并去掉就可以了;
1.15 Multiple definition of ‘AddTaskItem’
多重定义问题,也没有发现有其他定义;
解决办法:
将文件名和类名改成其他名字之后,再重新编译,解决问题;
原因分析:AddTaskItem 的头文件件没有加条件编译,或者名称重复定义;
解决办法:
加上条件编译或者将类名改个名字 AddFileTaskItem
#ifndef AddTaskItem_H
#define AddTaskItem_H
……
#endif
1.16 This application failed to start because it could not find or load the Qt platform plugin "xcb"
nvmlInit Failed Graphics Memory May not abtain!
no nvmlDevice Found! Graphics Memory May not abtain
load libvaGLX failed!
hpr tls index{4}
This application failed to start because it could not find or load the Qt platform plugin "xcb"
in "".
Available platform plugins are: xcb, eglfs, linuxfb, minimal, minimalegl, offscreen, vnc.
Reinstalling the application may fix this problem.
已放弃
原因分析:
缺少 QT 的依赖库,或者 Qt 依赖库的版本和系统的 Qt 版本不匹配;
解决办法:
(1) 将file:///opt/soft/Qt5.9.6/5.9.6/gcc_64/plugins目录下 platforms 文件夹复制到程序运行目录;
(2) 使用自动打包脚本将 xcb 依赖的库文件复制到 lib
终端执行命令:./copylib.sh libqxcb.so,生成 lib 文件夹,将 lib 文件夹内的 lib 文件复制到运行目录;
打包脚本如下所示:
#!/bin/bash
LibDir=$PWD"/lib"
Target=$1
lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))
$(mkdir $LibDir)
for Variable in ${lib_array[@]}
do
cp "$Variable" $LibDir
done
#$
(3) 采用同样的方法的生成可执行程序的依赖库,然后也复制到运行目录;
(4) lib 文件夹下面的有些库不能删除,这些事 HUI 依赖的库文件,如下图所示:
如果删除了这些文件,会报如下错误;
1.17 undefined symbol: _ZdlPvm, version Qt_5
undefined symbol: _ZNK15QDateTimeParser5parseER7QStringRiRK9QDateTimeb, version Qt_5_PRIVATE_API (./libQt5Widgets.so.5)
undefined symbol: _ZN15QHighDpiScaling6originEPK7QScreen, version Qt_5_PRIVATE_API (./libQt5Widgets.so.5)
undefined symbol: _ZdaPvm, version Qt_5 (./libQt5Widgets.so.5)
undefined symbol: _ZN15QHighDpiScaling6factorEPK7QScreen, version Qt_5_PRIVATE_API (./libQt5Widgets.so.5)
undefined symbol: _ZN15QHighDpiScaling6factorEPK7QWindow, version Qt_5_PRIVATE_API (./libQt5Widgets.so.5)
undefined symbol: _ZdlPvm, version Qt_5 (./libQt5Widgets.so.5)
undefined symbol: _ZdlPvm, version Qt_5 (./libQt5PrintSupport.so.5)
undefined symbol: _ZdlPvm, version Qt_5 (./libQt5Sql.so.5)
undefined symbol: _ZdlPvm, version Qt_5 (./libQt5Svg.so.5)
undefined symbol: _ZdlPvm, version Qt_5 (./AnalysisCenter)
undefined symbol: _ZdaPvm, version Qt_5 (./AnalysisCenter)
原因分析:
Qt 安装的版本和系统使用的 QT 版本不一致,程序运行默认先从系统的 file:///lib/x86_64-linux-gnu 目录查找动态库,编译的使用了 Qt5.9.6,而系统目录是 Qt5.12.0 的版本,所以会出现未定义的错误;不能替换系统目录下的 Qt 库,否则系统会崩溃(别问我怎么知道的);
解决办法:
(1) 使用 ldd –r AnalysisCenter 命令查看可执行程序的依赖库,是不是指向file:///lib/x86_64-linux-gnu;如果是,则说明程序运行引用的动态库是系统的 Qt 库,如果编译的 QT 库和系统不匹配,则会报错;
(2) 复制 Qt5.9.6 的库文件到运行目录,然后创建软连接 libQtWidget.so.5 链接到运行目录的 libQtWidget.so 库;(我是直接将 HUIDemo 中的 QT 文件直接复制到运行目录,即可运行)
1.18 failure to convert GBK to UTF-8
converting to execution chatracter set invalid or incomplete multibyte or wide byte
cc1plus: error: failure to convert GBK to UTF-8
界面出现乱码
使用 file –b 查看文件的编码格式;
file -b AddClusterTask.cpp
发现是 ASCII 编码,所以先要对文件编码格式进行转换,可以用 iconv 命令去转换文件编码格式;
1.19 No rule to make target
'AnalysisCenter_gch1.0.0/src/AddClusterTask', needed by 'GeneratedFiles/AddClusterTask.o'. Stop.
原因分析:
文件没有找到
解决办法:
在 pro 文件中删除不存在或者删除的掉的文件;
1.20 界面上代码设置的汉字为乱码
Ui 文件中设置的汉字都可以正常显示,但是从 VS2015 复制过去的 *.cpp 文件中通过代买 setText() 设置的汉显示的都是乱码;如下图所示:
原因分析:
VS2015 默认的文件编码格式是 ANSI(GBK)编码格式,而麒麟 Linux 默认的是 UTF-8 的文件编码格式,linux 在编译的时候以 UTF-8 的格式去读取文件,导致中文乱码;
解决方法:
在 Linux 系统,将包含中文的文件的编码格式修改为 UTF-8;
(1)查看文件编码格式
文件编码格式查看命令:file filename 查看文件编码
(2)修改文件的编码格式
1)在 vim 中使用 :set fileencoding= UTF-8 来转换文件的编码格式;
2)文件编码格式批量转换命令: find *.cpp -exec sh -c "iconv -f GBK -t UTF-8 {} > ./UTF8Temp/{}" \;
报错:find: 遗漏“-exec”的参数错误
是因为./UTF8Temp/{}" \; 最后反斜杠之前少了空格,加个空格即可;
(3)再 pro 文件中加入编译参数
QMAKE_CXXFLAGS +=-finput-charset=UTF-8 -fexec-charset=utf-8
(4)将转码后的文件替换到原来的文件,然后再重新编译;
会出现如下的错误,这个错误原因是文件中有些中文字符无法识别,导致无法转换,转换后的文件数据丢失,丢了一半;如果源文件格式不是 GBK,则转换之后的文件只有 3 字节,所以先找到 3 字节的文件,用源文件替换;
如果之前通过 vim 将文件格式改为 utf-8,现在用批量命令去转,发现之前转为 utf-8 的 AddClusterTask.cpp 文件会出现转换失败,只有 3 字节的结束标志;所以要统一用批量命令去转;而且转换不能直接覆盖,要转码到 UTF8Temp 文件夹下,然后保存原 cpp 文件,然后再替换转换后文件;
用 iconv 命令转码的文件,有时会出现问题,只转了一半;后面的代码丢失了,导致无法编译通过;将有问题的文件通过 vim 逐个设置格式;或者单独用 iconv 命令进行转换;iconv -f GBK -t UTF-8 main.cpp >./UTF8Temp/main.cpp;保障转换前后的文件大小相等;
1.21 常量中有换行符错误
将 linux 中编译通过的文件,复制到 window 系统 vs2015 中再次进行编译,发现会出现所有中文的地方都会报错“常量中有换行符错误”;
原因分析:
Linux 中文件转换为了 utf8 编码,转到 window 中,默认的编码是 GBK,所以中文位置会出现换行符;
解决方法:
将文件保存为 utf8 带标签格式;
1.22 该字符在当前源字符集中无效
warning C4828: 文件包含在偏移 0x13c9 处开始的字符,该字符在当前源字符集中无效 (代码页 65001)。
解决办法
可以下载转码工具
批量将文件转码为 utf-8 bom 格式;并且将命令行参数 /utf-8 改为 /execution-charset:utf-8。也就是执行字符集保存为 u8,源文件不去要求 utf8;
1.23 error LNK2005u* 已经在 * 定义
error LNK2005: SU_ControlWrite_HID 已经在 LicenseVerify.lib(SRUsbToken.obj) 中定义
原因分析
连接的时候会链接多个,链接器无法取舍;
解决方法
在链接器命令行加上 /force:multiple ,意思是是出现多个,强制链接多个;
1.24 Linux 和 window 同时兼容中文不乱码
Linux 中文不乱码的要求是文件采用 utf8 编码格式; QMAKE_CXXFLAGS +=-finput-charset=UTF-8 -fexec-charset=utf-8
编译参数要加上 window 中文不乱码要求在每个源文件头部加上宏定义 #pragma execution_character_set("utf-8"),或者在编译命令行中输入:/execution-charset:utf-8,若只需要修改源代码的编码,也可以只输入:/source-charset:utf-8
/utf-8 相当于同时设置源代码和可执行文件。
解决 cpp,h 文件全部采用 utf8 bom 编码格式;可以用 vs2015 的高级保存选项,也可以用批量转码工具转测 utf8bom;linux 的编译命令参数加上 QMAKE_CXXFLAGS +=-finput-charset=UTF-8 -fexec-charset=utf-8。这样在 Linux 环境下就可以实现中文显示;在 vs2015 代码中有设置中文的 cpp 文件中加入宏定义 #pragma execution_character_set("utf-8"),或者在编译命令行中输入:/execution-charset:utf-8,
1.25 Could not connect to any X display
麒麟系统中执行./AnalysisCenter 出现无法打开桌面应用,安装图形桌面后,Linux 通过终端命令无法启动图形应用,报错“Could not connect to any X display.”或“Gtk-WARNING **: 10:49:06.625: cannot open display: :0”等。
是因为用户没有显示权限,需要执行命令 xhost 获取可以访问当前主机上的增强 X-Windows 显示权限,之后就可以打开了;
1.26 执行软件报权限不够错误
银河麒麟系统安装后,没有可执行权限,运行 bash 或者二进制程序都提示 bash 权限不够或者类似报错
解决方法
执行 sudo setstatus softmode -p 即可,如下图所示:
sudo setstatus softmode -p
1.27 设置透明和阴影的窗口变成了黑色
为了实现弹出窗口边框周围带阴影的效果;采用外层设置透明,内层边缘显示阴影;代码如下。但是在 window 下可以,在麒麟系统中,透明部分的窗口直接变为黑色;setAttribute(Qt::WA_TranslucentBackground); 不生效了;
setWindowModality(Qt::ApplicationModal);
setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint | Qt::SubWindow);
setAttribute(Qt::WA_TranslucentBackground); // 背景透明
// 边框阴影效果
m_ShadowEffect = new QGraphicsDropShadowEffect(ui.widget);
m_ShadowEffect->setBlurRadius(34);
m_ShadowEffect->setColor(QColor(0, 0, 0, 51));
m_ShadowEffect->setOffset(0, 12);
ui.widget->setGraphicsEffect(m_ShadowEffect);
setFocusPolicy(Qt::StrongFocus);
解决方法:
是因为使用的麒麟系统不支持透明阴影等渲染效果,需要安装一个软件 xcompmgr。Xcompmgr 是一个简单的混合窗口管理器,可以实现阴影、原生窗口透明(配合 transset 工具)等特效。Xcompmgr 设计初衷只是实现混合窗口管理器的概念,所以比起同类混合窗口管理器如 Compiz Fusion,Xcompmgr 轻量许多。Xcompmgr 不替代任何窗口管理器,所以对于 Openbox 和 Fluxbox 这类缺乏特效的窗口管理器来讲,配合 Xcompmgr 能得到更华丽的视觉效果。
执行如下命令安装软件
sudo apt-get install xcompmgr
然后再输入 xcompmgr ,启动 xcompmgr(关闭终端);
或者设置 xcompmgr 开机自启动
再次打开程序, 就可以正常显示了;
1.28 字节对齐方式不同导致协议发送解析错误
通过 Socket TCP 发送消息,实现进程间的通讯,突然消息解析报错 ,协议头的结构体的长度不一致;
例如下面的的结构定义,在 window 系统中,结构体大小是 12 字节;但是在 linux 系统中,是以最大的变量长度对齐,最大的是 unsigned long 4 字节,所以结构体的大小是 4*4+4+4=24 字节;
struct msg_header
{
char head[4];
unsigned long pack_len;
int code;
msg_header()
{
head[0] = 'H';
head[1] = 'K';
head[2] = 'P';
head[3] = '&';
}
};
解决方法
为了实现同样是 16 字节,需要在结构体定义中加上 #pragma pack(push,1); 表示按照 1 字节对齐; #pragma pack() 则是取消字节对齐设置,避免对其他的结构体造成影响;
// 协议头对齐方式
#pragma pack(push,1)
struct msg_header
{
char head[4];
unsigned long pack_len;
int code;
msg_header()
{
head[0] = 'H';
head[1] = 'K';
head[2] = 'P';
head[3] = '&';
}
};
#pragma pack()// 取消对齐,避免对其他造成影响
1.29 Ssh 无法连接服务
没有安装或者驱动 ssh 服务
1.29.1 安装
sudo yum install sshd
sudo yum install openssh-server
sudo apt-get install sshd
sudo apt-get install openssh-server
1.29.2 启动
sudo service ssh start
1.30 Qtcreator Could not determine which "make"
重新安装了麒麟系统,安装了 QtCreator 之后,原先可以正常编译的工程,突然不能编译了;报错如下
20:28:00: Could not determine which "make" command to run. Check the "make" step in the build configuration.
Error while building/deploying project AnalysisCenter (kit: Desktop Qt 5.9.6 GCC 64bit)
When executing step "qmake"
原因分析:
缺少了 G++ 编译器;
解决方法:
安装 G++ 编译器,充电线 USB 插到 PC 设备上面,手机去设置 -》USB 共享网络 -》USB 共享网络;执行 sudo apt-get install build-essential
或者下载 G++ 软件包去安装:build-essential_12.8kylin1_amd64.deb