Window下Qt无法加载动静态库解决方案


加载示例代码

# 请配置 Mysql 的包含库路径
win32:INCLUDEPATH  += "D:/Mysql/mysql-5.7.15-win32/include"
# 请配置 Mysql 的静态库路径
win32:LIBS += "-LD:/Mysql/mysql-5.7.15-win32/lib" -llibmysql

静态库标示符注意事项

-L :后面要跟的是lib文件的路径名,不可以有空格。

-l  :后面跟的是要加载的静态库lib文件名,是文件名,不要加后缀名,要链接着写,别加空格。


Qt帮助文档

双击选中关键字 "LIBS"  || “INCLUDEPATH”  按下键盘的F1键 调用 Qt自带的帮助文档。


加载不到静态库情形 


1、空格路径

LIBS    += "-LE:\Work For Chenluyong\znjd_20161213\Code\External\bin"  -lSystemModule_znjd

路径中存在空格时,务必用双引号包裹起来。


2、L与l

-L : 跟的是路径 (绝对路径 / 相对路径)

-l:跟的是静态库名字.


3、LIBS关键字的位置的摆放



4、静态库的后缀名

-llibmysql.lib 应该改写为 -llibmysql


5、究极错误 之 我的64位Mysql

这是我所遇到的问题,困扰了我很久才发现,原来我的程序是32位的,而我的Mysql库是64位的!!!

6、C风格接口

如果库已经找到,但是发现提示一些被调用函数未声明或者未实现的错误

请检查函数接口是否已用 extern "C"  修饰

