QML Book 第十五章 Qt 和 C++ 1

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)組件舔痪。

yourapplication

對(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è)例子中知道的核心功能辞居。

storecontent

主窗口本身是一個(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)征候。

** 參考 **

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)目例驹。

** 參考 **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末退唠,一起剝皮案震驚了整個(gè)濱河市鹃锈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞧预,老刑警劉巖屎债,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異松蒜,居然都是意外死亡扔茅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門秸苗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)召娜,“玉大人,你說(shuō)我怎么就攤上這事惊楼【寥常” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵檀咙,是天一觀的道長(zhǎng)雅倒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)弧可,這世上最難降的妖魔是什么蔑匣? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮棕诵,結(jié)果婚禮上裁良,老公的妹妹穿的比我還像新娘。我一直安慰自己校套,他們只是感情好价脾,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著笛匙,像睡著了一般侨把。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妹孙,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天秋柄,我揣著相機(jī)與錄音,去河邊找鬼蠢正。 笑死华匾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜘拉,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萨西,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了旭旭?” 一聲冷哼從身側(cè)響起谎脯,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎持寄,沒(méi)想到半個(gè)月后源梭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稍味,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年废麻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模庐。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烛愧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掂碱,到底是詐尸還是另有隱情怜姿,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布疼燥,位于F島的核電站沧卢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏醉者。R本人自食惡果不足惜但狭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撬即。 院中可真熱鬧立磁,春花似錦、人聲如沸搞莺。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)才沧。三九已至,卻和暖如春绍刮,著一層夾襖步出監(jiān)牢的瞬間温圆,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工孩革, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岁歉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像锅移,于是被迫代替她去往敵國(guó)和親熔掺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容