qt creator源碼全方面分析(3-6)


qtcreatorplugin.pri

上一節我們介紹了qtcreatorlibrary.pri,現在我們介紹qtcreatorplugin.pri,其實插件的本質也是動態庫,所以qtcreatorplugin.pri實現的內容和功能與qtcreatorlibrary.pri差不多。

使用實例

和上一節一樣,為了分析這個文件,我們也再找個使用該pri的例子,源目錄\src\plugins\cppeditor\cppeditor.pro。

DEFINES += CPPEDITOR_LIBRARY
include(../../qtcreatorplugin.pri)
...

以及依賴項,源目錄\src\libs\cplusplus\cppeditor_dependencies.pri。

QTC_PLUGIN_NAME = CppEditor
QTC_LIB_DEPENDS += \
    extensionsystem \
    utils \
    cplusplus
QTC_PLUGIN_DEPENDS += \
    texteditor \
    coreplugin \
    cpptools \
    projectexplorer
QTC_TEST_DEPENDS += \
    qmakeprojectmanager

這里我們也可以看見,設置了插件名QTC_PLUGIN_NAME,依賴的庫名QTC_LIB_DEPENDS和依賴的插件名QTC_PLUGIN_DEPENDS,這在qtcreator.pri中解析依賴時會用到的。

上半部

depfile = $$replace(_PRO_FILE_PWD_, ([^/]+$), \\1/\\1_dependencies.pri)
exists($$depfile) {
    include($$depfile)
    isEmpty(QTC_PLUGIN_NAME): \
        error("$$basename(depfile) does not define QTC_PLUGIN_NAME.")
} else {
    isEmpty(QTC_PLUGIN_NAME): \
        error("QTC_PLUGIN_NAME is empty. Maybe you meant to create $$basename(depfile)?")
}
TARGET = $$QTC_PLUGIN_NAME

plugin_deps = $$QTC_PLUGIN_DEPENDS
plugin_test_deps = $$QTC_TEST_DEPENDS
plugin_recmds = $$QTC_PLUGIN_RECOMMENDS

include(../qtcreator.pri)

defineReplace(dependencyName) {
    dependencies_file =
    for(dir, QTC_PLUGIN_DIRS) {
        exists($$dir/$$1/$${1}_dependencies.pri) {
            dependencies_file = $$dir/$$1/$${1}_dependencies.pri
            break()
        }
    }
    isEmpty(dependencies_file): \
        error("Plugin dependency $$dep not found")
    include($$dependencies_file)
    return($$QTC_PLUGIN_NAME)
}

# for substitution in the .json
dependencyList =
for(dep, plugin_deps) {
    dependencyList += "        { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\" }"
}
for(dep, plugin_recmds) {
    dependencyList += "        { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\", \"Type\" : \"optional\" }"
}
for(dep, plugin_test_deps) {
    dependencyList += "        { \"Name\" : \"$$dependencyName($$dep)\", \"Version\" : \"$$QTCREATOR_VERSION\", \"Type\" : \"test\" }"
}
dependencyList = $$join(dependencyList, ",$$escape_expand(\\n)")

dependencyList = "\"Dependencies\" : [$$escape_expand(\\n)$$dependencyList$$escape_expand(\\n)    ]"

# use gui precompiled header for plugins by default
isEmpty(PRECOMPILED_HEADER):PRECOMPILED_HEADER = $$PWD/shared/qtcreator_gui_pch.h

isEmpty(USE_USER_DESTDIR) {
    DESTDIR = $$IDE_PLUGIN_PATH
} else {
    win32 {
        DESTDIRAPPNAME = "qtcreator"
        DESTDIRBASE = "$$(LOCALAPPDATA)"
        isEmpty(DESTDIRBASE):DESTDIRBASE="$$(USERPROFILE)\Local Settings\Application Data"
    } else:macx {
        DESTDIRAPPNAME = "Qt Creator"
        DESTDIRBASE = "$$(HOME)/Library/Application Support"
    } else:unix {
        DESTDIRAPPNAME = "qtcreator"
        DESTDIRBASE = "$$(XDG_DATA_HOME)"
        isEmpty(DESTDIRBASE):DESTDIRBASE = "$$(HOME)/.local/share/data"
        else:DESTDIRBASE = "$$DESTDIRBASE/data"
    }
    DESTDIR = "$$DESTDIRBASE/QtProject/$$DESTDIRAPPNAME/plugins/$$QTCREATOR_VERSION"
}
LIBS += -L$$DESTDIR
INCLUDEPATH += $$OUT_PWD