<think>我们首先需要解决用户的问题:在国产系统中使用Qt进行静态编译,并实现在静态编译的程序中运行同目录下的Shell脚本,同时弹窗显示输出信息。 步骤分解: 1. 配置国产系统(如统信UOS、麒麟OS)下的Qt静态编译环境。 2. 编写Qt程序,实现执行同目录下的Shell脚本(注意静态编译后程序路径的处理)。 3. 捕获脚本输出,通过弹窗(QMessageBox)显示输出信息。 注意:静态编译时,需要将Qt库和依赖的插件都静态编译进去,同时确保程序在国产系统上能够运行。 ## 一、国产系统下Qt静态编译环境配置 在国产系统中配置Qt静态编译环境需要以下步骤: ### 1.1 安装必要的编译工具 ```bash sudo apt update sudo apt install build-essential g++ make cmake ``` ### 1.2 下载Qt源码 前往[Qt官网](https://download.qt.io/)下载Qt的源码包(如5.15.2版本): ```bash wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz tar xvf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.2 ``` ### 1.3 配置静态编译选项 在配置时,需要指定静态编译,并关闭一些不需要的模块以减小体积: ```bash ./configure -static -release -prefix /opt/Qt-static-5.15.2 \ -skip webengine -nomake tools -nomake examples -nomake tests \ -qt-xcb # 国产系统通常使用X11,需要xcb支持 ``` 注意:国产系统可能还需要安装一些依赖库,例如: ```bash sudo apt install libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxkbcommon-dev libxkbcommon-x11-dev ``` ### 1.4 编译并安装 ```bash make -j$(nproc) sudo make install ``` ### 1.5 配置环境变量 安装完成后,将静态Qt的路径添加到环境变量: ```bash echo "export PATH=/opt/Qt-static-5.15.2/bin:\$PATH" >> ~/.bashrc source ~/.bashrc ``` ## 二、创建Qt静态项目并实现脚本执行功能 ### 2.1 创建项目 使用Qt Creator创建新项目,选择Qt Widgets Application。 ### 2.2 修改项目文件(.pro)以进行静态编译 在.pro文件中添加: ```qmake # 使用静态编译 CONFIG += static # 禁止动态链接 QTPLUGIN += qjpeg qgif # 根据实际需要添加插件,这里以图片插件为例 # 添加静态编译标志 DEFINES += QT_STATICPLUGIN # 引入静态插件(需要根据实际编译的插件调整) STATICPLUGINS += qjpeg STATICPLUGINS += qgif ``` ### 2.3 编写代码执行Shell脚本并弹窗显示输出 这里我们使用QProcess来执行脚本,并捕获输出。由于是静态编译,程序运行时的当前目录就是可执行文件所在目录,因此可以直接使用相对路径。 注意:在静态编译的程序中,使用QCoreApplication::applicationDirPath()获取程序所在目录,然后拼接脚本路径。 主要代码(与之前类似,但注意静态编译下路径处理): **mainwindow.h** ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QProcess> #include <QMessageBox> #include <QTextEdit> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void executeScript(); void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadyRead(); private: QProcess *m_process; QString m_output; }; #endif // MAINWINDOW_H ``` **mainwindow.cpp** ```cpp #include "mainwindow.h" #include <QVBoxLayout> #include <QPushButton> #include <QApplication> #include <QDir> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_process(new QProcess(this)) { QPushButton *button = new QPushButton("执行脚本", this); setCentralWidget(button); connect(button, &QPushButton::clicked, this, &MainWindow::executeScript); connect(m_process, &QProcess::readyRead, this, &MainWindow::onReadyRead); connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &MainWindow::onProcessFinished); } MainWindow::~MainWindow() { } void MainWindow::executeScript() { // 获取当前程序所在目录 QString appDir = QCoreApplication::applicationDirPath(); // 脚本放在同目录下的scripts文件夹中 QString scriptPath = appDir + "/scripts/my_script.sh"; // 检查脚本是否存在 if (!QFile::exists(scriptPath)) { QMessageBox::critical(this, "错误", "脚本文件不存在: " + scriptPath); return; } // 设置执行权限(可选,确保有权限) QFile::setPermissions(scriptPath, QFile::ExeUser | QFile::ReadUser | QFile::WriteUser); m_output.clear(); // 清空之前的输出 // 启动脚本,使用bash执行 m_process->start("bash", QStringList() << scriptPath); } void MainWindow::onReadyRead() { // 读取标准输出和标准错误 m_output += m_process->readAllStandardOutput(); m_output += m_process->readAllStandardError(); } void MainWindow::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus) // 创建弹窗 QMessageBox msgBox; msgBox.setWindowTitle("脚本执行结果"); if (exitCode == 0) { msgBox.setText("执行成功!"); } else { msgBox.setText(QString("执行失败,退出码:%1").arg(exitCode)); } // 创建可滚动的文本区域 QTextEdit *textEdit = new QTextEdit; textEdit->setPlainText(m_output); textEdit->setReadOnly(true); textEdit->setMinimumSize(400, 300); // 将文本区域添加到布局 QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(textEdit); // 创建一个widget作为msgBox的自定义内容 QWidget *widget = new QWidget; widget->setLayout(layout); // 将widget添加到消息框 msgBox.layout()->addWidget(widget, 0, 0, 1, msgBox.layout()->columnCount()); msgBox.exec(); } ``` **main.cpp** ```cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } ``` ### 2.4 部署脚本 在程序同目录下创建scripts文件夹,并将脚本my_script.sh放入其中。注意在程序运行前确保脚本有可执行权限(可在程序启动时设置,也可手动设置)。 ### 2.5 静态编译项目 在Qt Creator中,选择我们配置的静态Qt套件(如Qt 5.15.2 Static)进行编译。 或者使用命令行: ```bash qmake make ``` 编译完成后,生成的可执行文件可以独立运行(不依赖系统Qt库)。 ## 三、注意事项 1. **脚本路径问题**:静态编译的程序在运行时,当前目录就是可执行文件所在目录,因此使用相对路径`scripts/my_script.sh`即可。 2. **脚本执行环境**:国产系统可能默认的shell不是bash,因此显式使用`bash`来执行脚本。 3. **静态编译体积**:静态编译后的可执行文件体积较大,可以通过去除不必要的模块来减小体积。 4. **国产系统兼容性**:在统信UOS、麒麟OS等国产系统上测试静态编译的程序,确保依赖的系统库(如glibc)版本兼容。 5. **弹窗显示大量文本**:使用`QTextEdit`作为消息框的内容,可以滚动查看大量输出。 6. **中文显示**:确保程序支持中文,可以在main函数中设置编码: ```cpp #include <QTextCodec> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 设置中文编码 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(codec); // ... } ``` 7. **静态编译插件问题**:如果程序中使用了图片(如png、jpeg)等,需要将对应的插件静态编译并链接到程序中,否则无法加载图片。在.pro文件中添加了静态插件的引入。 ## 四、测试 1. 在国产系统上运行编译后的程序,点击按钮执行脚本。 2. 观察弹窗中是否显示脚本输出。 通过以上步骤,我们实现了在国产系统中使用Qt静态编译,并运行同目录下的Shell脚本,同时弹窗显示输出信息。 §§相关问题§§ 1. 如何减小Qt静态编译生成的可执行文件体积? 2. 静态编译的Qt程序在国产系统上运行时出现依赖库问题如何解决? 3. 如何在Qt静态编译中集成第三方库? 4. 如何确保Qt静态编译的程序在多种国产系统上兼容运行?</think># 国产系统Qt静态编译与Shell脚本执行方案 ## 静态编译环境配置(国产系统) ### 1. 安装编译依赖 ```bash # 安装基本编译工具 sudo apt install build-essential g++ make cmake # 安装Qt5静态编译依赖 sudo apt install libgl1-mesa-dev libxcb-xinerama0-dev libxkbcommon-dev \ libxkbcommon-x11-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev \ libxcb-render-util0-dev libxcb-xfixes0-dev libxcb-xkb-dev libxcb-util-dev ``` ### 2. 下载Qt源码 ```bash wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz tar xvf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.2 ``` ### 3. 配置静态编译选项 ```bash ./configure -static -release -prefix /opt/Qt-static-5.15.2 \ -skip webengine -nomake tools -nomake examples -nomake tests \ -qt-xcb # 国产系统使用X11需要此选项 ``` ### 4. 编译与安装 ```bash make -j$(nproc) sudo make install ``` ### 5. 设置环境变量 ```bash echo "export PATH=/opt/Qt-static-5.15.2/bin:\$PATH" >> ~/.bashrc source ~/.bashrc ``` ## Qt程序实现Shell脚本执行与弹窗输出 ### 核心代码实现 **mainwindow.h** ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QProcess> #include <QMessageBox> #include <QTextEdit> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void executeScript(); void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadyRead(); private: QProcess *m_process; QString m_output; QString getScriptPath() const; }; #endif ``` **mainwindow.cpp** ```cpp #include "mainwindow.h" #include <QVBoxLayout> #include <QPushButton> #include <QApplication> #include <QDir> #include <QFileInfo> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_process(new QProcess(this)) { QPushButton *button = new QPushButton("执行脚本", this); setCentralWidget(button); connect(button, &QPushButton::clicked, this, &MainWindow::executeScript); connect(m_process, &QProcess::readyRead, this, &MainWindow::onReadyRead); connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &MainWindow::onProcessFinished); } QString MainWindow::getScriptPath() const { // 获取当前程序所在目录 QString appDir = QCoreApplication::applicationDirPath(); // 国产系统路径兼容处理 QString scriptPath = QDir::toNativeSeparators(appDir + "/my_script.sh"); // 检查脚本是否存在 if (!QFile::exists(scriptPath)) { QMessageBox::critical(this, "错误", "脚本文件不存在: " + scriptPath); return ""; } // 设置执行权限 QFile::setPermissions(scriptPath, QFile::ExeUser | QFile::ReadUser | QFile::WriteUser); return scriptPath; } void MainWindow::executeScript() { QString scriptPath = getScriptPath(); if (scriptPath.isEmpty()) return; m_output.clear(); // 清空之前的输出 // 设置中文环境(国产系统兼容) QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("LANG", "zh_CN.UTF-8"); env.insert("LC_ALL", "zh_CN.UTF-8"); m_process->setProcessEnvironment(env); // 执行脚本(使用bash确保兼容性) m_process->start("bash", QStringList() << scriptPath); } void MainWindow::onReadyRead() { // 读取标准输出和标准错误 m_output += m_process->readAllStandardOutput(); m_output += m_process->readAllStandardError(); } void MainWindow::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus) // 创建弹窗 QMessageBox msgBox; msgBox.setWindowTitle("脚本执行结果"); if (exitCode == 0) { msgBox.setIcon(QMessageBox::Information); msgBox.setText("脚本执行成功 ✅"); } else { msgBox.setIcon(QMessageBox::Critical); msgBox.setText("脚本执行失败 ❌ (退出码: " + QString::number(exitCode) + ")"); } // 创建可滚动的文本区域 QTextEdit *textEdit = new QTextEdit; textEdit->setPlainText(m_output); textEdit->setReadOnly(true); textEdit->setMinimumSize(600, 300); // 添加到弹窗 QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(textEdit); QWidget *widget = new QWidget; widget->setLayout(layout); msgBox.layout()->addWidget(widget, 0, 0, 1, msgBox.layout()->columnCount()); msgBox.exec(); } ``` ### 示例Shell脚本 (my_script.sh) ```bash #!/bin/bash echo "===== 系统信息 =====" echo "操作系统: $(lsb_release -d | cut -f2)" echo "内核版本: $(uname -r)" echo "CPU架构: $(uname -m)" echo "当前用户: $USER" echo "当前时间: $(date)" echo "" echo "===== 内存使用 =====" free -h echo "" echo "===== 磁盘空间 =====" df -h | grep -v tmpfs ``` ## 静态编译与部署 ### 1. 项目配置 (.pro文件) ```qmake # 使用静态编译 CONFIG += static # 禁止动态链接 QTPLUGIN += qjpeg qgif # 添加必要的静态插件 # 添加静态编译标志 DEFINES += QT_STATICPLUGIN # 引入静态插件 STATICPLUGINS += qjpeg STATICPLUGINS += qgif # 源文件 SOURCES += main.cpp \ mainwindow.cpp HEADERS += mainwindow.h FORMS += ``` ### 2. 编译与打包 ```bash # 生成Makefile qmake # 编译项目 make # 检查依赖 ldd ./YourAppName | grep "not found" # 应该无输出 # 打包部署 mkdir -p deploy/scripts cp YourAppName deploy/ cp my_script.sh deploy/scripts/ ``` ## 关键注意事项 1. **国产系统兼容性**: - 使用`QDir::toNativeSeparators()`处理路径分隔符差异 - 显式设置中文环境变量`LANG`和`LC_ALL` - 使用`bash`作为解释器确保脚本兼容性 2. **静态编译优化**: - 通过`-skip`选项排除不需要的模块减小体积 - 使用`-nomake`跳过示例和测试代码 - 只链接必要的静态插件 3. **安全增强**: ```cpp // 防止路径遍历攻击 if (scriptPath.contains("..") || !QFileInfo(scriptPath).canonicalPath().startsWith(appDir)) { QMessageBox::critical(this, "安全错误", "无效的脚本路径"); return ""; } ``` 4. **国产系统部署**: - 在x86和ARM架构上分别测试 - 检查系统glibc版本兼容性 - 使用`patchelf`修复二进制文件中的rpath(如果需要) ## 静态编译优化技巧 $$ \text{优化体积} = \text{排除模块} + \text{编译器选项} + \text{链接时优化} $$ 1. 配置时排除模块: ```bash ./configure -static -release ... -skip qtwebengine -skip qtmultimedia -skip qtsensors ``` 2. 添加编译器优化选项: ```qmake # 在.pro文件中添加 QMAKE_CXXFLAGS += -Os -flto QMAKE_LFLAGS += -Os -flto ``` 3. 使用UPX压缩可执行文件: ```bash upx --best --lzma ./YourAppName ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值