Qt實戰1.如何讓Qt應用程序集成編譯功能?

1 需求描述

  1. 軟件能夠編譯c/c++源代碼;
  2. 軟件內部實現編譯功能,無需安裝其它開發工具。

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應用程序集成編譯功能步驟如下:

  1. 集成MinGW編譯套件,其實就是一個目錄;
  2. 編寫並調用編譯腳本;
  3. 複製依賴的dll文件。

強烈建議MinGW位數和Qt應用程序位數保持一致。

5 下載

相關代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章