15.Qt 和 C++(Qt and C++)
本章的作者:jryannel
** 注意: **
最新的構(gòu)建時(shí)間:2016/03/21
這章的源代碼能夠在assetts folder找到。
Qt 是一個(gè)帶有 QML 和 Javascript 擴(kuò)展的 C++ 工具包皆撩。存在許多針對(duì) Qt 的語(yǔ)言綁定,但是隨著 Qt 在 C++ 中開(kāi)發(fā),C++ 的精神可以在整個(gè)類中找到惫叛。在本節(jié)中昌阿,我們將從 C++ 角度來(lái)看 Qt殖告,以便更好地了解如何使用 C++ 開(kāi)發(fā)的本機(jī)插件擴(kuò)展 QML烘挫。通過(guò) C++祭刚,可以擴(kuò)展和控制提供給 QML 的執(zhí)行環(huán)境。
本章將與 Qt 一樣,要求讀者掌握 C++ 的一些基礎(chǔ)知識(shí)涡驮。Qt 不依賴于高級(jí) C++ 特性,我通常認(rèn)為C++ 的 Qt 風(fēng)格是非常易讀的喜滨,所以如果你覺(jué)得 C++ 的知識(shí)是不穩(wěn)定的話捉捅,別擔(dān)心蝠筑。
從 C++ 方向接近 Qt猴仑,我們會(huì)發(fā)現(xiàn) Qt 通過(guò)使內(nèi)省數(shù)據(jù)可用,豐富了 C++诽里,使其具備了與許多現(xiàn)代語(yǔ)言類似的功能辜膝。這可以通過(guò)使用 QObject 基類來(lái)實(shí)現(xiàn)无牵。內(nèi)省數(shù)據(jù)或元數(shù)據(jù)在運(yùn)行時(shí)維護(hù)類的信息,這是普通 C++ 不做的事情厂抖。這使得可以動(dòng)態(tài)地探測(cè)對(duì)象以獲得關(guān)于這些細(xì)節(jié)的信息茎毁,例如它們的屬性和可用的方法。
Qt 使用這個(gè)元信息來(lái)啟用使信號(hào)和槽的非常松散綁定的回調(diào)概念忱辅。每個(gè)信號(hào)可以連接到任意數(shù)量的槽或甚至任意其他的信號(hào)七蜘。當(dāng)從對(duì)象實(shí)例發(fā)出信號(hào)時(shí),調(diào)用與之連接的槽墙懂。由于信號(hào)發(fā)射對(duì)象不需要知道與之連接的槽的對(duì)象橡卤,反之亦然,因此該機(jī)制用于創(chuàng)建具有非常少的組件間依賴性的可重用的組件非常有用损搬。
內(nèi)省特性也用于創(chuàng)建動(dòng)態(tài)語(yǔ)言的綁定碧库,使得 QML 可以調(diào)用暴露的 C++ 對(duì)象實(shí)例,并且可以從 JavaScript 中調(diào)用 C++ 函數(shù)巧勤。除了綁定 Qt C++, 綁定標(biāo)準(zhǔn)的 JavaScript 也是一種非常流行的方式嵌灰,還有 Python 的綁定,叫做 PyQt踢关。
除了這個(gè)中心概念伞鲫,Qt 還可以使用 C++ 開(kāi)發(fā)跨平臺(tái)應(yīng)用程序。Qt C++ 在不同的操作系統(tǒng)上提供了一個(gè)平臺(tái)抽象签舞,它允許開(kāi)發(fā)人員專注于手頭的任務(wù)秕脓,而不是在不同操作系統(tǒng)上打開(kāi)文件的細(xì)節(jié)。這意味著您可以為 Windows儒搭,OS X 和 Linux 重新編譯相同的源代碼吠架,并且 Qt 負(fù)責(zé)處理某些事情的不同操作系統(tǒng)。最終的結(jié)果是具有目標(biāo)平臺(tái)外觀和感覺(jué)的本地構(gòu)建的應(yīng)用程序搂鲫。由于移動(dòng)設(shè)備是新的桌面傍药,更新的 Qt 版本也可以使用相同的源代碼來(lái)移植到多個(gè)移動(dòng)平臺(tái):iOS,Android,Jolla拐辽,BlackBerry拣挪,Ubuntu Phone,Tizen俱诸。
當(dāng)涉及到重用時(shí)菠劝,不僅可以重新使用源代碼,還可以重用開(kāi)發(fā)人員技能睁搭。知道 Qt 的團(tuán)隊(duì)可以接觸到更多的平臺(tái)赶诊,然后一個(gè)團(tuán)隊(duì)只關(guān)注一個(gè)單一的平臺(tái)特定技術(shù),而 Qt 如此靈活园骆,團(tuán)隊(duì)可以使用相同的技術(shù)創(chuàng)建不同的系統(tǒng)組件舔痪。
對(duì)于所有平臺(tái),Qt 提供了一組基本類型锌唾,例如:具有完整 unicode 支持锄码,列表,向量鸠珠,緩沖區(qū)的字符串巍耗。它還為目標(biāo)平臺(tái)的主循環(huán),跨平臺(tái)線程和網(wǎng)絡(luò)支持提供了一個(gè)共同的抽象渐排。一般的理念是炬太,對(duì)于應(yīng)用程序開(kāi)發(fā)人員,Qt 附帶了所有必需的功能驯耻。對(duì)于特定于領(lǐng)域的任務(wù)亲族,如與本地庫(kù)的接口,Qt 帶有幾個(gè)幫助類可缚,使之更容易霎迫。
15.1 示例程序
理解 Qt 的最好方法是從一個(gè)小的演示應(yīng)用程序開(kāi)始。此應(yīng)用程序創(chuàng)建一個(gè)簡(jiǎn)單的 “Hello World帘靡!” 字符串知给,并使用 unicode 字符將其寫入文件。
#include <QCoreApplication>
#include <QString>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// prepare the message
QString message("Hello World!");
// prepare a file in the users home directory named out.txt
QFile file(QDir::home().absoluteFilePath("out.txt"));
// try to open the file in write mode
if(!file.open(QIODevice::WriteOnly)) {
qWarning() << "Can not open file with write access";
return -1;
}
// as we handle text we need to use proper text codecs
QTextStream stream(&file);
// write message to file via the text stream
stream << message;
// do not start the eventloop as this would wait for external IO
// app.exec();
// no need to close file, closes automatically when scope ends
return 0;
}
簡(jiǎn)單的例子演示文件訪問(wèn)的使用以及使用文本編輯器通過(guò)文本流將文本寫入文件的正確方法描姚。對(duì)于二進(jìn)制數(shù)據(jù)涩赢,有一個(gè)稱為 QDataStream 的跨平臺(tái)二進(jìn)制流。我們使用的不同類需要使用它們的類名包含轩勘。另一種是使用模塊名和類名例如 #include <QtCore/QFile>筒扒。對(duì)于比較懶的人,有一個(gè)更加簡(jiǎn)單的方法是包含整個(gè)模塊绊寻,使用 #include <QtCore>花墩。例如在 QtCore 中你可以在應(yīng)用程序中使用很多通用的類悬秉,這沒(méi)有 UI 依賴。查看 QtCore class list 或者 QtCore overview 獲取更多的信息冰蘑。
我們使用 qmake 和 make 構(gòu)建應(yīng)用程序和泌。QMake 讀取一個(gè)項(xiàng)目文件并生成一個(gè) Makefile,然后可以使用 make 進(jìn)行編譯祠肥。項(xiàng)目文件與平臺(tái)無(wú)關(guān)允跑,qmake 有一些規(guī)則將平臺(tái)特定設(shè)置應(yīng)用于生成的 make 文件。該項(xiàng)目還可以包含平臺(tái)特定規(guī)則的平臺(tái)范圍搪柑,這在特定情況下是必需的。這是一個(gè)簡(jiǎn)單的項(xiàng)目文件的例子索烹。
# build an application
TEMPLATE = app
# use the core module and do not use the gui module
QT += core
QT -= gui
# name of the executable
TARGET = CoreApp
# allow console output
CONFIG += console
# for mac remove the application bundling
macx {
CONFIG -= app_bundle
}
# sources to be build
SOURCES += main.cpp
我們不會(huì)深入這個(gè)話題工碾。只要記住 Qt 使用項(xiàng)目文件進(jìn)行項(xiàng)目管理,并且 qmake 會(huì)從這些項(xiàng)目文件中生成特定于平臺(tái)的 make 文件百姓。
上面的簡(jiǎn)單代碼示例只是寫入文本并退出應(yīng)用程序渊额。對(duì)于命令行工具,這是足夠好的垒拢。對(duì)于用戶界面旬迹,我們需要一個(gè)等待用戶輸入的事件循環(huán),并且以某種方式調(diào)度重新繪制操作求类。所以這里使用同樣的例子奔垦,但是現(xiàn)在使用桌面按鈕來(lái)觸發(fā)寫作。
我們的 main.cpp 令人驚訝地變小了尸疆。我們將代碼移動(dòng)到自定義的類中椿猎,以便能夠使用用戶輸入的信號(hào)/槽,例如寿弱。按鈕點(diǎn)擊犯眠。信號(hào)/插槽機(jī)制通常需要一個(gè)對(duì)象實(shí)例,我們將很快看到症革。
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#include "mainwindow.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MainWindow win;
win.resize(320, 240);
win.setVisible(true);
return app.exec();
}
在 main 函數(shù)中筐咧,我們簡(jiǎn)單地創(chuàng)建應(yīng)用程序?qū)ο螅⑹褂?exec() 啟動(dòng)事件循環(huán)≡朊現(xiàn)在應(yīng)用程序位于事件循環(huán)中量蕊,并等待用戶輸入。
int main(int argc, char** argv)
{
QApplication app(argc, argv); // init application
// create the ui
return app.exec(); // execute event loop
}
Qt 提供多種 UI 技術(shù)摩疑。對(duì)于這個(gè)例子危融,我們使用純粹的 Qt C ++ 的 Desktop Widgets 用戶界面庫(kù)。我們創(chuàng)建一個(gè)主窗口雷袋,該窗口將包含一個(gè)按鈕用來(lái)觸發(fā)功能吉殃,主窗口還將呈現(xiàn)我們從上一個(gè)例子中知道的核心功能辞居。
主窗口本身是一個(gè)小部件。它成為頂級(jí)窗口蛋勺,因?yàn)樗鼪](méi)有任何父級(jí)瓦灶。這來(lái)自于 Qt 將用戶界面看作是一個(gè) ui 元素的樹(shù)。在這種情況下抱完,主窗口是根元素贼陶,因此成為窗口,而按鈕是主窗口的子窗口巧娱,并在窗口中成為窗口小部件碉怔。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets>
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget* parent=0);
~MainWindow();
public slots:
void storeContent();
private:
QPushButton *m_button;
};
#endif // MAINWINDOW_H
另外我們定義一個(gè)名為 storeContent() 的公共槽,當(dāng)這個(gè)按鈕被點(diǎn)擊時(shí)禁添,它將被調(diào)用撮胧。一個(gè)槽是一個(gè) C++ 方法,它被注冊(cè)到 Qt 元對(duì)象系統(tǒng)中老翘,可以被動(dòng)態(tài)調(diào)用芹啥。
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_button = new QPushButton("Store Content", this);
setCentralWidget(m_button);
connect(m_button, &QPushButton::clicked, this, &MainWindow::storeContent);
}
MainWindow::~MainWindow()
{
}
void MainWindow::storeContent()
{
qDebug() << "... store content";
QString message("Hello World!");
QFile file(QDir::home().absoluteFilePath("out.txt"));
if(!file.open(QIODevice::WriteOnly)) {
qWarning() << "Can not open file with write access";
return;
}
QTextStream stream(&file);
stream << message;
}
在主窗口中,我們首先創(chuàng)建按鈕铺峭,然后使用 connect 方法將槽 storeContent() 和 clicked() 進(jìn)行連接墓怀。每次當(dāng)發(fā)出點(diǎn)擊信號(hào)時(shí),都會(huì)調(diào)用槽 storeContent()卫键。這樣很簡(jiǎn)單傀履,對(duì)象通過(guò)信號(hào)和槽實(shí)現(xiàn)了松耦合的通信。
15.2 QObject
如引言所述永罚,QObject 是 Qt 內(nèi)省的內(nèi)容啤呼。它是 Qt 幾乎所有類的基類。沒(méi)有繼承自 QObject 的是一些值類型呢袱,如 QColor官扣,QString 和 QList 等。
Qt 對(duì)象是一個(gè)標(biāo)準(zhǔn)的 C++ 對(duì)象羞福,但具有更多的能力惕蹄。這些可以分為兩組:內(nèi)省和內(nèi)存管理。第一個(gè)意思是 Qt 對(duì)象知道它的類名治专,它與其他類的關(guān)系卖陵,以及它的方法和屬性。內(nèi)存管理概念意味著每個(gè) Qt 對(duì)象都可以是子對(duì)象的父對(duì)象张峰。父對(duì)象擁有子對(duì)象泪蔫,當(dāng)父對(duì)象被銷毀時(shí),會(huì)負(fù)責(zé)銷毀子對(duì)象喘批。
了解 QObject 能力如何影響類的最佳方法是使用標(biāo)準(zhǔn)的 C++ 類撩荣,并啟用 Qt铣揉。下面所示的類代表普通的類。
person 類是具有名稱和性別屬性的數(shù)據(jù)類餐曹。person 類使用 Qt 的對(duì)象系統(tǒng)向 c++ 類添加元信息逛拱。它允許 person 對(duì)象的用戶連接到插槽,并在屬性更改時(shí)收到通知台猴。
class Person : public QObject
{
Q_OBJECT // enabled meta object abilities
// property declarations required for QML
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(Gender gender READ gender WRITE setGender NOTIFY genderChanged)
// enables enum introspections
Q_ENUMS(Gender)
public:
// standard Qt constructor with parent for memory management
Person(QObject *parent = 0);
enum Gender { Unknown, Male, Female, Other };
QString name() const;
Gender gender() const;
public slots: // slots can be connected to signals
void setName(const QString &);
void setGender(Gender);
signals: // signals can be emitted
void nameChanged(const QString &name);
void genderChanged(Gender gender);
private:
// data members
QString m_name;
Gender m_gender;
};
構(gòu)造函數(shù)將父類傳遞給超類并初始化成員朽合。Qt 的值類被自動(dòng)初始化。在這種情況下饱狂,QString 將初始化為一個(gè)空字符串(QString::isNull())曹步,性別成員將顯式地初始化為未知性別。
Person::Person(QObject *parent)
: QObject(parent)
, m_gender(Person::Unknown)
{
}
getter 函數(shù)以該屬性命名休讳,通常是一個(gè)簡(jiǎn)單的 const 函數(shù)箭窜。當(dāng)屬性真的改變時(shí),setter 發(fā)出改變的信號(hào)衍腥。為此,我們插入一個(gè)警衛(wèi)來(lái)將當(dāng)前值與新值進(jìn)行比較纳猫。只有當(dāng)值不同的時(shí)候婆咸,我們把它分配給成員變量并發(fā)出改變的信號(hào)。
QString Person::name() const
{
return m_name;
}
void Person::setName(const QString &name)
{
if (m_name != name) // guard
{
m_name = name;
emit nameChanged(m_name);
}
}
通過(guò)定義一個(gè)派生自 QObject 的類芜辕,我們獲得了更多的元對(duì)象能力尚骄,我們可以使用 metaObject() 方法來(lái)探索。例如從對(duì)象檢索類名侵续。
Person* person = new Person();
person->metaObject()->className(); // "Person"
Person::staticMetaObject.className(); // "Person"
還有更多的功能可以被 QObject 基類和元對(duì)象訪問(wèn)倔丈。請(qǐng)查看 QMetaObject 文檔。
15.3 構(gòu)建系統(tǒng)
在不同的平臺(tái)上穩(wěn)定的編譯軟件是一個(gè)復(fù)雜的任務(wù)状蜗。你將會(huì)遇到不同環(huán)境下的不同編譯器需五,路徑和庫(kù)變量的問(wèn)題。Qt 的目的是防止應(yīng)用開(kāi)發(fā)者遭遇這些跨平臺(tái)問(wèn)題轧坎。為了完成這個(gè)任務(wù)宏邮,Qt 引進(jìn)了 qmake 編譯文件生成器。qmake 操作以 .pro 結(jié)尾的項(xiàng)目文件缸血。這個(gè)項(xiàng)目文件包含了關(guān)于應(yīng)用程序的說(shuō)明和需要讀取的資源文件蜜氨。用 qmake 執(zhí)行這個(gè)項(xiàng)目文件會(huì)為你生成一個(gè)在 unix 和 mac 的 Makefile,如果在 windows 下使用 mingw 編譯工具鏈也會(huì)生成捎泻。否則可能會(huì)創(chuàng)建一個(gè) visual studio 項(xiàng)目或者一個(gè) xcode 項(xiàng)目飒炎。
在 unix 下,Qt 中的典型構(gòu)建流程將是:
$ edit myproject.pro
$ qmake // generates Makefile
$ make
Qt 還允許您使用影子構(gòu)建笆豁。影子構(gòu)建是源代碼位置之外的構(gòu)建郎汪。假設(shè)我們有一個(gè)帶有 myproject.pro 文件的 myproject 文件夾赤赊。流程將如下所示:
$ mkdir build
$ cd build
$ qmake ../myproject/myproject.pro
我們創(chuàng)建一個(gè)構(gòu)建文件夾,然后使用我們的項(xiàng)目文件夾的位置從構(gòu)建文件夾內(nèi)部調(diào)用 qmake怒竿。這將以所有構(gòu)建工件存儲(chǔ)在構(gòu)建文件夾而不是我們的源代碼文件夾內(nèi)的方式設(shè)置 make 文件砍鸠。這允許我們?yōu)椴煌?qt 版本創(chuàng)建構(gòu)建,同時(shí)構(gòu)建配置耕驰,并且它不會(huì)使我們的代碼文件夾變得混亂爷辱,這是一件好事。
當(dāng)我們使用 Qt Creator 時(shí)朦肘,它會(huì)為我們?cè)谀缓髨?zhí)行這些操作饭弓,而我們通常不用關(guān)心這些步驟。對(duì)于較大的項(xiàng)目和想要了解構(gòu)建流程時(shí)媒抠,建議我們從命令行學(xué)習(xí)構(gòu)建我們的 qt 項(xiàng)目弟断。
15.3.1 QMake
QMake 讀取我們的項(xiàng)目文件并生成構(gòu)建文件的工具。項(xiàng)目文件是對(duì)項(xiàng)目的配置趴生,外部依賴關(guān)系和源文件的簡(jiǎn)化記錄阀趴。最簡(jiǎn)單的項(xiàng)目文件可能是這樣的:
// myproject.pro
SOURCES += main.cpp
在這里,我們構(gòu)建一個(gè)可執(zhí)行的應(yīng)用程序苍匆,它將基于項(xiàng)目文件名稱命名為 myproject刘急。該構(gòu)建將僅包含 main.cpp 源文件。默認(rèn)情況下浸踩,我們將使用該項(xiàng)目的 QtCore 和 QtGui 模塊叔汁。如果我們的項(xiàng)目是 QML 應(yīng)用程序,我們需要將 QtQuick 和 QtQml 模塊添加到列表中:
// myproject.pro
QT += qml quick
SOURCES += main.cpp
現(xiàn)在检碗,構(gòu)建文件知道與 QtQml 和 QtQuick Qt 模塊鏈接据块。QMake 使用 =,+= 和 -= 的概念分別從選項(xiàng)列表中分配折剃,添加另假,刪除元素。對(duì)于沒(méi)有 UI 依賴關(guān)系的純控制臺(tái)構(gòu)建怕犁,您將刪除 QtGui 模塊:
// myproject.pro
QT -= gui
SOURCES += main.cpp
當(dāng)我們要構(gòu)建庫(kù)而不是應(yīng)用程序時(shí)浪谴,我們需要更改構(gòu)建模板:
// myproject.pro
TEMPLATE = lib
QT -= gui
HEADERS += utils.h
SOURCES += utils.cpp
現(xiàn)在,該項(xiàng)目將構(gòu)建為沒(méi)有 UI 依賴性的庫(kù)因苹,并使用 utils.h 頭文件和 utils.cpp 源文件苟耻。庫(kù)的格式將取決于我們正在構(gòu)建項(xiàng)目的操作系統(tǒng)。
通常我們會(huì)有更復(fù)雜的設(shè)置扶檐,需要建立一套項(xiàng)目凶杖。為此,qmake 提供了 subdirs 模板款筑。假設(shè)我們將有一個(gè) mylib 和一個(gè) myapp 項(xiàng)目智蝠。那么我們的設(shè)置可能是這樣的:
my.pro
mylib/mylib.pro
mylib/utils.h
mylib/utils.cpp
myapp/myapp.pro
myapp/main.cpp
我們已經(jīng)知道 mylib.pro 和 myapp.pro 的外觀如何腾么。my.pro 作為總體項(xiàng)目文件將如下所示:
// my.pro
TEMPLATE = subdirs
subdirs = mylib \
myapp
myapp.depends = mylib
這個(gè)項(xiàng)目有兩個(gè)子項(xiàng)目:mylib 和 myapp,其中 myapp 依賴于 mylib杈湾。當(dāng)我們?cè)诖隧?xiàng)目文件上運(yùn)行 qmake 時(shí)解虱,它會(huì)為相應(yīng)文件夾中的每個(gè)項(xiàng)目生成文件一個(gè)構(gòu)建文件。當(dāng)我們運(yùn)行 my.pro 的 make 文件時(shí)漆撞,還會(huì)構(gòu)建所有子項(xiàng)目殴泰。
有時(shí)我們需要根據(jù)我們的配置在一個(gè)平臺(tái)上做一件事,另外還要做其他平臺(tái)上的一件事情浮驳。因?yàn)檫@個(gè) qmake 引入了范圍的概念悍汛。當(dāng)配置選項(xiàng)設(shè)置為 true 時(shí),應(yīng)用范圍至会。
例如离咐,使用可以使用的 unix 下特定的 utils 實(shí)現(xiàn):
unix {
SOURCES += utils_unix.cpp
} else {
SOURCES += utils.cpp
}
它說(shuō)的是如果 CONFIG 變量包含一個(gè) unix 選項(xiàng),然后應(yīng)用此范圍奉件,否則使用 else 路徑宵蛀。一個(gè)典型的應(yīng)用是刪除 mac 下的應(yīng)用捆綁:
macx {
CONFIG -= app_bundle
}
這將創(chuàng)建我們的應(yīng)用程序作為一個(gè)普通的可執(zhí)行文件,而不是 mac 應(yīng)用程序安裝的 .app 文件夾县貌。
當(dāng)我們開(kāi)始編寫 Qt 應(yīng)用程序時(shí)糖埋,基于 QMake 的項(xiàng)目通常是第一選擇。還有其他的選擇窃这。都有自己的好處和缺點(diǎn)。接下來(lái)我們將再討論這些其他選項(xiàng)征候。
** 參考 **
- QMake Manual —— qmake 手冊(cè)的目錄
- QMake Language —— 價(jià)分配杭攻,范圍等等
- QMake Variables —— 對(duì) TEMPLATE、CONFIG疤坝、QT 等變量進(jìn)行說(shuō)明
15.3.2 CMake
CMake 是 Kitware 創(chuàng)建的工具兆解。Kitware 以其 3D 視覺(jué)軟件 VTK 以及跨平臺(tái) makefile 生成器 CMake 而聞名。它使用一系列 CMakeLists.txt 文件來(lái)生成平臺(tái)特定的 make 文件跑揉。CMake 由 KDE 項(xiàng)目使用锅睛,因此與 Qt 社區(qū)有特殊關(guān)系。
CMakeLists.txt 是用于存儲(chǔ)項(xiàng)目配置的文件历谍。對(duì)于使用 QtCore 的簡(jiǎn)單的示例现拒,項(xiàng)目文件將如下所示:
// ensure cmake version is at least 3.0
cmake_minimum_required(VERSION 3.0)
// adds the source and build location to the include path
set(CMAKE_INCLUDE_CURRENT_DIR ON)
// Qt's MOC tool shall be automatically invoked
set(CMAKE_AUTOMOC ON)
// using the Qt5Core module
find_package(Qt5Core)
// create excutable helloworld using main.cpp
add_executable(helloworld main.cpp)
// helloworld links against Qt5Core
target_link_libraries(helloworld Qt5::Core)
這將使用 main.cpp 構(gòu)建一個(gè) helloworld 可執(zhí)行文件,并與外部 Qt5Core 庫(kù)鏈接望侈。構(gòu)建文件可以修改為更通用:
// sets the PROJECT_NAME variable
project(helloworld)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt5Core)
// creates a SRC_LIST variable with main.cpp as single entry
set(SRC_LIST main.cpp)
// add an executable based on the project name and source list
add_executable(${PROJECT_NAME} ${SRC_LIST})
// links Qt5Core to the project executable
target_link_libraries(${PROJECT_NAME} Qt5::Core)
你可以看到印蔬,CMake 相當(dāng)強(qiáng)大。需要一些時(shí)間來(lái)習(xí)慣語(yǔ)法脱衙。一般來(lái)說(shuō)侥猬,據(jù)說(shuō) CMake 更適合大型和復(fù)雜的項(xiàng)目例驹。
** 參考 **
- CMake Help —— 在線可用,也可作為 QtHelp 格式使用
- Running CMake
- KDE CMake Tutorial
- CMake Book
- CMake and Qt