1 需求描述
- 軟件能夠編譯c/c++源代碼;
- 軟件內部實現編譯功能,無需安裝其它開發工具。
2 思考路線
2.1 如何實現?
最開始的時候其實軟件也是支持編譯功能的,只是藉助了Visual Studio開發工具中的編譯器,這樣用戶在安裝軟件後還要安裝Visual Studio纔行,如此一來顯得特別麻煩。後來想着把Visual Studio中的編譯功能集成到軟件中,但是發現可行性並不高。
那,有沒有一種簡單可行的辦法,讓軟件不安裝Visual Studio也能夠編譯代碼?答案是肯定,使用MinGW編譯套件即可實現集成編譯功能。
MinGW,是Minimalist GNUfor Windows的縮寫。它是一個可自由使用和自由發佈的Windows特定頭文件和使用GNU工具集導入庫的集合,允許你在GNU/Linux和Windows平臺生成本地的Windows程序而不需要第三方C運行時(C Runtime)庫。
2.2 如何獲取MinGW編譯套件?
其實,在安裝Qt的時候只要勾選了MinGW組件就能獲取到套件,如下:
ok,安裝完成後套件就獲取到套件了。
套件路徑示例:D:\Program\Qt\Qt5.12.6\Tools\mingw730_32
2.3 如何集成?
獲取到套件後集成就很簡單了,在Qt可執行程序目錄下創建一個Tools目錄(名字自擬),將mingw730_32中的內容全部複製進去即可。
3 代碼實現
3.1 套件獲取到了如何編譯?
完成上述步驟後,接下來就是寫代碼了,這裏使用QProcess調用腳本的方式進行編譯,編譯過程信息可通過信號槽獲取,然後顯示到界面上,是不是感覺很專業。
void CompileUtil::startCompilation(const QString &buildPath)
{
m_buildPath = buildPath;
//清空構建目錄下可執行程序
clearFiles("exe");
//創建構建腳本
QFileInfo batInfo(QDir(buildPath), "build.bat");
QFile file(batInfo.absoluteFilePath());
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
out << QString("set PATH=%1\\Tools\\bin;%PATH%").arg(QDir::toNativeSeparators(QApplication::applicationDirPath())) << endl;
out << QString(QString("cd /D %1").arg(QDir::toNativeSeparators(buildPath))) << endl;
out << QString("g++ *.cpp --verbose -o %1 -lwsock32").arg(OUTPUT_PROCESS_NAME) << endl;
file.close();
//執行構建腳本
m_process.setWorkingDirectory(buildPath);
m_process.setProcessChannelMode(QProcess::MergedChannels);
m_process.start(batInfo.absoluteFilePath());
}
3.2 編譯完成後獲取可執行文件
順利的話,編譯完成後會在源碼路徑生成exe可執行程序,這時便可獲取到它了。
QString CompileUtil::getExecuteFile()
{
QDir dir(m_buildPath);
QFileInfoList infoList = dir.entryInfoList(QDir::Files);
foreach (QFileInfo info, infoList) {
if ("exe" == info.suffix().toLower()) {
return info.absoluteFilePath();
}
}
return QString();
}
3.3 複製可執行文件依賴的dll庫
此時,生成的可執行程序還不能直接執行,它依賴一些動態庫,現在把相關動態庫複製到可執行文件目錄下。
void CompileUtil::copyDependentDllFiles()
{
QDir sourceDir(QApplication::applicationDirPath() + "/Tools/bin");
QDir destDir(m_buildPath);
QStringList destList;
QStringList sourceList;
QFileInfoList infoList = sourceDir.entryInfoList(QDir::Files);
foreach (QFileInfo info, infoList) {
if ("dll" == info.suffix().toLower()) {
sourceList.append(info.absoluteFilePath());
}
}
infoList = destDir.entryInfoList(QDir::Files);
foreach (QFileInfo info, infoList) {
if ("dll" == info.suffix().toLower()) {
destList.append(info.absoluteFilePath());
}
}
foreach (QString fileName, sourceList) {
if (!destList.contains(fileName)) {
QFileInfo sourceInfo(fileName);
QFileInfo destInfo(m_buildPath, sourceInfo.fileName());
QFile file(fileName);
file.copy(destInfo.absoluteFilePath());
}
}
}
這裏處理比較簡單,直接把/Tools/bin目錄下所有的dll複製過來,簡單且有效。
到此,通過集成的MinGW套件編譯的可執行程序就可以正常執行了。
4 總結
讓Qt應用程序集成編譯功能步驟如下:
- 集成MinGW編譯套件,其實就是一個目錄;
- 編寫並調用編譯腳本;
- 複製依賴的dll文件。
強烈建議MinGW位數和Qt應用程序位數保持一致。