# copy the plugin spec
isEmpty(TARGET) {
    error("qtcreatorplugin.pri: You must provide a TARGET")
}

PLUGINJSON = $$_PRO_FILE_PWD_/$${TARGET}.json
PLUGINJSON_IN = $${PLUGINJSON}.in
exists($$PLUGINJSON_IN) {
    DISTFILES += $$PLUGINJSON_IN
    QMAKE_SUBSTITUTES += $$PLUGINJSON_IN
    PLUGINJSON = $$OUT_PWD/$${TARGET}.json
} else {
    # need to support that for external plugins
    DISTFILES += $$PLUGINJSON
}
  1. 第一部分實現的內容和qtcreatorlibrary.pri中的一樣,

    1. 根據pro文件名獲取對應的依賴文件,進行包含。這里只是多了個文件存在性判斷,以及插件名是否設置判斷。

    2. 設置插件文件名。

    3. 加載qtcreator.pri。

  2. 定義了替換函數dependencyName。

    代碼和qtcreator.pri文件最后的遞歸解決插件依賴幾乎一樣。區別在於這里只分析了當前依賴的插件,而不是繼續遞歸往下。

  3. 實現插件元數據的依賴信息替換。

    我們在Plugin Meta Data已經介紹過Dependencies鍵,示例如下:

    "Dependencies" : [
              { "Name" : "SomeOtherPlugin", "Version" : "2.3.0_2" },
              { "Name" : "EvenOther", "Version" : "1.0.0" }
    ]
    

    這里很明顯,把依賴信息填充到dependencyList對象中。

  4. 添加預編譯頭文件。和qtcreatorlibrary.pri一樣。

  5. 設置目標文件夾,並添加庫和包含路徑。

    win32系統下,有兩個輸出路徑,一個為構建目錄/lib/qtcreator/plugin,一個為用戶路徑,譬如C:/Users/codeForFamily/AppData/Local/QtProject/qtcreator/plugins/4.6.2。我們在Creating Your First Plugin的"部署到列表"中就提到過。

  6. *.json.in編譯為*.json

    獲取插件目錄下的json.in文件。其實就是插件元數據的模板。

    {
        \"Name\" : \"CppEditor\",
        \"Version\" : \"$$QTCREATOR_VERSION\",
        ...
        $$dependencyList
    }
    

    並設置QMAKE_SUBSTITUTES對json.in文件進行變量替換,生成json文件。這種用法我們在qtcreator.pri中已經介紹過。

    {
        "Name" : "CppEditor",
        "Version" : "4.6.2",
        ...
        "Dependencies" : [
            { "Name" : "TextEditor", "Version" : "4.6.2" },
            { "Name" : "Core", "Version" : "4.6.2" },
            { "Name" : "CppTools", "Version" : "4.6.2" },
            { "Name" : "ProjectExplorer", "Version" : "4.6.2" },
            { "Name" : "QmakeProjectManager", "Version" : "4.6.2", "Type" : "test" }
        ]
    }
    

    該json文件最終輸出到OUT_PWD目錄,這也是步驟5中為什么要包含OUT_PWD路徑的原因。

    image-20200305221549795

下半部


osx {
    QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/PlugIns/
    QMAKE_LFLAGS += -compatibility_version $$QTCREATOR_COMPAT_VERSION
}
include(rpath.pri)

contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

TEMPLATE = lib
CONFIG += plugin plugin_with_soname
linux*:QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF

target.path = $$INSTALL_PLUGIN_PATH
INSTALLS += target

TARGET = $$qtLibraryTargetName($$TARGET)

這部分內容和qtcreatorlibrary.pri幾乎一樣。不再介紹。

結果

qtcreatorplugin.pri與qtcreatorlibrary.pri的主要區別,就在於多了生成dependencyList,以及json.in文件轉為json文件這兩部分。


原創造福大家,共享改變世界

獻出一片愛心,溫暖作者心靈



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM